Browse Source

埋点

main
Your Name 3 weeks ago
parent
commit
fd6f7a8dfc
  1. 2
      App.tsx
  2. 2
      app/screens/CartScreen.tsx
  3. 2
      app/screens/MainApp.tsx
  4. 164
      app/screens/ProductCard.tsx
  5. 31
      app/screens/ProductDetailScreen.tsx
  6. 7
      app/screens/SearchScreen.tsx
  7. 10
      app/screens/loginList/PhoneLoginModal.tsx
  8. 38
      app/screens/previewOrder/PaymentMethod.tsx
  9. 16
      app/screens/previewOrder/PreviewAddress.tsx
  10. 17
      app/screens/previewOrder/ShippingFee.tsx
  11. 1
      app/services/api/orders.ts
  12. 2
      app/services/api/productApi.ts
  13. 60
      app/store/burialPoint.ts
  14. 60
      app/store/productCart.ts

2
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();

2
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,

2
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';

164
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<ProductCardProps> = ({
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,10 +105,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
}
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) => {
item.list?.forEach((item) => {
if ((item.size ?? 0) > 0) {
skus.push({
sku_id: item.sku_id,
@ -121,8 +121,29 @@ const ProductCard: React.FC<ProductCardProps> = ({
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 =
@ -139,7 +160,32 @@ const ProductCard: React.FC<ProductCardProps> = ({
skus,
};
cartApi(data).then((res) => {
console.log(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<ProductCardProps> = ({
<TouchableOpacity
style={[
styles.productBoxImgListBox,
item.has_color && styles.productBoxImgListBoxActive,
item?.has_color && styles.productBoxImgListBoxActive,
]}
key={index}
onPress={() =>
handleColorSelect(
item.value,
item?.value || '',
index,
item.sku_image_url
item?.sku_image_url || ''
)
}
>
<Image
source={{ uri: item.sku_image_url }}
source={{ uri: item?.sku_image_url || '' }}
style={styles.productBoxImgListBoxImg}
/>
{item.size && (
{(item?.size ?? 0) > 0 && (
<View style={styles.fixedCornerView}>
<Text style={styles.fixedCornerViewText}>
x{item.size}
@ -312,7 +358,7 @@ const ProductCard: React.FC<ProductCardProps> = ({
<View style={styles.sizePriceBox}>
{hasImg &&
hasImg.attributes
?.find((item) => item.has_color)
?.find((item) => item?.has_color)
?.list.map((list, index1) => (
<View style={styles.sizePriceBoxItems} key={index1}>
<View style={styles.sizePriceBoxItem}>
@ -323,18 +369,18 @@ const ProductCard: React.FC<ProductCardProps> = ({
</Text>
)}
<Text style={styles.priceText}>
{list.offer_price || price}
{list?.offer_price || price || 0}
</Text>
<Text
style={styles.sizePriceBoxItemText}
numberOfLines={1}
ellipsizeMode="tail"
>
{list.attributes[0].value}
{list.attributes?.[0]?.value}
</Text>
</View>
<Text style={styles.amountText}>
{list?.amount_on_sale}
{list?.amount_on_sale ?? 0}
</Text>
</View>
<View style={styles.sizePriceBoxStepForward}>
@ -342,10 +388,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
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<ProductCardProps> = ({
</TouchableOpacity>
<TextInput
style={styles.sizePriceBoxStepForwardInput}
value={list.size?.toString() ?? "0"}
value={list?.size?.toString() ?? "0"}
keyboardType="numeric"
onChangeText={(text) =>
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<ProductCardProps> = ({
style={styles.sizePriceBoxStepForwardButton}
onPress={() =>
handleSizeSelect(
list?.attributes[0]?.value,
list?.attributes?.[0]?.value,
"+",
index1,
list.amount_on_sale
list?.amount_on_sale ?? 0
)
}
>
@ -389,7 +435,7 @@ const ProductCard: React.FC<ProductCardProps> = ({
{hasImg && groupList.length > 1 && !hasImg.has_image && (
<View style={styles.productBox}>
<View style={styles.productTit}>
<Text style={styles.productTitText}>{hasImg.attribute_name}</Text>
<Text style={styles.productTitText}>{hasImg?.attribute_name || ''}</Text>
</View>
{hasImg.attributes?.map((item, index) => {
@ -397,17 +443,17 @@ const ProductCard: React.FC<ProductCardProps> = ({
<TouchableOpacity
style={[
styles.noImgBoxs,
item.has_color && styles.productBoxImgListBoxActive,
item?.has_color && styles.productBoxImgListBoxActive,
]}
key={index}
onPress={() => {
handleColorSelect(item.value, index, item.sku_image_url);
handleColorSelect(item?.value || '', index, item?.sku_image_url || '');
}}
>
{(item?.size ?? 0) > 0 && (
<Text style={styles.selectedNumText}>x{item?.size}</Text>
)}
<Text style={styles.noImgBoxsText}>{item.value}</Text>
<Text style={styles.noImgBoxsText}>{item?.value || ''}</Text>
</TouchableOpacity>
);
})}
@ -424,7 +470,7 @@ const ProductCard: React.FC<ProductCardProps> = ({
<View style={styles.sizePriceBox}>
{hasImg &&
hasImg.attributes
?.find((item) => item.has_color)
?.find((item) => item?.has_color)
?.list.map((list, index1) => (
<View style={styles.sizePriceBoxItems} key={index1}>
<View style={styles.sizePriceBoxItem}>
@ -435,18 +481,18 @@ const ProductCard: React.FC<ProductCardProps> = ({
</Text>
)}
<Text style={styles.priceText}>
{list.offer_price || price}
{list?.offer_price || price || 0}
</Text>
<Text
style={styles.sizePriceBoxItemText}
numberOfLines={1}
ellipsizeMode="tail"
>
{list.attributes[0].value}
{list.attributes?.[0]?.value}
</Text>
</View>
<Text style={styles.amountText}>
{list?.amount_on_sale}
{list?.amount_on_sale ?? 0}
</Text>
</View>
<View style={styles.sizePriceBoxStepForward}>
@ -454,10 +500,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
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<ProductCardProps> = ({
</TouchableOpacity>
<TextInput
style={styles.sizePriceBoxStepForwardInput}
value={list.size?.toString() ?? "0"}
value={list?.size?.toString() ?? "0"}
keyboardType="numeric"
onChangeText={(text) =>
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<ProductCardProps> = ({
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<ProductCardProps> = ({
</Text>
)}
<Text style={styles.priceText}>
{list.offer_price || price}
{list?.offer_price || price || 0}
</Text>
<Text
style={styles.sizePriceBoxItemText}
numberOfLines={1}
ellipsizeMode="tail"
>
{list.attributes[0].value}
{list.attributes?.[0]?.value}
</Text>
</View>
<Text style={styles.amountText}>
{list?.amount_on_sale}
{list?.amount_on_sale ?? 0}
</Text>
</View>
<View style={styles.sizePriceBoxStepForward}>
@ -538,10 +584,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
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<ProductCardProps> = ({
</TouchableOpacity>
<TextInput
style={styles.sizePriceBoxStepForwardInput}
value={list.size?.toString() ?? "0"}
value={list?.size?.toString() ?? "0"}
keyboardType="numeric"
onChangeText={(text) =>
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<ProductCardProps> = ({
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<ProductCardProps> = ({
<View style={styles.allImageBox} key={index1}>
<View style={styles.allImageBoxImg}>
<Image
source={{ uri: list.attributes[0].sku_image_url }}
source={{ uri: list.attributes?.[0]?.sku_image_url }}
style={styles.allImageBoxImgImg}
/>
</View>
@ -616,19 +662,19 @@ const ProductCard: React.FC<ProductCardProps> = ({
marginRight: 5,
}}
>
{list.offer_price || price}
{list?.offer_price || price || 0}
</Text>
<Text
style={styles.allImageBoxListBoxText}
numberOfLines={1}
ellipsizeMode="tail"
>
{list.attributes[0].value}
{list.attributes?.[0]?.value}
</Text>
</View>
<Text style={styles.amountText}>
{list?.amount_on_sale}
{list?.amount_on_sale ?? 0}
</Text>
</View>
<View style={styles.allImageBoxListStop}>
@ -636,10 +682,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
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<ProductCardProps> = ({
<TextInput
style={styles.sizePriceBoxStepForwardInput}
keyboardType="numeric"
value={list.size?.toString() ?? "0"}
value={list?.size?.toString() ?? "0"}
onChangeText={(text) =>
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<ProductCardProps> = ({
style={styles.sizePriceBoxStepForwardButton}
onPress={() =>
handleNoImgSizeSelect(
list.attributes[0]?.value,
list.attributes?.[0]?.value,
"+",
index1,
list.amount_on_sale
list?.amount_on_sale ?? 0
)
}
>

31
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 = () => {

7
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<NativeStackNavigationProp<any>>();
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]);

10
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,6 +103,7 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => {
const navigation =
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
const { setSettings, setUser } = useUserStore();
const { logLogin, } = useBurialPointStore();
// Phone login state
const [phoneNumber, setPhoneNumber] = 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('用户名或密码错误')

38
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,6 +389,41 @@ 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 {

16
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<NativeStackNavigationProp<RootStackParamList>>();
const route = useRoute<AddRessRouteProp>();
const { logAddressInfo } = useBurialPointStore();
const [open, setOpen] = useState(false);
const [value, setValue] = useState<string | null>(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,
});

17
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<number>();
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("请选择运输方式");

1
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;

2
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,

60
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<PaymentProperty, "timestamp">, fromPage?: string) => void;
logPreviewOrder: (fromPage?: string) => void;
logCheckout: (checkoutInfo: Omit<CheckoutProperty, "timestamp">, fromPage?: string) => void;
logAddToCart: (cartInfo: Omit<CartProperty, "timestamp">, fromPage?: string) => void;
clearData: () => void;
}
@ -121,12 +136,36 @@ const useBurialPointStore = create<BurialPointState>((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<BurialPointState>((set, get) => ({
get().addEvent(checkoutEvent);
},
// 记录添加购物车事件埋点
logAddToCart: (cartInfo: Omit<CartProperty, "timestamp">, 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: () => {
// 这里可以添加发送数据到服务器的逻辑

60
app/store/productCart.ts

@ -85,7 +85,7 @@ const useProductCartStore = create<ProductCartState>((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) {
@ -152,12 +152,47 @@ const useProductCartStore = create<ProductCartState>((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<ProductCartState>((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: (

Loading…
Cancel
Save