diff --git a/app/screens/HomeScreen.tsx b/app/screens/HomeScreen.tsx index 68f0c7c..14514a9 100644 --- a/app/screens/HomeScreen.tsx +++ b/app/screens/HomeScreen.tsx @@ -535,7 +535,7 @@ const styles = StyleSheet.create({ searchPlaceholder: { flex: 1, marginLeft: 8, - fontSize: 16, + fontSize: fontSize(16), }, cameraButton: { padding: 5, @@ -808,7 +808,7 @@ const styles = StyleSheet.create({ marginTop: 9, }, beautyProductTitle: { - fontSize: 14, + fontSize: fontSize(14), fontWeight: "600", color: "black", lineHeight: 18, @@ -823,25 +823,25 @@ const styles = StyleSheet.create({ }, highlightedText: { fontWeight: "700", - fontSize: 24, + fontSize: fontSize(24), color: "#ff5100", }, highlightedText1: { fontWeight: "700", - fontSize: 14, + fontSize: fontSize(14), color: "#ff5100", }, priceContainer1: { marginLeft: 5.75, }, priceLabel1: { - fontSize: 12, + fontSize: fontSize(12), fontWeight: "600", color: "#9a9a9a", }, beautySalesInfo: { marginTop: 6.75, - fontSize: 14, + fontSize: fontSize(14), fontWeight: "600", color: "#7c7c7c", }, diff --git a/app/screens/LoginScreen.tsx b/app/screens/LoginScreen.tsx index 749f797..e1ae2cf 100644 --- a/app/screens/LoginScreen.tsx +++ b/app/screens/LoginScreen.tsx @@ -27,9 +27,9 @@ import AsyncStorage from "@react-native-async-storage/async-storage"; type RootStackParamList = { Login: undefined; EmailLogin: undefined; - MainTabs: undefined; + MainTabs: { screen: string }; Google: undefined; - Home: undefined; + Home: { screen: string }; }; @@ -353,7 +353,7 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { const res = await userApi.login(params); const token = res.token_type + " " + res.access_token; await AsyncStorage.setItem("token", token); - navigation.navigate("Home"); + navigation.navigate('MainTabs', { screen: 'Home' }); const data = await settingApi.postFirstLogin(221); console.log(data); }; @@ -366,7 +366,7 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { const handlePhoneVerificationSuccess = async () => { await login(); closePhoneLogin(); - navigation.replace('MainTabs'); + navigation.replace('MainTabs', { screen: 'Home' }); }; const handlePhoneContinue = async () => { @@ -374,7 +374,7 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { if (password === '123') { await login(); closePhoneLogin(); - navigation.replace('MainTabs'); + navigation.replace('MainTabs', { screen: 'Home' }); } else { setPasswordError(true); } diff --git a/app/screens/ProductCard.tsx b/app/screens/ProductCard.tsx index 77527d6..e8619e2 100644 --- a/app/screens/ProductCard.tsx +++ b/app/screens/ProductCard.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback } from "react"; +import React, { useEffect, useCallback, useState } from "react"; import { View, Text, @@ -7,11 +7,15 @@ import { TouchableOpacity, ScrollView, Modal, - InteractionManager + InteractionManager, + Alert, + TextInput, } from "react-native"; import widthUtils from "../utils/widthUtils"; import fontSize from "../utils/fontsizeUtils"; import CloseIcon from "../components/CloseIcon"; +import XIconBottom from "../components/XIconBottom"; +import XIconTop from "../components/XIconTop"; import { ProductDetailParams, ProductGroupList, @@ -19,9 +23,11 @@ import { Sku, } from "../services/api/productApi"; import { cartApi } from "../services/api/cart"; -import { useState } from "react"; import { useNavigation } from "@react-navigation/native"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; +import ImageView from "react-native-image-viewing"; +import useProductCartStore from "../store/productCart"; + interface ProductCardProps { onClose: () => void; product: ProductDetailParams; @@ -38,268 +44,52 @@ const ProductCard: React.FC = ({ groupList: ProductGroupList[]; }) => { const navigation = useNavigation>(); - const [groupList, setGroupList] = - useState(localGroupList); - const [product, setProduct] = useState(localProduct); - const [imgTitle, setImgTitle] = useState(""); - const [sizeList, setSizeList] = useState([]); - const [sizeTitle, setSizeTitle] = useState(""); - const [size, setSize] = useState(""); - const [hasImg, setHasImg] = useState(); - const [noImgList, setNoImgList] = useState([]); - const [price, setPrice] = useState(0); - const [selectedSize, setSelectedSize] = useState(0); - const [totalPrice, setTotalPrice] = useState(0); - const [flag, setFlag] = useState(false); const [deleteModalVisible, setDeleteModalVisible] = useState(false); - useEffect(() => { - setPrice(product.price as number); - const imageItem = groupList.filter((item) => item.has_image); - if (imageItem.length > 0) { - setSizeTitle(imageItem[imageItem.length - 1].attribute_name); - imageItem.forEach((item) => { - const colorItem = item.attributes.filter( - (attribute) => attribute.has_color - ); - if (colorItem.length > 0) { - setImgTitle(colorItem[0].sku_image_url); - } - }); - setFlag(true); - } else { - setFlag(false); - } - if (imageItem.length === 0) { - setImgTitle(product.product_image_urls[0]); - } - const sizeItem = groupList.filter((item) => !item.has_image); - if (sizeItem.length > 0) { - setSizeTitle(sizeItem[sizeItem.length - 1].attribute_name); - } - - const noImg = groupList - .find((item) => !item.has_image) - ?.attributes.find((item) => item.has_color); - setSize(noImg?.value ?? ""); - - const shotData = groupList.sort((a, b) => (a.has_image ? -1 : 1)); - if (shotData.length > 1) { - const hasImg = shotData[0]; - if (hasImg) { - // 创建一个深拷贝,避免修改原始数据 - const processedImg = { ...hasImg }; - processedImg.attributes = hasImg.attributes.map((attr) => ({ - ...attr, - list: [], - })); - // 处理每个属性,添加匹配的SKU到list - processedImg.attributes.forEach((attribute) => { - product.skus.forEach((sku) => { - // 检查SKU是否包含当前属性值 - const matchedAttr = sku.attributes.find( - (attr) => attr.value === attribute.value - ); - - if (matchedAttr) { - // 创建SKU的复制,不修改原始SKU - const skuCopy = { ...sku }; - // 过滤属性,创建新的属性数组而不是修改原始数组 - skuCopy.attributes = sku.attributes - .filter((attr) => attr.value !== attribute.value) - .map((attr) => ({ ...attr })); // 复制每个属性对象 - - // 将处理后的SKU添加到list - attribute.list.push(skuCopy); - } - }); - }); - console.log(processedImg); - - setHasImg(processedImg); - } else { - setHasImg(groupList[0]); - } - } else { - setNoImgList(product.skus); - } - - const img = groupList - .find((item) => item.has_image) - ?.attributes.find((item) => item.has_color); - - setSize(img?.value ?? ""); - - // 找到有图片的属性组 - }, [groupList, product]); // 添加依赖,确保数据变化时重新处理 - - const handleColorSelect = (colorId: string, index: number) => { - if (!hasImg) return; - // setPrice(price ?? 0); - - // 创建attributes的深拷贝 - const newAttributes = hasImg.attributes.map((attr, i) => { - if (i === index) { - // 当前选中项设为true - return { ...attr, has_color: true }; - } else { - // 其他项设为false - return { ...attr, has_color: false }; - } - }); - - const price = newAttributes[index].list[0].offer_price; - setPrice( - price ?? - product.sale_info.price_range_list[ - product.sale_info.price_range_list.length - 1 - ].price - ); - - // 更新hasImg状态 - setHasImg({ - ...hasImg, - attributes: newAttributes, - }); - }; - - const handleSizeSelect = ( - value: string, - type: string, - index: number, - amount_on_sale: number - ) => { - if (!hasImg) return; - - const data = hasImg.attributes.find((item) => item.has_color); - if (data) { - // 创建hasImg的深拷贝 - const newHasImg = { ...hasImg }; - - // 找到有颜色的属性索引 - const colorIndex = newHasImg.attributes.findIndex( - (item) => item.has_color - ); - if (colorIndex !== -1) { - // 创建属性数组的深拷贝 - newHasImg.attributes = [...newHasImg.attributes]; - - // 创建特定属性的深拷贝 - newHasImg.attributes[colorIndex] = { - ...newHasImg.attributes[colorIndex], - }; - - // 创建list数组的深拷贝 - newHasImg.attributes[colorIndex].list = [ - ...(newHasImg.attributes[colorIndex].list || []), - ]; - - // 创建特定list项的深拷贝 - if (index < newHasImg.attributes[colorIndex].list.length) { - newHasImg.attributes[colorIndex].list[index] = { - ...newHasImg.attributes[colorIndex].list[index], - }; - - // 修改size值 - if (type === "+") { - newHasImg.attributes[colorIndex].size = - (newHasImg.attributes[colorIndex].size ?? 0) + 1; - if (newHasImg.attributes[colorIndex].size > amount_on_sale) { - newHasImg.attributes[colorIndex].size = amount_on_sale; - } - newHasImg.attributes[colorIndex].list[index].size = - (newHasImg.attributes[colorIndex].list[index].size ?? 0) + 1; - - if ( - newHasImg.attributes[colorIndex].list[index].size > amount_on_sale - ) { - newHasImg.attributes[colorIndex].list[index].size = - amount_on_sale; - } - } else { - newHasImg.attributes[colorIndex].size = - (newHasImg.attributes[colorIndex].size ?? 0) - 1; - newHasImg.attributes[colorIndex].list[index].size = - (newHasImg.attributes[colorIndex].list[index].size ?? 0) - 1; + const [images, setImages] = useState([]); + const [currentImageIndex, setCurrentImageIndex] = useState(0); + const [imageViewerVisible, setImageViewerVisible] = useState(false); - if (newHasImg.attributes[colorIndex].list[index].size < 0) { - newHasImg.attributes[colorIndex].list[index].size = 0; - } - if (newHasImg.attributes[colorIndex].size < 0) { - newHasImg.attributes[colorIndex].size = 0; - } - } - - // 更新hasImg状态 - setHasImg(newHasImg); - calculateTotalSize(newHasImg); - } - } - } - }; - - // 无图片的加减 - const handleNoImgSizeSelect = ( - value: string, - type: string, - index: number, - amount_on_sale: number - ) => { - if (!noImgList) return; - console.log(noImgList); - - if (type === "+") { - noImgList[index].size = (noImgList[index].size ?? 0) + 1; - if (noImgList[index].size > amount_on_sale) { - noImgList[index].size = amount_on_sale; - } - } else { - noImgList[index].size = (noImgList[index].size ?? 0) - 1; - } - if (noImgList[index].size < 0) { - noImgList[index].size = 0; - } - setNoImgList([...noImgList]); + const { + product, + groupList, + imgTitle, + price, + hasImg, + noImgList, + sizeTitle, + size, + flag, + totalPrice, + selectedSize, + setProduct, + setGroupList, + setImgTitle, + setPrice, + setHasImg, + setNoImgList, + setSizeTitle, + setSize, + setFlag, + setTotalPrice, + setSelectedSize, + processProductData, + handleSizeSelect, + handleNoImgSizeSelect, + handleColorSelect, + } = useProductCartStore(); - let total = 0; - let priceSum = 0; - - noImgList.forEach((item) => { - total += item.size ?? 0; - priceSum += - (item.offer_price ?? - product.sale_info.price_range_list[ - product.sale_info.price_range_list.length - 1 - ].price) * (item.size ?? 0); - }); - - setSelectedSize(total); - setTotalPrice(priceSum); - }; - - // 计算所有size的总和 - const calculateTotalSize = (hasImgData: ProductGroupList | undefined) => { - if (!hasImgData) return; - - let total = 0; - let priceSum = 0; - hasImgData.attributes.forEach((attr) => { - attr.list?.forEach((item) => { - const itemSize = item.size ?? 0; - total += itemSize; - priceSum += - (item.offer_price ?? - product.sale_info.price_range_list[ - product.sale_info.price_range_list.length - 1 - ].price) * itemSize; - }); - }); - - setSelectedSize(total); - setTotalPrice(priceSum); - }; + useEffect(() => { + setProduct(localProduct); + setGroupList(localGroupList); + processProductData(); + }, [localProduct, localGroupList]); // 加入购物车 const addCartHandel = () => { + if (totalPrice === 0) { + Alert.alert("添加失败", "请选择商品"); + return; + } if (groupList.length > 1) { const selectedSku = hasImg?.attributes.filter((item) => (item.size ?? 0) > 0) || []; @@ -345,6 +135,7 @@ const ProductCard: React.FC = ({ const cancelDelete = () => { // 关闭确认对话框 setDeleteModalVisible(false); + onClose(); }; const handleNavigateToCart = useCallback(() => { @@ -354,377 +145,181 @@ const ProductCard: React.FC = ({ }); }, [navigation]); + // 图片预览 + const handleImagePress = (imageUrl: string) => { + setImages([imageUrl]); + setCurrentImageIndex(0); + setImageViewerVisible(true); + }; + return ( - - - - - - - - - {/* SVG commented out as requested */} - {/* - - - - - - - - */} - + + + + + + + + - - - - - {price} - - FCFA - - - -5% - - {/* SVG commented out as requested */} - {/* - - - - - - - - - - - - - - */} - - - - - - VIP - - + + - - - - 3072 - FCFA - - ≥2 Pièces + + + + + + + {price} + FCFA - - - 2500 - FCFA + + + + -5% - ≥50 Pièces - - - 2099 - FCFA - - ≥100 Pièces + + + + onClose()}> + + + + + + {product && + product.sale_info && + product.sale_info.price_range_list && + product.sale_info.price_range_list.length > 0 + ? product.sale_info.price_range_list.map((item, index) => { + return ( + + + + {item.price} + + FCFA + + + + >= {item.min_quantity} 硬币 + + + + ); + }) + : null} + - - {hasImg && groupList.length > 1 && hasImg.has_image && ( - - - {hasImg?.attribute_name}: {size} - + + {/* 图片和文字 */} + {hasImg && groupList.length > 1 && hasImg.has_image && ( + + {hasImg && ( + <> + + + {hasImg.attribute_name} :{" "} + + {size} + - - {hasImg.attributes.map((attribute, index1) => ( + {hasImg?.attributes?.map((item, index) => { + return ( - handleColorSelect(attribute.value, index1) + handleColorSelect( + item.value, + index, + item.sku_image_url + ) } > - - - - - {(attribute.size ?? 0) > 0 && ( - - - x{attribute.size} - - - )} - - - {attribute.value} + + {item.size && ( + + + x{item.size} - + )} - ))} - + ); + })} - - {sizeTitle} - - - {/* 显示属性列表 */} - {hasImg.attributes - .find((item) => item.has_color) - ?.list.map((list, index1) => ( - - - - {(list?.size ?? 0) > 0 && ( - - x{list?.size} - - )} - - {list?.attributes[0]?.value} - - - - 库存 {list?.amount_on_sale} - - - - - - handleSizeSelect( - list?.attributes[0]?.value, - "-", - index1, - list.amount_on_sale - ) - } - > - - - - - {list?.size ?? 0} - - - handleSizeSelect( - list?.attributes[0]?.value, - "+", - index1, - list.amount_on_sale - ) - } - > - + - - - - ))} - - - - - )} - - {hasImg && groupList.length > 1 && !hasImg.has_image && ( - - - {hasImg?.attribute_name}: {size} - - - - {hasImg.attributes.map((item, index) => ( - handleColorSelect(item.value, index)} - > - - {item.size && ( - - x{item.size} - - )} - - - {item.value} - - - ))} - - - {sizeTitle} - - {hasImg.attributes - .find((item) => item.has_color) - ?.list.map((list, index1) => ( - - - - {(list?.size ?? 0) > 0 && ( - - x{list?.size} - - )} - - {list?.attributes[0]?.value} - - - - 库存 {list?.amount_on_sale} - - - - - - handleSizeSelect( - list?.attributes[0]?.value, - "-", - index1, - list.amount_on_sale - ) - } - > - - - - - {list?.size ?? 0} - - - handleSizeSelect( - list?.attributes[0]?.value, - "+", - index1, - list.amount_on_sale - ) - } - > - + - - - - ))} - - - - - + )} - - {noImgList && groupList.length === 1 && !flag && ( - - - {sizeTitle}: {size} - - - - {/* 显示属性列表 */} - {noImgList?.map((list, index1) => ( - - - + + {sizeTitle} + + + + {hasImg && + hasImg.attributes + ?.find((item) => item.has_color) + ?.list.map((list, index1) => ( + + + {(list?.size ?? 0) > 0 && ( x{list?.size} )} + + {list.offer_price || price} + - {list?.attributes[0]?.value} + {list.attributes[0].value} 库存 {list?.amount_on_sale} - - + - handleNoImgSizeSelect( + handleSizeSelect( list?.attributes[0]?.value, "-", index1, @@ -734,10 +329,23 @@ const ProductCard: React.FC = ({ > - - {list?.size ?? 0} + + handleSizeSelect( + list?.attributes[0]?.value, + text, + index1, + list.amount_on_sale + ) + } + /> - handleNoImgSizeSelect( + handleSizeSelect( list?.attributes[0]?.value, "+", index1, @@ -750,89 +358,78 @@ const ProductCard: React.FC = ({ ))} - - - )} + + + )} + {/* 两个都是文字 */} + {hasImg && groupList.length > 1 && !hasImg.has_image && ( + + + {hasImg.attribute_name} + - {noImgList && groupList.length === 1 && flag && ( - - - {sizeTitle}: {size} - - - - {/* 显示属性列表 */} - {noImgList?.map((list, index1) => ( - - - - - - - - - - {(list?.size ?? 0) > 0 && ( - - x{list?.size} - - )} - - {list?.attributes[0]?.value} - - - + {hasImg.attributes?.map((item, index) => { + return ( + { + handleColorSelect(item.value, index, item.sku_image_url); + }} + > + {(item?.size ?? 0) > 0 && ( + x{item?.size} + )} + {item.value} + + ); + })} - - 库存 {list?.amount_on_sale} + + {sizeTitle} + + + + {hasImg && + hasImg.attributes + ?.find((item) => item.has_color) + ?.list.map((list, index1) => ( + + + + {(list?.size ?? 0) > 0 && ( + + x{list?.size} - + )} + + {list.offer_price || price} + + + {list.attributes[0].value} + + + 库存 {list?.amount_on_sale} + - - + - handleNoImgSizeSelect( + handleSizeSelect( list?.attributes[0]?.value, "-", index1, @@ -842,10 +439,23 @@ const ProductCard: React.FC = ({ > - - {list?.size ?? 0} + + handleSizeSelect( + list?.attributes[0]?.value, + text, + index1, + list.amount_on_sale + ) + } + /> - handleNoImgSizeSelect( + handleSizeSelect( list?.attributes[0]?.value, "+", index1, @@ -858,369 +468,435 @@ const ProductCard: React.FC = ({ ))} - - - )} + - - - - - - + )} + {/* 只有一个文字 */} + {noImgList && groupList.length === 1 && !flag && ( + + + {sizeTitle} + + + {noImgList && + noImgList?.map((list, index1) => ( + + + + {(list?.size ?? 0) > 0 && ( + + x{list?.size} + + )} + + {list.offer_price || price} + + + {list.attributes[0].value} + + + + 库存 {list?.amount_on_sale} + + + + + handleNoImgSizeSelect( + list?.attributes[0]?.value, + "-", + index1, + list.amount_on_sale + ) + } + > + - + + + handleNoImgSizeSelect( + list?.attributes[0]?.value, + text, + index1, + list.amount_on_sale + ) + } + /> + + handleNoImgSizeSelect( + list?.attributes[0]?.value, + "+", + index1, + list.amount_on_sale + ) + } + > + + + + + + ))} + + + )} + + {/* 只有图片 */} + {noImgList && groupList.length === 1 && flag && ( + + + {sizeTitle} + + + {noImgList.map((list, index1) => ( + + + + + + + + + + {list.offer_price || price} + + + {list.attributes[0].value} + + + + + 库存 {list?.amount_on_sale} + + + + + handleNoImgSizeSelect( + list.attributes[0]?.value, + "-", + index1, + list.amount_on_sale + ) + } + > + - + + + handleNoImgSizeSelect( + list.attributes[0]?.value, + text, + index1, + list.amount_on_sale + ) + } + /> + + handleNoImgSizeSelect( + list.attributes[0]?.value, + "+", + index1, + list.amount_on_sale + ) + } + > + + + + + + + ))} + + + )} - - - - - 总数量:{selectedSize} + + + + + 总数量: + + {selectedSize} - - Total: {totalPrice.toFixed(2)} FCFA + + + 总价: + + {totalPrice.toFixed(2)} FCFA - - - - 加入购物车 - - - + + + 加入购物车 + - - - {/* */} - Supprimer l'article ? - - - Non - - - Voir le panier - + visible={deleteModalVisible} + transparent + animationType="fade" + onRequestClose={cancelDelete} + > + + + {/* */} + Supprimer l'article ? + + + Non + + + Voir le panier + + - - + ); }; const styles = StyleSheet.create({ - container: { - width: "100%", - backgroundColor: "white", - height: "100%", - }, - productCardContainer3: { - flexDirection: "column", - alignItems: "stretch", - justifyContent: "flex-start", - width: "100%", - paddingTop: 15, - paddingRight: 19, - paddingLeft: 19, - height: "100%", + wrapper: { + flex: 1, }, - pricingCard: { - paddingTop: 5, - paddingBottom: 5, - height: "100%", + container: { + flex: 1, + padding: 19, + paddingBottom: widthUtils(118, 118).height, }, - flexRowAlignedEndFullWidth: { + productInfo: { flexDirection: "row", - alignItems: "flex-end", - justifyContent: "flex-start", - width: "100%", - }, - productCardContainer: { - flexBasis: widthUtils(80, 80).width, - paddingTop: 5, + height: widthUtils(100, 100).height, }, - cardContainer: { - width: "100%", - backgroundColor: "#e0e0e0", - borderRadius: 5, - }, - flexColumnEndAlign2: { - flexDirection: "column", - alignItems: "flex-end", - justifyContent: "flex-start", - width: "100%", - height: widthUtils(80, 80).height, - borderRadius: 5, + productBigImgBox: { + width: widthUtils(100, 100).width, + height: widthUtils(100, 81000).height, + borderRadius: 10, }, - flexColumnImg: { + productBigImg: { width: "100%", height: "100%", - borderRadius: 5, + borderRadius: 10, }, - productCardContainer2: { - flexBasis: widthUtils(295, 295).width, - marginLeft: 15, + productInfoBox: { + flex: 1, + paddingLeft: 10, }, - productCardContainer1: { + priceInfo: { + width: "100%", + height: "40%", flexDirection: "row", - alignItems: "flex-end", - justifyContent: "flex-start", + justifyContent: "space-between", }, - priceInfoContainer1: { + priceInfoBox: { + width: "90%", + height: "100%", flexDirection: "row", alignItems: "center", - justifyContent: "flex-start", + gap: 10, }, - highlightedText: { - padding: 0, - margin: 0, + price: { + flexDirection: "row", + }, + priceInfoText: { fontWeight: "700", fontSize: fontSize(30), fontFamily: "Segoe UI", color: "#ff5100", }, - priceInfoContainer2: { - flexDirection: "row", - alignItems: "flex-start", - justifyContent: "flex-start", - marginLeft: 1, + priceListBoxText: { + fontWeight: "700", + fontSize: fontSize(20), + fontFamily: "Segoe UI", }, - orangeHeading: { - padding: 0, - paddingBottom: 14, - margin: 0, + priceListBoxTextCon: { fontWeight: "700", fontSize: fontSize(14), fontFamily: "Segoe UI", - color: "#ff5100", - }, - percentageChangeContainer: { - flexDirection: "column", - alignItems: "center", - justifyContent: "flex-start", - marginLeft: 14.5, + lineHeight: fontSize(20), }, - discountPercentageTextStyle: { - padding: 0, - margin: 0, - fontStyle: "italic", - fontWeight: "900", - fontSize: fontSize(11), + priceListBoxListText: { fontFamily: "Segoe UI", - color: "#4e2000", }, - vipButtonContainer: { - flexDirection: "row", - alignItems: "center", - justifyContent: "flex-start", - marginLeft: 1.25, - }, - vipButton: { - width: widthUtils(55,55).width, - minWidth: 55, - height: 21, - marginLeft: -2.5, - backgroundColor: "#3b3b3b", - borderWidth: 0, - borderRadius: 5, - borderBottomLeftRadius: 0, - }, - italicBoldSegoeVip: { - fontStyle: "italic", - fontWeight: "900", + priceInfoTextCon: { + fontWeight: "700", fontSize: fontSize(14), fontFamily: "Segoe UI", + color: "#ff5100", + lineHeight: fontSize(30), }, - pricingCardContainer: { - flexDirection: "row", - gap: widthUtils(29.5, 29.5).width, - alignItems: "flex-start", - justifyContent: "space-between", + priceInfoOffer: { + width: widthUtils(28, 28).width, + height: widthUtils(28, 28).height, + position: "relative", + }, + priceInfoOfferImg: { width: "100%", - paddingRight: 15, - paddingBottom: 3, - paddingLeft: 11, - marginTop: 7, - backgroundColor: "#f3f4f8", - borderRadius: 5, + height: "100%", }, - priceInfoContainer: { - flexDirection: "row", + discountTextContainer: { + position: "absolute", + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: "center", alignItems: "center", - justifyContent: "flex-start", }, - priceHighlightedText: { - padding: 0, - margin: 0, - fontWeight: "700", - fontSize: fontSize(16), - fontFamily: "Segoe UI", - color: "#373737", - }, - priceTagBold: { - padding: 0, - margin: 0, - fontWeight: "700", - fontSize: fontSize(11), - fontFamily: "Segoe UI", - color: "#373737", - }, - productPriceTier: { - padding: 0, - margin: 0, - marginTop: -4, - fontWeight: "400", + discountText: { + color: "#512003", fontSize: fontSize(12), - fontFamily: "PingFang SC", - color: "#373737", + fontWeight: "600", + fontStyle: "italic", }, - productDetailsContainer: { + priceInfoVip: { + width: widthUtils(21, 63).width, + height: widthUtils(21, 63).height, + }, + priceInfoVipImg: { width: "100%", - marginTop: 24, height: "100%", }, - primaryTextHeading: { - padding: 0, - margin: 0, - fontWeight: "600", - fontSize: fontSize(16), - lineHeight: fontSize(20), - fontFamily: "Segoe UI", - color: "black", + priceInfoClose: { + width: "10%", + alignItems: "flex-end", }, - colorPaletteContainer1: { - marginTop: 12, + priceInfoList: { + width: "100%", + padding: 5, + backgroundColor: "#f3f4f8", + borderRadius: 10, + height: "60%", }, - cardContainerWithTitle: { - flexDirection: "column", - alignItems: "stretch", + priceList: { + width: widthUtils(100, 100).width, + height: "100%", + borderRadius: 10, + marginRight: 5, justifyContent: "flex-start", - width: widthUtils(116,116).width, - height: widthUtils(116,116).height, - paddingBottom: 5, - backgroundColor: "#f4f4f4", - borderRadius: 5, + alignItems: "flex-start", + paddingLeft: 10, }, - cardContainerWithImage: { + priceListBox: { flexDirection: "row", + justifyContent: "center", + }, + priceListBoxPie: { alignItems: "flex-start", - justifyContent: "flex-start", - borderRadius: 5, - width: widthUtils(90,90).width, - height: widthUtils(90,90).height, }, - imageContainer: { + productBox: { + marginTop: 10, + flex: 1, + }, + productTit: { + flexDirection: "row", width: "100%", - height: "100%", - borderWidth: 0, - resizeMode: "cover", }, - profileCard: { - alignSelf: "center", - padding: 0, - margin: 0, - marginTop: 1, - fontWeight: "400", + productTitText: { + fontSize: fontSize(16), + fontWeight: "700", fontFamily: "Segoe UI", - color: "black", - textAlign: "center", - width: widthUtils(90,26).width, - height: widthUtils(90,26).height, - fontSize: fontSize(18), + color: "#000", }, - closeIconContainer: { - position: "absolute", - top: 15, - right: 15, - zIndex: 1, + productBoxImgList: { + width: "100%", + paddingTop: 10, + flexGrow: 0, + flexDirection: "row", + flexWrap: "wrap", + }, + productBoxImgListBox: { + width: widthUtils(90, 90).width, + height: widthUtils(90, 90).height, + backgroundColor: "#f4f4f4", + borderRadius: 10, + marginRight: 10, + marginBottom: 10, + position: "relative", }, - selectedColorImageContainer: { + productBoxImgListBoxActive: { borderWidth: 1, - borderColor: "#ff5217", + borderColor: "#ff5100", }, - topLeftBadge: { - position: "absolute", - top: -6, - left: -1, - width: widthUtils(16,30).width, - height: widthUtils(16,30).height, - borderRadius: 8, - backgroundColor: "#ff5323", - zIndex: 1, - alignItems: "center", - justifyContent: "center", + noImgBoxsText: { + width: "100%", }, - topLeftBadgeText: { - color: "white", - fontSize: fontSize(10), - fontWeight: "400", - fontFamily: "Segoe UI", - textAlign: "center", - lineHeight: fontSize(16), + productBoxImgListBoxImg: { + width: "100%", + height: "100%", + borderRadius: 10, }, - specifications: { + sizePrice: {}, + sizePriceBox: { + width: "100%", + height: "100%", flex: 1, - paddingVertical: 10, - }, - sizeList: { - gap: 5, - }, - sizeItem: { - paddingHorizontal: 10, - paddingVertical: 8, - borderRadius: 5, - marginTop: 10, - backgroundColor: "#efefef", }, - sizeActiveItem: { - backgroundColor: "#ff5323", - color: "#ffffff", - }, - sizeActiveItemText: { - color: "#ffffff", - }, - sizeTitle: { - marginTop: 5, - padding: 0, - margin: 0, - fontWeight: "600", - fontSize: fontSize(16), - lineHeight: fontSize(20), - fontFamily: "Segoe UI", - color: "black", - }, - specificationsList: { - marginTop: 10, + sizePriceBoxItem: { + width: "70%", }, - specificationsItem: { - paddingVertical: 5, + sizePriceBoxItemTextBox: { flexDirection: "row", - justifyContent: "space-between", alignItems: "center", }, - sizeText: { - fontSize: fontSize(16), - fontWeight: "600", - fontFamily: "Segoe UI", - color: "black", - width: widthUtils(200,200).width, - }, selectedNumText: { - width: widthUtils(16,30).width, - height: widthUtils(16,30).height, + width: widthUtils(16, 30).width, + height: widthUtils(16, 30).height, backgroundColor: "#ff5217", borderRadius: 5, color: "white", @@ -1231,91 +907,196 @@ const styles = StyleSheet.create({ marginRight: 5, lineHeight: 18, }, + sizePriceBoxItems: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + marginBottom: 10, + width: "100%", + }, + sizePriceBoxItemText: { + fontSize: fontSize(18), + color: "#000", + }, + priceText: { + fontSize: fontSize(16), + fontWeight: "700", + fontFamily: "Segoe UI", + color: "red", + marginRight: 5, + }, amountText: { fontSize: fontSize(16), fontWeight: "600", fontFamily: "Segoe UI", color: "#bdbdbd", }, - numberContainer: { + sizePriceBoxStepForward: { + width: "30%", flexDirection: "row", alignItems: "center", + justifyContent: "flex-end", }, - numText: { - width: widthUtils(24,40).width, - height: widthUtils(24,40).height, + sizePriceBoxStepForwardButton: { + width: widthUtils(40, 30).width, + height: widthUtils(40, 30).height, + backgroundColor: "#f3f4f8", + justifyContent: "center", + alignItems: "center", + }, + sizePriceBoxStepForwardInput: { + width: widthUtils(40, 30).width, + height: widthUtils(40, 30).height, + backgroundColor: "#fff", textAlign: "center", - fontSize: fontSize(16), - fontWeight: "600", - fontFamily: "Segoe UI", - color: "black", - backgroundColor: "#f4f4f4", - borderRadius: 5, - lineHeight: fontSize(28), - marginHorizontal: 5, + fontSize: fontSize(14), + borderWidth: 1, + borderColor: "#f3f4f8", + padding: 0, + lineHeight: fontSize(14), }, - bottomFixedContainer: { + fixedBottomView: { position: "absolute", bottom: 0, left: 0, + right: 0, + height: widthUtils(118, 118).height, width: "100%", - height: widthUtils(118,118).height, - backgroundColor: "white", borderTopWidth: 1, - borderTopColor: "#f4f4f4", - elevation: 5, - shadowColor: "#000", - shadowOffset: { width: 0, height: -2 }, - shadowOpacity: 0.1, - shadowRadius: 3, - paddingHorizontal: 19, - paddingVertical: 15, - }, - bottomFixedContainer1: { + borderTopColor: "#f3f4f8", + padding: 10, + zIndex: 1000, + backgroundColor: "white", + }, + fixedBottomViewBox: { + width: "100%", flexDirection: "row", - alignItems: "center", justifyContent: "space-between", - paddingTop: 10, - paddingBottom: 10, }, - bottomFixedContainerText: { - fontSize: fontSize(14), - fontWeight: "600", - fontFamily: "PingFang SC", - color: "black", + fixedBottomViewBoxLeft: { + width: "50%", + flexDirection: "row", + alignItems: "center", + }, + fixedBottomViewBoxLeftText: { + fontSize: fontSize(16), + fontFamily: "Segoe UI", + color: "#000", + }, + fixedBottomViewBoxPriceText: { + fontSize: fontSize(20), + fontFamily: "Segoe UI", + color: "#ff5217", + fontWeight: "700", }, - bottomFixedContainer2: { + fixedBottomViewBoxRight: { + width: "50%", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + }, + fixedBottomViewBoxRightText: { + fontSize: fontSize(16), + fontFamily: "Segoe UI", + }, + fixedBottomViewButton: { + marginTop: 10, width: "100%", - height: widthUtils(40,40).height, + height: widthUtils(50, 50).height, backgroundColor: "#ff5217", - borderRadius: 25, + borderRadius: 10, + justifyContent: "center", alignItems: "center", + }, + fixedBottomViewButtonText: { + fontSize: fontSize(16), + fontFamily: "Segoe UI", + color: "#fff", + fontWeight: "700", + lineHeight: widthUtils(50, 50).height, + }, + noImgBoxs: { + width: "100%", + marginTop: 10, + padding: 10, + borderRadius: 10, + backgroundColor: "#efefef", + flexDirection: "row", + }, + allImage: { + flex: 1, + }, + allImageBox: { + flexDirection: "row", + marginTop: 10, + alignItems: "center", + }, + allImageBoxImg: { + width: 50, + height: 50, + borderRadius: 10, + }, + allImageBoxImgImg: { + width: "100%", + height: "100%", + borderRadius: 10, + }, + allImageBoxList: { + flex: 1, + paddingLeft: 10, + flexDirection: "row", + }, + allImageBoxListBox: { + width: "60%", justifyContent: "center", }, - bottomFixedContainerButtonText: { - fontSize: fontSize(14), - fontWeight: "600", - fontFamily: "PingFang SC", - color: "white", + allImageBoxListBoxText: { + fontSize: fontSize(16), + fontFamily: "Segoe UI", + color: "#000", + }, + allImageBoxListStop: { + width: "40%", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + }, + cornerView: { + position: "absolute", + top: 0, + right: 0, + width: 22, + height: 22, + backgroundColor: "#787675", + }, + topRightIcon: { + position: "absolute", + top: 3, + right: 3, + }, + bottomLeftIcon: { + position: "absolute", + bottom: 3, + left: 3, }, fixedCornerView: { position: "absolute", - top: -8, + top: 0, left: 0, - width: widthUtils(16,30).width, - height: widthUtils(16,30).height, - zIndex: 10, - borderRadius: 5, + width: 30, + height: 16, + backgroundColor: "#ff5217", + borderRadius: 10, + justifyContent: "center", + zIndex: 1, }, - fixedCornerText: { + fixedCornerViewText: { fontSize: fontSize(12), - fontWeight: "600", fontFamily: "Segoe UI", - color: "white", + color: "#fff", + fontWeight: "700", textAlign: "center", - lineHeight: fontSize(18), - backgroundColor: "#ff5217", - borderRadius: 5, + lineHeight: 16, }, overlay: { flex: 1, @@ -1332,8 +1113,8 @@ const styles = StyleSheet.create({ gap: 21, }, image: { - width: widthUtils(80,80).width, - height: widthUtils(80,80).height, + width: widthUtils(80, 80).width, + height: widthUtils(80, 80).height, borderRadius: 5, resizeMode: "cover", }, @@ -1349,16 +1130,16 @@ const styles = StyleSheet.create({ marginTop: 10, }, cancelButton1: { - width: widthUtils(50,160).width, - height: widthUtils(50,160).height, + width: widthUtils(50, 160).width, + height: widthUtils(50, 160).height, borderRadius: 25, backgroundColor: "#f2f3f5", justifyContent: "center", alignItems: "center", }, confirmButton: { - width: widthUtils(50,160).width, - height: widthUtils(50,160).height, + width: widthUtils(50, 160).width, + height: widthUtils(50, 160).height, borderRadius: 25, backgroundColor: "#002fa7", justifyContent: "center", diff --git a/app/screens/ProductDetailScreen.tsx b/app/screens/ProductDetailScreen.tsx index c7da772..9ed11e3 100644 --- a/app/screens/ProductDetailScreen.tsx +++ b/app/screens/ProductDetailScreen.tsx @@ -38,6 +38,7 @@ import { RouteProp } from "@react-navigation/native"; import BackIcon from "../components/BackIcon"; import CameraIcon from "../components/CameraIcon"; import ProductCard from "./ProductCard"; +import useProductCartStore from "../store/productCart"; type ProductDetailRouteParams = { offer_id: string; searchKeyword?: string; @@ -45,6 +46,7 @@ type ProductDetailRouteParams = { }; export const ProductDetailScreen = () => { + const {product,setProduct,groupList,setGroupList} = useProductCartStore() const { width } = useWindowDimensions(); // 移动到组件内部 const navigation = useNavigation>(); const route = @@ -56,8 +58,7 @@ export const ProductDetailScreen = () => { }>({}); const [isHeartRed, setIsHeartRed] = useState(false); - const [product, setProduct] = useState(); - const [groupList, setGroupList] = useState([]); + const [isLoading, setIsLoading] = useState(true); const [similars, setSimilars] = useState(); @@ -370,6 +371,12 @@ export const ProductDetailScreen = () => { [navigation] ); + useEffect(() => { + if (showBottomSheet) { + console.log(123); + } + }, [showBottomSheet]) + return ( {isLoading ? ( @@ -380,9 +387,9 @@ export const ProductDetailScreen = () => { ) : ( <> - + navigation.goBack()}> - + 搜索 @@ -479,7 +486,7 @@ export const ProductDetailScreen = () => { }} > - {activeIndex + 1}/{product?.product_image_urls.length} + {activeIndex + 1}/{product?.product_image_urls?.length} diff --git a/app/screens/productStatus/OrderDatails.tsx b/app/screens/productStatus/OrderDatails.tsx index 41176c2..dc2c600 100644 --- a/app/screens/productStatus/OrderDatails.tsx +++ b/app/screens/productStatus/OrderDatails.tsx @@ -24,10 +24,10 @@ import AddressIcon from "../../components/AddressIcon"; import EditIcon from "../../components/ColorfulEditIcon"; import BrightnessIcon from "../../components/BrightnessIcon"; import PhoneIcon from "../../components/PhoneIcon"; -import WatchAppIcon from "../../components/watchAppIcon"; import ShoppingBagIcon from "../../components/ShoppingBagIcon"; import PowerIcon from "../../components/PowerIcon"; import CardIcon from "../../components/ShoppingCartIcon"; +import WhatsAppIcon from "../../components/WatchAppIcon"; import { useOrderListStore } from "../../store/orderList"; export const OrderDetails = () => { const navigation = useNavigation>(); @@ -206,7 +206,7 @@ export const OrderDetails = () => { {/* watchApp */} - + WhatsApp: {orderDetails.receiver_phone} @@ -551,10 +551,12 @@ const styles = StyleSheet.create({ orderIdText: { color: "#999", width: "50%", + fontSize: fontSize(14), }, orderIdText1: { width: "50%", textAlign: "right", + fontSize: fontSize(14), }, TotalText: { color: "#f77f3a", diff --git a/app/screens/productStatus/Progress.tsx b/app/screens/productStatus/Progress.tsx index 1b1b782..f41ffac 100644 --- a/app/screens/productStatus/Progress.tsx +++ b/app/screens/productStatus/Progress.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { View, StyleSheet } from 'react-native'; import { Text } from 'react-native-paper'; - +import fontSize from '../../utils/fontsizeUtils'; interface ProgressProps { statuses: number; @@ -74,7 +74,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, }, label: { - fontSize: 12, + fontSize: fontSize(12), color: '#666', textAlign: 'center', width: 60, diff --git a/app/store/productCart.ts b/app/store/productCart.ts new file mode 100644 index 0000000..56e81ec --- /dev/null +++ b/app/store/productCart.ts @@ -0,0 +1,364 @@ +import { create } from "zustand"; +import { + ProductDetailParams, + ProductGroupList, + SkuAttribute, + Sku, +} from "../services/api/productApi"; + +interface ProductCartState { + product: ProductDetailParams; + groupList: ProductGroupList[]; + imgTitle: string; + price: number; + hasImg: ProductGroupList; + totalPrice: number; + sizeList: SkuAttribute[]; + selectedSize: number; + setProduct: (product: ProductDetailParams) => void; + setGroupList: (groupList: ProductGroupList[]) => void; + setImgTitle: (imgTitle: string) => void; + setPrice: (price: number) => void; + setHasImg: (hasImg: ProductGroupList) => void; + setSizeList: (sizeList: SkuAttribute[]) => void; + setTotalPrice: (totalPrice: number) => void; + setSelectedSize: (selectedSize: number) => void; + noImgList: Sku[]; + setNoImgList: (noImgList: Sku[]) => void; + flag: boolean; + setFlag: (flag: boolean) => void; + sizeTitle: string; + setSizeTitle: (sizeTitle: string) => void; + size: string; + setSize: (size: string) => void; + processProductData: () => void; + handleSizeSelect: ( + value: string, + type: string, + index: number, + amount_on_sale: number + ) => void; + handleNoImgSizeSelect: ( + value: string, + type: string, + index: number, + amount_on_sale: number + ) => void; + calculateTotalSize: (hasImgData: ProductGroupList | undefined) => void; + handleColorSelect: ( + colorId: string, + index: number, + sku_image_url: string + ) => void; + offer_id:number; + setOfferId: (offer_id:number) => void; +} + +const useProductCartStore = create((set, get) => ({ + product: {} as ProductDetailParams, + groupList: [] as ProductGroupList[], + imgTitle: "", + price: 0, + hasImg: {} as ProductGroupList, + sizeList: [] as SkuAttribute[], + totalPrice: 0, + selectedSize: 0, + noImgList: [] as Sku[], + flag: false, + sizeTitle: "", + size: "", + offer_id:0, + setOfferId: (offer_id:number) => set({ offer_id }), + setSizeTitle: (sizeTitle: string) => set({ sizeTitle }), + setSize: (size: string) => set({ size }), + setProduct: (product: ProductDetailParams) => set({ product }), + setGroupList: (groupList: ProductGroupList[]) => set({ groupList }), + setImgTitle: (imgTitle: string) => set({ imgTitle }), + setPrice: (price: number = 0) => + set((state) => ({ + price: price, + })), + setHasImg: (hasImg: ProductGroupList) => set({ hasImg }), + setSizeList: (sizeList: SkuAttribute[]) => set({ sizeList }), + setTotalPrice: (totalPrice: number) => set({ totalPrice }), + setSelectedSize: (selectedSize: number) => set({ selectedSize }), + setNoImgList: (noImgList: Sku[]) => set({ noImgList }), + setFlag: (flag: boolean) => set({ flag }), + processProductData: () => { + const { groupList, product, offer_id, setOfferId } = get(); + set({ price: product.price as number }); + if (product) { + if (offer_id !== product.offer_id) { + set({ totalPrice: 0, selectedSize: 0 }); + } + const imageItem = groupList.filter((item) => item.has_image); + if (imageItem.length > 0) { + set({ sizeTitle: imageItem[imageItem.length - 1].attribute_name }); + imageItem.forEach((item) => { + const colorItem = item.attributes.filter( + (attribute) => attribute.has_color + ); + if (colorItem.length > 0) { + set({ imgTitle: colorItem[0].sku_image_url }); + } + }); + set({ flag: true }); + } else { + set({ flag: false }); + } + if (imageItem.length === 0) { + set({ imgTitle: product?.product_image_urls?.[0] || '' }); + } + + const sizeItem = groupList.filter((item) => !item.has_image); + if (sizeItem.length > 0) { + set({ sizeTitle: sizeItem[sizeItem.length - 1].attribute_name }); + } + + const noImg = groupList + .find((item) => !item.has_image) + ?.attributes.find((item) => item.has_color); + set({ size: noImg?.value ?? "" }); + + const shotData = groupList.sort((a, b) => (a.has_image ? -1 : 1)); + if (shotData.length > 1) { + const hasImg = shotData[0]; + if (hasImg) { + // 创建一个深拷贝,避免修改原始数据 + const processedImg = { ...hasImg }; + processedImg.attributes = hasImg.attributes.map((attr) => ({ + ...attr, + list: [], + })); + // 处理每个属性,添加匹配的SKU到list + processedImg.attributes.forEach((attribute) => { + product.skus.forEach((sku) => { + // 检查SKU是否包含当前属性值 + const matchedAttr = sku.attributes.find( + (attr) => attr.value === attribute.value + ); + + if (matchedAttr) { + // 创建SKU的复制,不修改原始SKU + const skuCopy = { ...sku }; + // 过滤属性,创建新的属性数组而不是修改原始数组 + skuCopy.attributes = sku.attributes + .filter((attr) => attr.value !== attribute.value) + .map((attr) => ({ ...attr })); // 复制每个属性对象 + + // 将处理后的SKU添加到list + attribute.list.push(skuCopy); + } + }); + }); + + set({ hasImg: processedImg }); + } else { + set({ hasImg: groupList[0] }); + } + } else { + set({ noImgList: product.skus }); + } + + const img = groupList + .find((item) => item.has_image) + ?.attributes.find((item) => item.has_color); + + set({ size: img?.value ?? "" }); + setOfferId(product.offer_id); + } + }, + handleColorSelect: ( + colorId: string, + index: number, + sku_image_url: string + ) => { + const { hasImg, product, setImgTitle, setPrice, setHasImg } = get(); + if (!hasImg) return; + if (sku_image_url) { + setImgTitle(sku_image_url); + } + // 创建attributes的深拷贝 + const newAttributes = hasImg.attributes.map((attr, i) => { + if (i === index) { + // 当前选中项设为true + return { ...attr, has_color: true }; + } else { + // 其他项设为false + return { ...attr, has_color: false }; + } + }); + + const newPrice = newAttributes[index].list[0].offer_price; + setPrice( + newPrice ?? + product.sale_info.price_range_list[ + product.sale_info.price_range_list.length - 1 + ].price + ); + + set({ size: newAttributes[index].value }); + + // 更新hasImg状态 + setHasImg({ + ...hasImg, + attributes: newAttributes, + }); + }, + handleSizeSelect: ( + value: string, + type: string, + index: number, + amount_on_sale: number + ) => { + const { hasImg, product } = get(); + if (!hasImg) return; + + const data = hasImg.attributes.find((item) => item.has_color); + if (data) { + // 创建hasImg的深拷贝 + const newHasImg = { ...hasImg }; + + // 找到有颜色的属性索引 + const colorIndex = newHasImg.attributes.findIndex( + (item) => item.has_color + ); + if (colorIndex !== -1) { + // 创建属性数组的深拷贝 + newHasImg.attributes = [...newHasImg.attributes]; + + // 创建特定属性的深拷贝 + newHasImg.attributes[colorIndex] = { + ...newHasImg.attributes[colorIndex], + }; + + // 创建list数组的深拷贝 + newHasImg.attributes[colorIndex].list = [ + ...(newHasImg.attributes[colorIndex].list || []), + ]; + + // 创建特定list项的深拷贝 + if (index < newHasImg.attributes[colorIndex].list.length) { + newHasImg.attributes[colorIndex].list[index] = { + ...newHasImg.attributes[colorIndex].list[index], + }; + + // 修改size值 + if (type === "+") { + newHasImg.attributes[colorIndex].size = + (newHasImg.attributes[colorIndex].size ?? 0) + 1; + if (newHasImg.attributes[colorIndex].size > amount_on_sale) { + newHasImg.attributes[colorIndex].size = amount_on_sale; + } + newHasImg.attributes[colorIndex].list[index].size = + (newHasImg.attributes[colorIndex].list[index].size ?? 0) + 1; + + if ( + newHasImg.attributes[colorIndex].list[index].size > amount_on_sale + ) { + newHasImg.attributes[colorIndex].list[index].size = + amount_on_sale; + } + } else if (type === "-") { + newHasImg.attributes[colorIndex].size = + (newHasImg.attributes[colorIndex].size ?? 0) - 1; + newHasImg.attributes[colorIndex].list[index].size = + (newHasImg.attributes[colorIndex].list[index].size ?? 0) - 1; + + if (newHasImg.attributes[colorIndex].list[index].size < 0) { + newHasImg.attributes[colorIndex].list[index].size = 0; + } + if (newHasImg.attributes[colorIndex].size < 0) { + newHasImg.attributes[colorIndex].size = 0; + } + } else { + // 处理直接输入数字的情况 + const newSize = parseInt(type); + if (!isNaN(newSize)) { + // 确保输入的数字在有效范围内 + const validSize = Math.min(Math.max(0, newSize), amount_on_sale); + newHasImg.attributes[colorIndex].list[index].size = validSize; + + // 更新总数量 + let totalSize = 0; + newHasImg.attributes[colorIndex].list.forEach(item => { + totalSize += item.size ?? 0; + }); + newHasImg.attributes[colorIndex].size = totalSize; + } + } + // 更新hasImg状态 + set({ hasImg: newHasImg }); + get().calculateTotalSize(newHasImg); + } + } + } + }, + handleNoImgSizeSelect: ( + value: string, + type: string, + index: number, + amount_on_sale: number + ) => { + const { noImgList, product } = get(); + if (!noImgList || !product || !product.sale_info || !product.sale_info.price_range_list) return; + + const newNoImgList = [...noImgList]; + if (type === "+") { + newNoImgList[index].size = (newNoImgList[index].size ?? 0) + 1; + if (newNoImgList[index].size > amount_on_sale) { + newNoImgList[index].size = amount_on_sale; + } + } else if (type === "-") { + newNoImgList[index].size = (newNoImgList[index].size ?? 0) - 1; + if (newNoImgList[index].size < 0) { + newNoImgList[index].size = 0; + } + } else { + // Handle direct number input + const newSize = parseInt(type); + if (!isNaN(newSize)) { + // Ensure the input number is within valid range + const validSize = Math.min(Math.max(0, newSize), amount_on_sale); + newNoImgList[index].size = validSize; + } + } + set({ noImgList: newNoImgList }); + + let total = 0; + let priceSum = 0; + + newNoImgList.forEach((item) => { + total += item.size ?? 0; + priceSum += + (item.offer_price ?? + product.sale_info.price_range_list[ + product.sale_info.price_range_list.length - 1 + ].price) * (item.size ?? 0); + }); + + set({ selectedSize: total, totalPrice: priceSum }); + }, + calculateTotalSize: (hasImgData: ProductGroupList | undefined) => { + if (!hasImgData) return; + const { product } = get(); + + let total = 0; + let priceSum = 0; + hasImgData.attributes.forEach((attr) => { + attr.list?.forEach((item) => { + const itemSize = item.size ?? 0; + total += itemSize; + priceSum += + (item.offer_price ?? + product.sale_info.price_range_list[ + product.sale_info.price_range_list.length - 1 + ].price) * itemSize; + }); + }); + + set({ selectedSize: total, totalPrice: priceSum }); + }, +})); + +export default useProductCartStore; diff --git a/assets/img/vip1.png b/assets/img/vip1.png new file mode 100644 index 0000000..6966bb3 Binary files /dev/null and b/assets/img/vip1.png differ diff --git a/assets/img/折扣VIP1 (1).png b/assets/img/折扣VIP1 (1).png new file mode 100644 index 0000000..dfeb6d5 Binary files /dev/null and b/assets/img/折扣VIP1 (1).png differ