From fd6f7a8dfcc0cbb9b7db328aff97cd04913c291d Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 18 May 2025 17:10:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=8B=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.tsx | 2 + app/screens/CartScreen.tsx | 2 +- app/screens/MainApp.tsx | 2 +- app/screens/ProductCard.tsx | 182 ++++++++++++-------- app/screens/ProductDetailScreen.tsx | 31 ++-- app/screens/SearchScreen.tsx | 7 +- app/screens/loginList/PhoneLoginModal.tsx | 12 +- app/screens/previewOrder/PaymentMethod.tsx | 38 ++++ app/screens/previewOrder/PreviewAddress.tsx | 16 +- app/screens/previewOrder/ShippingFee.tsx | 17 ++ app/services/api/orders.ts | 1 + app/services/api/productApi.ts | 2 + app/store/burialPoint.ts | 60 ++++++- app/store/productCart.ts | 60 ++++++- 14 files changed, 339 insertions(+), 93 deletions(-) diff --git a/App.tsx b/App.tsx index 7e45cae..f65497c 100644 --- a/App.tsx +++ b/App.tsx @@ -11,6 +11,8 @@ import { View, ActivityIndicator } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; import "./app/i18n"; + + function AppContent() { const { setUser } = useUserStore(); const { login, logout } = useAuth(); diff --git a/app/screens/CartScreen.tsx b/app/screens/CartScreen.tsx index 042bc44..be7d443 100644 --- a/app/screens/CartScreen.tsx +++ b/app/screens/CartScreen.tsx @@ -869,7 +869,7 @@ const styles = StyleSheet.create({ }, safeAreaContent: { flex: 1, - paddingTop: Platform.OS === 'android' ? 10 : 0, + paddingTop: Platform.OS === 'android' ? 0 : 0, }, container: { flex: 1, diff --git a/app/screens/MainApp.tsx b/app/screens/MainApp.tsx index 71e8d0d..13c87a9 100644 --- a/app/screens/MainApp.tsx +++ b/app/screens/MainApp.tsx @@ -16,7 +16,7 @@ import Constants from 'expo-constants'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import { RootStackParamList } from '../../App'; +import { RootStackParamList } from '../navigation/types'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; diff --git a/app/screens/ProductCard.tsx b/app/screens/ProductCard.tsx index 1c260b1..cd48116 100644 --- a/app/screens/ProductCard.tsx +++ b/app/screens/ProductCard.tsx @@ -17,6 +17,7 @@ import fontSize from "../utils/fontsizeUtils"; import CloseIcon from "../components/CloseIcon"; import XIconBottom from "../components/XIconBottom"; import XIconTop from "../components/XIconTop"; +import useBurialPointStore from "../store/burialPoint"; import { ProductDetailParams, ProductGroupList, @@ -29,7 +30,6 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import ImageView from "react-native-image-viewing"; import useProductCartStore from "../store/productCart"; import useUserStore from "../store/user"; - interface ProductCardProps { onClose: () => void; product: ProductDetailParams; @@ -51,9 +51,9 @@ const ProductCard: React.FC = ({ const [currentImageIndex, setCurrentImageIndex] = useState(0); const [imageViewerVisible, setImageViewerVisible] = useState(false); const { - user: { user_id, vip_level }, + user: { user_id, vip_level,currency }, } = useUserStore(); - + const { logAddToCart } = useBurialPointStore(); const { product, groupList, @@ -105,24 +105,45 @@ const ProductCard: React.FC = ({ } if (groupList.length > 1) { const selectedSku = - hasImg?.attributes.filter((item) => (item.size ?? 0) > 0) || []; + hasImg?.attributes?.filter((item) => (item.size ?? 0) > 0) || []; const skus: { sku_id: number; quantity: number }[] = []; selectedSku.forEach((item) => { - item.list.forEach((item) => { - if ((item.size ?? 0) > 0) { - skus.push({ - sku_id: item.sku_id, - quantity: item.size as number, - }); - } - }); + item.list?.forEach((item) => { + if ((item.size ?? 0) > 0) { + skus.push({ + sku_id: item.sku_id, + quantity: item.size as number, + }); + } + }); }); const data = { offer_id: product.offer_id, skus, }; + cartApi(data).then((res) => { - console.log(res); + + const log = selectedSku[0].list?.filter((item) => (item.size ?? 0) > 0) || [] + log.forEach((item) => { + const logData = { + offer_id: product?.offer_id || 0, + category_id: product?.category_id || 0, + price: item.offer_price || price || 0, + all_price: totalPrice || 0, + currency: currency || '', + sku_id: item?.sku_id || 0, + quantity: (item?.size as number) || 0, + product_name: product?.subject || '', + timestamp: new Date().toISOString(), + sku_img: selectedSku[0].sku_image_url || '', + all_quantity: selectedSize || 0 + } + logAddToCart(logData,navigation.getState().routes[navigation.getState().index - 1]?.name as string) + }) + + }).catch((err) => { + Alert.alert("添加失败", "请稍后再试"); }); } else if (groupList.length === 1) { const selectedSku = @@ -138,8 +159,33 @@ const ProductCard: React.FC = ({ offer_id: product.offer_id, skus, }; - cartApi(data).then((res) => { - console.log(res); + cartApi(data).then((res) => { + console.log(selectedSku); + + selectedSku.forEach((item) => { + console.log(item); + + const logData = { + offer_id: product?.offer_id || 0, + category_id: product?.category_id || 0, + price: item.offer_price || price || 0, + all_price: totalPrice || 0, + currency: currency || '', + sku_id: item?.sku_id || 0, + quantity: (item?.size as number) || 0, + product_name: product?.subject || '', + timestamp: new Date().toISOString(), + sku_img: selectedSku[0].sku_image_url || '', + all_quantity: selectedSize || 0 + } + + console.log(logData); + + // logAddToCart(logData,navigation.getState().routes[navigation.getState().index - 1]?.name as string) + }) + + }).catch((err) => { + Alert.alert("添加失败", "请稍后再试"); }); } setDeleteModalVisible(true); @@ -272,22 +318,22 @@ const ProductCard: React.FC = ({ handleColorSelect( - item.value, + item?.value || '', index, - item.sku_image_url + item?.sku_image_url || '' ) } > - {item.size && ( + {(item?.size ?? 0) > 0 && ( x{item.size} @@ -312,7 +358,7 @@ const ProductCard: React.FC = ({ {hasImg && hasImg.attributes - ?.find((item) => item.has_color) + ?.find((item) => item?.has_color) ?.list.map((list, index1) => ( @@ -323,18 +369,18 @@ const ProductCard: React.FC = ({ )} - {list.offer_price || price} + {list?.offer_price || price || 0} - {list.attributes[0].value} + {list.attributes?.[0]?.value} - 库存 {list?.amount_on_sale} + 库存 {list?.amount_on_sale ?? 0} @@ -342,10 +388,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "-", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -353,14 +399,14 @@ const ProductCard: React.FC = ({ handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, text, index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } /> @@ -368,10 +414,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "+", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -389,25 +435,25 @@ const ProductCard: React.FC = ({ {hasImg && groupList.length > 1 && !hasImg.has_image && ( - {hasImg.attribute_name} + {hasImg?.attribute_name || ''} {hasImg.attributes?.map((item, index) => { return ( { - handleColorSelect(item.value, index, item.sku_image_url); + handleColorSelect(item?.value || '', index, item?.sku_image_url || ''); }} > {(item?.size ?? 0) > 0 && ( x{item?.size} )} - {item.value} + {item?.value || ''} ); })} @@ -424,7 +470,7 @@ const ProductCard: React.FC = ({ {hasImg && hasImg.attributes - ?.find((item) => item.has_color) + ?.find((item) => item?.has_color) ?.list.map((list, index1) => ( @@ -435,18 +481,18 @@ const ProductCard: React.FC = ({ )} - {list.offer_price || price} + {list?.offer_price || price || 0} - {list.attributes[0].value} + {list.attributes?.[0]?.value} - 库存 {list?.amount_on_sale} + 库存 {list?.amount_on_sale ?? 0} @@ -454,10 +500,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "-", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -465,14 +511,14 @@ const ProductCard: React.FC = ({ handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, text, index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } /> @@ -480,10 +526,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "+", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -519,18 +565,18 @@ const ProductCard: React.FC = ({ )} - {list.offer_price || price} + {list?.offer_price || price || 0} - {list.attributes[0].value} + {list.attributes?.[0]?.value} - 库存 {list?.amount_on_sale} + 库存 {list?.amount_on_sale ?? 0} @@ -538,10 +584,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleNoImgSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "-", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -549,14 +595,14 @@ const ProductCard: React.FC = ({ handleNoImgSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, text, index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } /> @@ -564,10 +610,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleNoImgSizeSelect( - list?.attributes[0]?.value, + list?.attributes?.[0]?.value, "+", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -597,7 +643,7 @@ const ProductCard: React.FC = ({ @@ -616,19 +662,19 @@ const ProductCard: React.FC = ({ marginRight: 5, }} > - {list.offer_price || price} + {list?.offer_price || price || 0} - {list.attributes[0].value} + {list.attributes?.[0]?.value} - 库存 {list?.amount_on_sale} + 库存 {list?.amount_on_sale ?? 0} @@ -636,10 +682,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleNoImgSizeSelect( - list.attributes[0]?.value, + list.attributes?.[0]?.value, "-", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > @@ -648,13 +694,13 @@ const ProductCard: React.FC = ({ handleNoImgSizeSelect( - list.attributes[0]?.value, + list.attributes?.[0]?.value, text, index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } /> @@ -662,10 +708,10 @@ const ProductCard: React.FC = ({ style={styles.sizePriceBoxStepForwardButton} onPress={() => handleNoImgSizeSelect( - list.attributes[0]?.value, + list.attributes?.[0]?.value, "+", index1, - list.amount_on_sale + list?.amount_on_sale ?? 0 ) } > diff --git a/app/screens/ProductDetailScreen.tsx b/app/screens/ProductDetailScreen.tsx index fdf1cfd..b365df6 100644 --- a/app/screens/ProductDetailScreen.tsx +++ b/app/screens/ProductDetailScreen.tsx @@ -31,6 +31,8 @@ import { Image as ExpoImage, ImageBackground } from "expo-image"; import useUserStore from "../store/user"; import { getSubjectTransLanguage } from "../utils/languageUtils"; import { useTranslation } from "react-i18next"; +import { getBurialPointData } from "../store/burialPoint"; +import useBurialPointStore from "../store/burialPoint"; import { productApi, @@ -54,6 +56,7 @@ type ProductDetailRouteParams = { }; export const ProductDetailScreen = () => { const { t } = useTranslation(); + const { logViewProduct } = useBurialPointStore(); const { product, setProduct, groupList, setGroupList } = useProductCartStore(); const userStore = useUserStore(); @@ -263,22 +266,16 @@ export const ProductDetailScreen = () => { }; const getProductDetail = async () => { if (!route.params?.offer_id) return; - const startTime = Date.now(); - console.log("开始时间:", startTime); setIsLoading(true); try { const res = await productApi.getProductDetail( route.params.offer_id, userStore.user?.user_id ); - console.log("API 请求完成"); if (res.skus != null) { const priceSelectedSku = res.skus.find( (item) => item.offer_price === route.params.price ); - - console.log("priceSelectedSku", priceSelectedSku); - if (priceSelectedSku) { res.price = priceSelectedSku.offer_price; res.original_price = priceSelectedSku.original_price; @@ -324,14 +321,28 @@ export const ProductDetailScreen = () => { imageUrls.length > 5 ? imageUrls.slice(0, 5) : imageUrls; setImageUrls(limitedImageUrls); setGroupList(list); - console.log("数据处理完成"); + + const previousScreen = navigation.getState().routes[navigation.getState().index - 1]; + + const data = { + offer_id: res.offer_id, + category_id: res.category_id, + price: res.price, + sku_id: priceSelectedSku?.sku_id, + currency: userStore.user?.currency, + product_name: res.subject, + product_img: res.product_image_urls[0], + timestamp: new Date().toISOString(), + } + logViewProduct(data,previousScreen?.name as string); + + console.log(getBurialPointData()); + + } catch (error) { console.error("Error fetching product details:", error); } finally { setIsLoading(false); - const endTime = Date.now(); - console.log("结束时间:", endTime); - console.log("总执行时间:", endTime - startTime, "毫秒"); } }; const getSimilars = () => { diff --git a/app/screens/SearchScreen.tsx b/app/screens/SearchScreen.tsx index d56ab5e..ed31955 100644 --- a/app/screens/SearchScreen.tsx +++ b/app/screens/SearchScreen.tsx @@ -17,6 +17,9 @@ import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useTranslation } from 'react-i18next'; import SearchIcon from "../components/SearchIcon"; +import useBurialPointStore from "../store/burialPoint"; +import { getBurialPointData } from "../store/burialPoint"; + // 图标组件 - 使用React.memo优化渲染 const IconComponent = React.memo(({ name, size, color }: { name: string; size: number; color: string }) => { const Icon = Ionicons as any; @@ -80,6 +83,7 @@ export const SearchScreen = () => { const [isLoading, setIsLoading] = useState(true); const navigation = useNavigation>(); const { t } = useTranslation(); + const { logSearch } = useBurialPointStore(); // 热门搜索标签 - 使用翻译后的关键词 const trendingSearchTerms = [ @@ -184,6 +188,7 @@ export const SearchScreen = () => { // 导航到搜索结果页面,并传递搜索关键词 navigation.navigate('SearchResult', { keyword: searchText.trim() }); + logSearch(searchText.trim(),navigation.getState().routes[navigation.getState().index - 1]?.name as string); } }, [searchText, saveSearchHistory, navigation]); @@ -192,7 +197,7 @@ export const SearchScreen = () => { console.log('tag',tag); setSearchText(tag); saveSearchHistory(tag); - + logSearch(searchText.trim(),navigation.getState().routes[navigation.getState().index - 1]?.name as string); // 导航到搜索结果页面,并传递搜索关键词 navigation.navigate('SearchResult', { keyword: tag }); }, [saveSearchHistory, navigation]); diff --git a/app/screens/loginList/PhoneLoginModal.tsx b/app/screens/loginList/PhoneLoginModal.tsx index 3a11b16..a95c5a8 100644 --- a/app/screens/loginList/PhoneLoginModal.tsx +++ b/app/screens/loginList/PhoneLoginModal.tsx @@ -26,6 +26,8 @@ import useUserStore from "../../store/user"; import { CountryList } from "../../constants/countries"; import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; import {ForgotPhonePassword} from "./ForgotPhonePassword"; +import useBurialPointStore from "../../store/burialPoint"; +import {getBurialPointData} from "../../store/burialPoint"; type RootStackParamList = { Login: undefined; @@ -101,7 +103,8 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => { const navigation = useNavigation>(); const { setSettings, setUser } = useUserStore(); - + const { logLogin, } = useBurialPointStore(); + // Phone login state const [phoneNumber, setPhoneNumber] = useState(""); const [password, setPassword] = useState(""); @@ -151,7 +154,6 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => { try { const res = await settingApi.getSendSmsCountryList(); - console.log(res); setCountryList(res); @@ -160,11 +162,7 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => { if (savedCountry) { try { const parsedCountry = JSON.parse(savedCountry); - console.log(parsedCountry); - const item = res.find(item => item.country === parsedCountry.country); - console.log(item); - setSelectedCountry(item); } catch (e) { console.error("Error parsing stored country", e); @@ -243,6 +241,8 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => { setLoading(false); navigation.navigate("MainTabs", { screen: "Home" }); onClose(); + logLogin(true, "phone"); + } } catch (error) { setError('用户名或密码错误') diff --git a/app/screens/previewOrder/PaymentMethod.tsx b/app/screens/previewOrder/PaymentMethod.tsx index 92f643e..e64f1ff 100644 --- a/app/screens/previewOrder/PaymentMethod.tsx +++ b/app/screens/previewOrder/PaymentMethod.tsx @@ -21,6 +21,8 @@ import useCreateOrderStore from "../../store/createOrder"; import { useRoute, RouteProp } from "@react-navigation/native"; import useUserStore from "../../store/user"; import { createOrderDataType } from "../../types/createOrder"; +import useBurialPointStore from "../../store/burialPoint"; +import {getBurialPointData} from "../../store/burialPoint"; import { ordersApi, OrderData, CreateOrderRequest, Order, @@ -214,6 +216,7 @@ export const PaymentMethod = () => { eur: 655.96 }); const [totalAmount, setTotalAmount] = useState(121.97); + const { logPaymentConfirm } = useBurialPointStore(); const toggleExpanded = () => { setExpanded(!expanded); }; @@ -386,7 +389,42 @@ export const PaymentMethod = () => { } setOrderData(createOrderData || {}); + const data = { + pay_method: selectedPayment, + offline_payment: currentTab === 'offline' ? 0 : 1, + all_price: selectedPayment === 'Paypal' ? convertedAmount : + Number(((previewOrder?.total_amount || 0) + (orderData?.domestic_shipping_fee || 0) + + (orderData?.shipping_fee || 0)).toFixed(2)), + all_quantity:previewOrder?.items?.reduce((acc,item) => acc + item.quantity,0), + currency: selectedCurrency, + shipping_method: orderData?.transport_type || 0, + shipping_price_outside: orderData?.shipping_fee || 0, + shipping_price_within: orderData?.domestic_shipping_fee || 0, + timestamp: new Date().toISOString(), + pay_product:JSON.stringify(previewOrder?.items.map(item => { + return { + offer_id: item.offer_id, + price: item.unit_price, + all_price: previewOrder.total_amount, + currency: previewOrder.currency, + sku: item.attributes.map(sku => { + return { + sku_id: item.sku_id, + value: sku.value + }; + }), + quantity: item.quantity, + product_name: item.product_name, + timestamp: new Date(), + product_img: item.sku_image_url + }; + })) + + } + logPaymentConfirm(data,navigation.getState().routes[navigation.getState().index - 1]?.name as string) + console.log(getBurialPointData()); + setCreateLoading(true) try { const res = await ordersApi.createOrder(createOrderData as CreateOrderRequest) diff --git a/app/screens/previewOrder/PreviewAddress.tsx b/app/screens/previewOrder/PreviewAddress.tsx index b968e19..1c4110b 100644 --- a/app/screens/previewOrder/PreviewAddress.tsx +++ b/app/screens/previewOrder/PreviewAddress.tsx @@ -27,6 +27,8 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { settingApi } from "../../services/api/setting"; import flagMap from "../../utils/flagMap"; import useCreateOrderStore from "../../store/createOrder"; +import useBurialPointStore from "../../store/burialPoint"; +import {getBurialPointData} from "../../store/burialPoint"; type RootStackParamList = { AddRess: { address?: AddressItem; cart_item_id?: number | string }; AddressList: undefined; @@ -44,7 +46,7 @@ export const PreviewAddress = () => { } = useAddressStore(); const navigation = useNavigation>(); const route = useRoute(); - + const { logAddressInfo } = useBurialPointStore(); const [open, setOpen] = useState(false); const [value, setValue] = useState(null); @@ -207,11 +209,21 @@ export const PreviewAddress = () => { const handleSubmit = async () => { if (validateForm()) { - console.log(defaultAddress); setOrderData({ ...orderData, address_id: defaultAddress?.address_id, }); + + const logData = { + last_name: formData.receiver_last_name, + first_name: formData.receiver_first_name, + country: formData.country, + phone_number: Number(formData.receiver_phone), + whatsApp_number: Number(formData.whatsapp_phone), + } + logAddressInfo(logData,navigation.getState().routes[navigation.getState().index - 1]?.name as string) + console.log(getBurialPointData()); + navigation.navigate("ShippingFee",{ cart_item_id: route.params, }); diff --git a/app/screens/previewOrder/ShippingFee.tsx b/app/screens/previewOrder/ShippingFee.tsx index 8d36314..7d7945d 100644 --- a/app/screens/previewOrder/ShippingFee.tsx +++ b/app/screens/previewOrder/ShippingFee.tsx @@ -29,6 +29,8 @@ import { useNavigation, useRoute, RouteProp } from "@react-navigation/native"; import useCreateOrderStore from "../../store/createOrder"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import useUserStore from "../../store/user"; +import useBurialPointStore from "../../store/burialPoint"; +import {getBurialPointData} from "../../store/burialPoint"; type RootStackParamList = { ShippingFee: undefined; PaymentMethod: { freight_forwarder_address_id: number }; @@ -73,6 +75,7 @@ export const ShippingFee = () => { const { setOrderData ,orderData,items} = useCreateOrderStore(); const [countryCode,setCountryCode] = useState(); const userStore = useUserStore(); + const { logShippingConfirm } = useBurialPointStore(); const getFreightForwarderAddress = async () => { await fetchFreightForwarderAddress(0); }; @@ -179,6 +182,20 @@ export const ShippingFee = () => { : shippingFeeData?.total_shipping_fee_air, receiver_address:selectedWarehouseLabel }); + const data = { + shipping_method: shippingMethod === "sea" ? 0 : 1, + shipping_price_outside: shippingMethod === "sea" + ? (shippingFeeData?.total_shipping_fee_sea || 0) + : (shippingFeeData?.total_shipping_fee_air || 0), + shipping_price_within: domesticShippingFeeData?.total_shipping_fee || 0, + currency: userStore.user?.currency || '', + forwarder_name: selectedWarehouse?.forwarder_name || '', + country_city: selectedWarehouseLabel, + timestamp: new Date().toISOString(), + } + logShippingConfirm(data,navigation.getState().routes[navigation.getState().index - 1]?.name as string) + console.log(getBurialPointData()); + navigation.navigate("PaymentMethod", {freight_forwarder_address_id: selectedWarehouse?.address_id || 0}); }else{ Alert.alert("请选择运输方式"); diff --git a/app/services/api/orders.ts b/app/services/api/orders.ts index 7bfaeb1..3836da2 100644 --- a/app/services/api/orders.ts +++ b/app/services/api/orders.ts @@ -5,6 +5,7 @@ import apiService from './apiClient'; export interface Address { address_id: number; user_id: number; + forwarder_name: string; receiver_first_name: string; receiver_last_name: string; country: string; diff --git a/app/services/api/productApi.ts b/app/services/api/productApi.ts index b9b78fc..b6baf32 100644 --- a/app/services/api/productApi.ts +++ b/app/services/api/productApi.ts @@ -58,9 +58,11 @@ export type Products = Product[] export interface Sku { "sku_id": 0, "price": number, + sku_image_url:string "spec_id": "string", "amount_on_sale": 0, "consign_price": 0, + quantity:number, "cargo_number": "string", "one_piece_price": 0, "offer_price": number, diff --git a/app/store/burialPoint.ts b/app/store/burialPoint.ts index bb74650..f828da6 100644 --- a/app/store/burialPoint.ts +++ b/app/store/burialPoint.ts @@ -25,6 +25,21 @@ type ProductProperty = { product_img: string; } +// 定义购物车属性类型 +type CartProperty = { + offer_id: number; + category_id: number; + price: number; + all_price: number; + currency: string; + sku_id: number; + quantity: number; + product_name: string; + timestamp: string; + sku_img: string; + all_quantity:number +} + // 定义搜索属性类型 type SearchProperty = { key_word: string; @@ -50,7 +65,6 @@ type ShippingProperty = { forwarder_name: string; country_city: string; timestamp: string; - product_list_text?: string; } // 定义支付方式属性类型 @@ -103,6 +117,7 @@ type BurialPointState = { logPaymentConfirm: (paymentInfo: Omit, fromPage?: string) => void; logPreviewOrder: (fromPage?: string) => void; logCheckout: (checkoutInfo: Omit, fromPage?: string) => void; + logAddToCart: (cartInfo: Omit, fromPage?: string) => void; clearData: () => void; } @@ -121,12 +136,36 @@ const useBurialPointStore = create((set, get) => ({ // 添加事件 addEvent: (event: BurialEvent) => { set((state) => { - const newEventList = [...state.event_list, event]; + // 检查是否已存在相同event_name, page_name, referre_page的事件 + const existingEventIndex = state.event_list.findIndex(item => + item.event_name === event.event_name && + item.page_name === event.page_name && + item.referre_page === event.referre_page + ); + + let newEventList = [...state.event_list]; + + if (existingEventIndex !== -1) { + // 如果存在相同事件,将新的event_properties添加到已存在事件的event_properties中 + const existingEvent = state.event_list[existingEventIndex]; + const updatedEvent = { + ...existingEvent, + event_properties: [...existingEvent.event_properties, ...event.event_properties] + }; + + // 更新现有事件 + newEventList[existingEventIndex] = updatedEvent; + } else { + // 如果不存在相同事件,添加新事件 + newEventList = [...state.event_list, event]; + } // 检查是否需要清理数据 if (newEventList.length >= 10) { // 这里可以在清理前添加发送数据到服务器的逻辑 console.log('Data cleared, event count:', newEventList.length); + console.log(getBurialPointData()); + return { event_list: [] }; } @@ -300,6 +339,23 @@ const useBurialPointStore = create((set, get) => ({ get().addEvent(checkoutEvent); }, + // 记录添加购物车事件埋点 + logAddToCart: (cartInfo: Omit, fromPage = "search") => { + const addToCartEvent: BurialEvent = { + event_name: "add_to_cart", + page_name: "add_to_cart", + referre_page: fromPage, + event_properties: [ + { + ...cartInfo, + timestamp: getCurrentFormattedTime() + } + ] + }; + + get().addEvent(addToCartEvent); + }, + // 清空数据 clearData: () => { // 这里可以添加发送数据到服务器的逻辑 diff --git a/app/store/productCart.ts b/app/store/productCart.ts index 56e81ec..e88ab55 100644 --- a/app/store/productCart.ts +++ b/app/store/productCart.ts @@ -85,7 +85,7 @@ const useProductCartStore = create((set, get) => ({ setNoImgList: (noImgList: Sku[]) => set({ noImgList }), setFlag: (flag: boolean) => set({ flag }), processProductData: () => { - const { groupList, product, offer_id, setOfferId } = get(); + const { groupList, product, offer_id, setOfferId, hasImg: existingHasImg, noImgList: existingNoImgList } = get(); set({ price: product.price as number }); if (product) { if (offer_id !== product.offer_id) { @@ -151,13 +151,48 @@ const useProductCartStore = create((set, get) => ({ } }); }); + + // 保留之前选择的数量信息 + if (existingHasImg && offer_id === product.offer_id) { + processedImg.attributes.forEach((attr, attrIndex) => { + // 查找匹配的属性 + const existingAttr = existingHasImg.attributes?.find(ea => ea.value === attr.value); + if (existingAttr) { + // 保留颜色选择状态 + attr.has_color = existingAttr.has_color; + // 保留总数量 + attr.size = existingAttr.size; + + // 保留每个列表项的数量 + attr.list.forEach((item, itemIndex) => { + const matchingExistingItem = existingAttr.list?.find( + ei => ei.sku_id === item.sku_id + ); + if (matchingExistingItem && matchingExistingItem.size) { + item.size = matchingExistingItem.size; + } + }); + } + }); + } set({ hasImg: processedImg }); } else { set({ hasImg: groupList[0] }); } } else { - set({ noImgList: product.skus }); + // 处理noImgList,保留之前的数量信息 + const newNoImgList = product.skus.map(sku => { + if (existingNoImgList && offer_id === product.offer_id) { + // 查找匹配的已存在项目 + const existingItem = existingNoImgList.find(item => item.sku_id === sku.sku_id); + if (existingItem && existingItem.size) { + return {...sku, size: existingItem.size}; + } + } + return sku; + }); + set({ noImgList: newNoImgList }); } const img = groupList @@ -166,6 +201,27 @@ const useProductCartStore = create((set, get) => ({ set({ size: img?.value ?? "" }); setOfferId(product.offer_id); + + // 重新计算总数量和总价格 + const hasImgData = get().hasImg; + if (Object.keys(hasImgData).length > 0) { + get().calculateTotalSize(hasImgData); + } else { + const noImgList = get().noImgList; + if (noImgList && noImgList.length > 0) { + 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) - 1 + ]?.price) || 0) * (item.size ?? 0); + }); + set({ selectedSize: total, totalPrice: priceSum }); + } + } } }, handleColorSelect: (