diff --git a/App.tsx b/App.tsx
index b408e33..0ce63dc 100644
--- a/App.tsx
+++ b/App.tsx
@@ -4,16 +4,27 @@ import { useEffect, useState } from "react";
import { userApi } from "./app/services/api/userApi";
import useUserStore from "./app/store/user";
import useBurialPointStore from "./app/store/burialPoint";
-import { AuthProvider, useAuth } from "./app/contexts/AuthContext";
+import { AuthProvider, useAuth, AUTH_EVENTS } from "./app/contexts/AuthContext";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { AppNavigator } from "./app/navigation/AppNavigator";
import { View, ActivityIndicator, Alert } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import "./app/i18n";
-import * as Linking from 'expo-linking';
+import * as Linking from "expo-linking";
+import { EventEmitter } from 'events';
+
+// 声明全局事件发射器类型
+declare global {
+ var EventEmitter: EventEmitter;
+}
+
+// 创建全局事件发射器
+if (!global.EventEmitter) {
+ global.EventEmitter = new EventEmitter();
+}
// 定义全局事件处理支付成功
-export const PAYMENT_SUCCESS_EVENT = 'PAYMENT_SUCCESS_EVENT';
+export const PAYMENT_SUCCESS_EVENT = "PAYMENT_SUCCESS_EVENT";
function AppContent() {
const { setUser } = useUserStore();
@@ -21,12 +32,22 @@ function AppContent() {
const { logAppLaunch } = useBurialPointStore();
const [isLoading, setIsLoading] = useState(true);
+ // 获取用户资料的函数
+ const fetchUserProfile = async () => {
+ try {
+ const user = await userApi.getProfile();
+ setUser(user);
+ return true;
+ } catch (error) {
+ console.error('Failed to fetch user profile:', error);
+ return false;
+ }
+ };
+
useEffect(() => {
const initApp = async () => {
try {
-
- const user = await userApi.getProfile();
- setUser(user);
+ await fetchUserProfile();
// 记录应用启动成功埋点
logAppLaunch(true);
@@ -42,24 +63,38 @@ function AppContent() {
initApp();
}, []);
+ // 监听登录成功事件,刷新用户资料
+ useEffect(() => {
+ const handleLoginSuccess = () => {
+ fetchUserProfile();
+ };
+
+ // 注册事件监听器
+ global.EventEmitter.on(AUTH_EVENTS.LOGIN_SUCCESS, handleLoginSuccess);
+
+ // 清理函数
+ return () => {
+ global.EventEmitter.off(AUTH_EVENTS.LOGIN_SUCCESS, handleLoginSuccess);
+ };
+ }, []);
+
// 添加深度链接处理
useEffect(() => {
// 处理深度链接
const handleDeepLink = ({ url }: { url: string }) => {
- console.log('Global deep link received:', url);
if (
- url.startsWith('myapp://payment-success') ||
- url.startsWith('exp://192.168.0.101:8084/--/payment-success')
+ url.startsWith("myapp://payment-success") ||
+ url.startsWith("exp://192.168.0.101:8084/--/payment-success")
) {
// 解析参数
const parsed = Linking.parse(url);
const params = parsed.queryParams || {};
- const paymentId = params.paymentId || '';
- const token = params.token || '';
- const payerId = params.PayerID || '';
-
+ const paymentId = params.paymentId || "";
+ const token = params.token || "";
+ const payerId = params.PayerID || "";
+
Alert.alert(
- '支付成功!',
+ "支付成功!",
`支付ID: ${paymentId}\nToken: ${token}\nPayerID: ${payerId}`
);
// 这里可以做页面跳转或业务处理
@@ -67,11 +102,11 @@ function AppContent() {
};
// 注册深度链接监听器
- const subscription = Linking.addEventListener('url', handleDeepLink);
+ const subscription = Linking.addEventListener("url", handleDeepLink);
// 处理应用冷启动的深度链接
Linking.getInitialURL().then((url) => {
- if (url && url.startsWith('myapp://payment-success')) {
+ if (url && url.startsWith("myapp://payment-success")) {
handleDeepLink({ url });
}
});
@@ -81,7 +116,7 @@ function AppContent() {
if (isLoading) {
return (
-
+
);
diff --git a/app/constants/productStatus.ts b/app/constants/productStatus.ts
index 6e9c73c..b2f0419 100644
--- a/app/constants/productStatus.ts
+++ b/app/constants/productStatus.ts
@@ -12,9 +12,9 @@ export const productStatus: ProductStatus[] = [
{ icon: PdfDocumentIcon, text: '待付款', textKey: 'order.status.waiting_payment', status: 0 },
// { icon: DocumentClockIcon, text: '付运费', textKey: 'order.status.pay_shipping', status: 6 },
{ icon: DocumentClockIcon, text: '待发货', textKey: 'order.status.waiting_shipment', status: 1 },
- { icon: DocumentApprovedIcon, text: '运输中', textKey: 'order.status.in_transit', status: 7 },
- { icon: DocumentApprovedIcon, text: '代收货', textKey: 'order.status.waiting_receipt', status: 2 },
- { icon: PdfDocumentIcon, text: '已完成', textKey: 'order.status.completed', status: 3 },
- { icon: DocumentClockIcon, text: '已取消', textKey: 'order.status.cancelled', status: 4 },
- { icon: DocumentClockIcon, text: '已退款', textKey: 'order.status.refunded', status: 5 }
+ { icon: DocumentApprovedIcon, text: '运输中', textKey: 'order.status.in_transit', status: 2 },
+ { icon: DocumentApprovedIcon, text: '代收货', textKey: 'order.status.waiting_receipt', status: 3 },
+ { icon: PdfDocumentIcon, text: '已完成', textKey: 'order.status.completed', status: 4 },
+ { icon: DocumentClockIcon, text: '已取消', textKey: 'order.status.cancelled', status: 5 },
+ { icon: DocumentClockIcon, text: '已退款', textKey: 'order.status.refunded', status: 6 }
]
\ No newline at end of file
diff --git a/app/contexts/AuthContext.tsx b/app/contexts/AuthContext.tsx
index b5eeaa6..a68ce5e 100644
--- a/app/contexts/AuthContext.tsx
+++ b/app/contexts/AuthContext.tsx
@@ -1,5 +1,16 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
+import { EventEmitter } from 'events';
+
+// 声明全局事件发射器类型
+declare global {
+ var EventEmitter: EventEmitter;
+}
+
+// 添加自定义事件
+export const AUTH_EVENTS = {
+ LOGIN_SUCCESS: 'LOGIN_SUCCESS'
+};
type AuthContextType = {
isLoggedIn: boolean;
@@ -30,6 +41,11 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
try {
await AsyncStorage.setItem('isLoggedIn', 'true');
setIsLoggedIn(true);
+
+ // 发出登录成功事件通知
+ if (global.EventEmitter) {
+ global.EventEmitter.emit(AUTH_EVENTS.LOGIN_SUCCESS);
+ }
} catch (error) {
console.error('Error logging in:', error);
}
diff --git a/app/i18n/index.ts b/app/i18n/index.ts
index 0a6626d..cad4663 100644
--- a/app/i18n/index.ts
+++ b/app/i18n/index.ts
@@ -12,6 +12,9 @@ const LANGUAGE_KEY = '@app_language';
// 获取设备语言
const deviceLanguage = Localization.locale.split('-')[0];
+// 确定使用的语言:仅在系统语言为法语时使用法语,其他语言一律使用英语
+const initialLanguage = deviceLanguage === 'fr' ? 'fr' : 'en';
+
// 初始化 i18n
i18n
.use(initReactI18next)
@@ -27,7 +30,7 @@ i18n
translation: frTranslation
}
},
- lng: deviceLanguage, // 使用设备语言
+ lng: initialLanguage, // 根据逻辑设置初始语言
fallbackLng: 'en', // 如果找不到翻译,使用英语
interpolation: {
escapeValue: false // 不需要转义 HTML
@@ -40,7 +43,9 @@ const loadLanguage = async () => {
try {
const savedLanguage = await AsyncStorage.getItem(LANGUAGE_KEY);
if (savedLanguage) {
- i18n.changeLanguage(savedLanguage);
+ // 仅接受法语或英语作为有效选择
+ const validLanguage = savedLanguage === 'fr' ? 'fr' : 'en';
+ i18n.changeLanguage(validLanguage);
}
} catch (error) {
console.error('加载语言设置失败:', error);
@@ -58,10 +63,12 @@ const saveLanguage = async (language: string) => {
// 修改语言切换函数
export const changeLanguage = async (language: string) => {
- await saveLanguage(language);
- i18n.changeLanguage(language);
+ // 仅接受法语或英语作为有效选择
+ const validLanguage = language === 'fr' ? 'fr' : 'en';
+ await saveLanguage(validLanguage);
+ i18n.changeLanguage(validLanguage);
- console.log("切换语言:" + language);
+ console.log("切换语言:" + validLanguage);
};
diff --git a/app/navigation/TabNavigator.tsx b/app/navigation/TabNavigator.tsx
index 1fe27a8..99b0ffe 100644
--- a/app/navigation/TabNavigator.tsx
+++ b/app/navigation/TabNavigator.tsx
@@ -163,7 +163,7 @@ export const TabNavigator = () => {
}}
/>
;
export const BalanceScreen = () => {
+ const { user } = useUserStore();
const navigation = useNavigation();
const [isModalVisible, setIsModalVisible] = useState(false);
+ const [rechargeHistory, setRechargeHistory] = useState([]);
const handleOpenModal = () => {
setIsModalVisible(true);
@@ -26,6 +29,14 @@ export const BalanceScreen = () => {
setIsModalVisible(false);
};
+ useEffect(() => {
+ const fetchRechargeHistory = async () => {
+ const response = await payApi.getRechargeHistory();
+ setRechargeHistory(response);
+ }
+ fetchRechargeHistory();
+ }, []);
+
return (
@@ -60,13 +71,13 @@ export const BalanceScreen = () => {
- 650,000
+ {user?.balance}
{/* SVG or icon replacement */}
- Solde Total (FCFA)
+ Solde Total ({user?.currency})
50,000
@@ -90,87 +101,28 @@ export const BalanceScreen = () => {
Détail du solde
-
- {/* Repeated Transaction Details */}
-
-
-
- Frais de transport
-
- -58 FCFA
-
-
- 2025-02-12
- BR-11-00010
-
-
- {/* Additional transaction panels can be added here */}
-
-
- {/* Repeated Transaction Details */}
-
-
-
- Frais de transport
-
- -58 FCFA
-
-
- 2025-02-12
- BR-11-00010
-
-
- {/* Additional transaction panels can be added here */}
-
-
- {/* Repeated Transaction Details */}
-
-
-
- Frais de transport
-
- -58 FCFA
-
-
- 2025-02-12
- BR-11-00010
-
-
- {/* Additional transaction panels can be added here */}
-
-
- {/* Repeated Transaction Details */}
-
-
-
- Frais de transport
-
- -58 FCFA
-
-
- 2025-02-12
- BR-11-00010
-
-
- {/* Additional transaction panels can be added here */}
-
-
- {/* Repeated Transaction Details */}
-
-
-
- Frais de transport
-
- -58 FCFA
-
-
- 2025-02-12
- BR-11-00010
-
-
- {/* Additional transaction panels can be added here */}
-
+ {rechargeHistory.map((item) => (
+
+ {/* Repeated Transaction Details */}
+
+
+
+ {item.payment_method}
+
+ {item.amount} {item.currency}
+
+
+ {item.create_time}
+ {item.transaction_id}
+
+
+ {/* Additional transaction panels can be added here */}
+
+ ))}
+
+
+
diff --git a/app/screens/CategoryScreen.tsx b/app/screens/CategoryScreen.tsx
index 90b1e44..d9c61cb 100644
--- a/app/screens/CategoryScreen.tsx
+++ b/app/screens/CategoryScreen.tsx
@@ -16,8 +16,20 @@ import {
import fontSize from '../utils/fontsizeUtils';
import widthUtils from '../utils/widthUtils';
import { categoriesApi, Category } from '../services/api/categories';
+import { useNavigation } from '@react-navigation/native';
+import { NativeStackNavigationProp } from "@react-navigation/native-stack";
+import { RootStackParamList } from '../types/navigation';
+
+const { width: SCREEN_WIDTH } = Dimensions.get('window');
+const MENU_WIDTH = widthUtils(120, 120).width;
+const AVAILABLE_WIDTH = SCREEN_WIDTH - MENU_WIDTH - 20; // 20 for padding
+const NUM_COLUMNS = 4;
+const ITEM_MARGIN = '2.66%';
+const ITEM_WIDTH = (AVAILABLE_WIDTH / NUM_COLUMNS) - (AVAILABLE_WIDTH * 0.0266);
+
export const CategoryScreen = () => {
+ const navigation = useNavigation>();
const [mainCategories, setMainCategories] = useState([]);
const [subCategories, setSubCategories] = useState([]);
const [activeMainCategory, setActiveMainCategory] = useState(null);
@@ -85,18 +97,25 @@ export const CategoryScreen = () => {
const renderSubCategoryItem: ListRenderItem = ({ item }) => (
{}}
+ style={styles.subCategoryItem}
+ onPress={() => {
+ navigation.navigate('SearchResult', { keyword: item.name_en.trim() });
+ }}
>
-
- {item.name_cn}
-
+
+
+
+ {item.name_cn}
+
+
);
@@ -130,8 +149,9 @@ export const CategoryScreen = () => {
data={subCategories}
renderItem={renderSubCategoryItem}
keyExtractor={(item) => item.category_id.toString()}
- numColumns={3}
+ numColumns={NUM_COLUMNS}
contentContainerStyle={styles.productGrid}
+ columnWrapperStyle={styles.columnWrapper}
/>
)}
@@ -155,7 +175,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
},
leftMenu: {
- width: widthUtils(100,100).width,
+ width: MENU_WIDTH,
backgroundColor: '#fff',
borderRightWidth: 1,
borderColor: '#eee',
@@ -179,7 +199,7 @@ const styles = StyleSheet.create({
},
rightContent: {
flex: 1,
- backgroundColor: '#f8f8f8',
+ backgroundColor: '#ffffff',
paddingHorizontal: 10,
paddingTop: 12,
},
@@ -192,4 +212,28 @@ const styles = StyleSheet.create({
alignItems: 'center',
backgroundColor: '#fff',
},
+ columnWrapper: {
+ justifyContent: 'flex-start',
+ marginBottom: 15,
+ },
+ subCategoryItem: {
+ width: ITEM_WIDTH,
+ overflow: 'hidden',
+ marginRight: ITEM_MARGIN,
+ },
+ subCategoryImage: {
+ width: '100%',
+ height: ITEM_WIDTH,
+ },
+ subCategoryInfo: {
+ padding: 8,
+ height: 26,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ subCategoryName: {
+ fontSize: fontSize(12),
+ color: '#333',
+ textAlign: 'center',
+ },
});
diff --git a/app/screens/ChatScreen.tsx b/app/screens/ChatScreen.tsx
index 3599699..911313d 100644
--- a/app/screens/ChatScreen.tsx
+++ b/app/screens/ChatScreen.tsx
@@ -29,7 +29,7 @@ interface Message {
mimetype: string;
userWs: string;
app_id: string;
- country: string;
+ country: number;
body: string;
text: string;
type: string;
@@ -130,10 +130,10 @@ export const ChatScreen = () => {
mimetype: "text/plain",
userWs: "unknown",
app_id: user.user_id ? user.user_id.toString() : "",
- country: country,
+ country: user.country_code,
body: "",
text: inputText,
- type: "chat",
+ type: "text",
isMe: true,
timestamp: new Date(),
id: Date.now().toString(), // Add unique id for keyExtractor
@@ -160,7 +160,7 @@ export const ChatScreen = () => {
mimetype: "text/plain",
userWs: "system",
app_id: "system",
- country: country,
+ country: user.country_code,
body: "",
text: `${t('typingMessage')}...`,
type: "chat",
@@ -174,8 +174,11 @@ export const ChatScreen = () => {
setMessages(prevMessages => [...prevMessages, simulatedResponse]);
}, 800);
+ const data = {
+ newMessage:chatServiceMessage,
+ }
// Send actual message to API
- chatService.sendMessage(chatServiceMessage)
+ chatService.sendMessage(data)
.then(response => {
// When real response arrives, replace simulated message
setMessages(prevMessages => {
@@ -187,7 +190,7 @@ export const ChatScreen = () => {
mimetype: "text/plain",
userWs: "system",
app_id: "system",
- country: country,
+ country: user.country_code,
body: "",
text: response?.text || t('defaultResponse'),
type: "chat",
@@ -209,7 +212,7 @@ export const ChatScreen = () => {
mimetype: "text/plain",
userWs: "system",
app_id: "system",
- country: country,
+ country: user.country_code,
body: "",
text: t('errorResponse'),
type: "chat",
diff --git a/app/screens/ProfileScreen.tsx b/app/screens/ProfileScreen.tsx
index 83bdc53..e1984a3 100644
--- a/app/screens/ProfileScreen.tsx
+++ b/app/screens/ProfileScreen.tsx
@@ -94,15 +94,17 @@ export const ProfileScreen = () => {
ID: {user?.user_id}
- navigation.navigate("Balance")}
- >
-
-
-
- 余额
-
+ {user.user_id && (
+ navigation.navigate("Balance")}
+ >
+
+
+
+ 余额
+
+ )}
@@ -136,7 +138,7 @@ export const ProfileScreen = () => {
- {t('profile.vip.next_level_info')}
+ {t("profile.vip.next_level_info")}
{
}
>
- {t('profile.learn_more')}
+ {t("profile.learn_more")}
@@ -213,14 +215,18 @@ export const ProfileScreen = () => {
- {t("order.title")}
+
+ {t("order.title")}
+
navigation.navigate("Status", { status: null })
}
>
- {t("all")}
+
+ {t("all")}
+
@@ -253,7 +259,9 @@ export const ProfileScreen = () => {
- {t("tool.title")}
+
+ {t("tool.title")}
+
@@ -267,7 +275,9 @@ export const ProfileScreen = () => {
color="#707070"
/>
- {t("browse.history")}
+
+ {t("browse.history")}
+
@@ -277,7 +287,9 @@ export const ProfileScreen = () => {
>
- {t("collection")}
+
+ {t("collection")}
+
{
- {t("address.management")}
+
+ {t("address.management")}
+
@@ -295,8 +309,8 @@ export const ProfileScreen = () => {
{/* Login Button at bottom of screen */}
-
{t("login.now")}
diff --git a/app/screens/RechargeScreen.tsx b/app/screens/RechargeScreen.tsx
index 0d1cc81..0c5621f 100644
--- a/app/screens/RechargeScreen.tsx
+++ b/app/screens/RechargeScreen.tsx
@@ -23,7 +23,7 @@ import CheckIcon from "../components/CheckIcon";
import BackIcon from "../components/BackIcon";
// 添加导航相关导入
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation } from "@react-navigation/native";
import { navigationRef } from "../navigation/RootNavigation";
// 添加API服务
@@ -43,13 +43,15 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 指定导航类型为any
const navigation = useNavigation();
- const [convertedAmount, setConvertedAmount] = useState<{
- converted_amount: number;
- item_key: string;
- original_amount: number;
- }[]>([]);
+ const [convertedAmount, setConvertedAmount] = useState<
+ {
+ converted_amount: number;
+ item_key: string;
+ original_amount: number;
+ }[]
+ >([]);
const [currentCurrency, setCurrentCurrency] = useState("USD");
- const [phoneNumber, setPhoneNumber] = useState('22660962235');
+ const [phoneNumber, setPhoneNumber] = useState("22660962235");
const [isSubmitting, setIsSubmitting] = useState(false);
const [paymentParams, setPaymentParams] = useState<{
originalAmount: number;
@@ -61,7 +63,7 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
const handlePriceSelect = (price: string) => {
setSelectedPrice(price);
-
+
// 如果当前已选择了货币转换,则重新计算转换后的金额
if (selectedOperator === "currency" && currentCurrency !== "FCFA") {
handleCurrencyConversion(price, currentCurrency);
@@ -70,7 +72,7 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
const handleOperatorSelect = (operator: string) => {
setSelectedOperator(operator === selectedOperator ? null : operator);
-
+
// 如果选择了货币支付方式,立即进行货币转换
if (operator === "currency" && operator !== selectedOperator) {
// 触发货币转换,使用默认的USD
@@ -86,13 +88,13 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
if (selectedOperator) {
// 准备支付参数,方便后续发送
const params = {
- originalAmount: parseFloat(selectedPrice.replace(/,/g, '')),
- amount: parseFloat(selectedPrice.replace(/,/g, '')),
+ originalAmount: parseFloat(selectedPrice.replace(/,/g, "")),
+ amount: parseFloat(selectedPrice.replace(/,/g, "")),
currency: "FCFA",
payment_method: "",
- selectedPriceLabel: selectedPrice + " FCFA" // 选择的充值面额
+ selectedPriceLabel: selectedPrice + " FCFA", // 选择的充值面额
};
-
+
// 根据selectedOperator确定支付方式
if (selectedOperator === "orange") {
params.payment_method = "Orange Money";
@@ -104,27 +106,22 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 当选择了货币转换时
params.payment_method = "paypal";
params.currency = currentCurrency; // 使用选择的货币
-
+
// 使用转换后的金额,如果有
if (convertedAmount.length > 0) {
- const convertedTotal = convertedAmount.find(item => item.item_key === 'total_amount');
+ const convertedTotal = convertedAmount.find(
+ (item) => item.item_key === "total_amount"
+ );
if (convertedTotal) {
params.amount = convertedTotal.converted_amount;
}
}
}
-
+
// 保存支付参数
setPaymentParams(params);
-
- // 打印支付信息
- console.log("Payment Information:");
- console.log("Selected Recharge Amount:", params.selectedPriceLabel);
- console.log("Original Amount:", params.originalAmount, "FCFA");
- console.log("Converted Amount:", params.amount);
- console.log("Currency:", params.currency);
- console.log("Payment Method:", params.payment_method);
-
+
+
setShowBlankPage(true);
}
};
@@ -132,22 +129,22 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 提取一个专门用于货币转换的函数
const handleCurrencyConversion = (price: string, currency: string) => {
setIsConverting(true);
-
+
// 格式化金额,去除逗号
- const amount = parseFloat(price.replace(/,/g, ''));
-
+ const amount = parseFloat(price.replace(/,/g, ""));
+
// 如果金额为0或无效,则不进行转换
if (!amount || isNaN(amount)) {
console.warn("Invalid amount for currency conversion");
setIsConverting(false);
return;
}
-
+
console.log(`Converting ${amount} FCFA to ${currency}...`);
-
+
// 调用货币转换API
const data = {
- from_currency: 'FCFA',
+ from_currency: "FCFA",
to_currency: currency,
amounts: {
total_amount: amount,
@@ -155,10 +152,15 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
shipping_fee: 0,
},
};
-
- payApi.convertCurrency(data)
+
+ payApi
+ .convertCurrency(data)
.then((res) => {
- if (res && res.converted_amounts_list && res.converted_amounts_list.length > 0) {
+ if (
+ res &&
+ res.converted_amounts_list &&
+ res.converted_amounts_list.length > 0
+ ) {
console.log("Conversion successful:", res.converted_amounts_list);
setConvertedAmount(res.converted_amounts_list);
} else {
@@ -166,38 +168,30 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96; // 1 USD = 580 FCFA, 1 EUR = 655.96 FCFA
const convertedValue = amount / fallbackRate;
-
- setConvertedAmount([{
- converted_amount: convertedValue,
- item_key: 'total_amount',
- original_amount: amount
- }]);
-
- if (Platform.OS === 'web') {
- console.warn("Using fallback conversion rate due to API error");
- } else {
- Alert.alert("Info", "Taux de conversion approximatif utilisé");
- }
+
+ setConvertedAmount([
+ {
+ converted_amount: convertedValue,
+ item_key: "total_amount",
+ original_amount: amount,
+ },
+ ]);
}
})
.catch((error) => {
console.error("Currency conversion failed:", error);
-
+
// 使用近似汇率作为备用
const fallbackRate = currency === "USD" ? 580.0 : 655.96;
const convertedValue = amount / fallbackRate;
-
- setConvertedAmount([{
- converted_amount: convertedValue,
- item_key: 'total_amount',
- original_amount: amount
- }]);
-
- if (Platform.OS === 'web') {
- console.warn("Using fallback conversion rate due to API error");
- } else {
- Alert.alert("Info", "Taux de conversion approximatif utilisé");
- }
+
+ setConvertedAmount([
+ {
+ converted_amount: convertedValue,
+ item_key: "total_amount",
+ original_amount: amount,
+ },
+ ]);
})
.finally(() => {
setIsConverting(false);
@@ -213,109 +207,73 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
// 更新处理支付提交的函数
const handlePaySubmit = async () => {
if (!paymentParams) {
- if (Platform.OS === 'web') {
- alert("Veuillez sélectionner un mode de paiement");
- } else {
- Alert.alert("Erreur", "Veuillez sélectionner un mode de paiement");
- }
return;
}
-
+
// 验证电话号码(添加更严格的验证)
if (!phoneNumber || phoneNumber.length < 8) {
- if (Platform.OS === 'web') {
- alert("Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)");
- } else {
- Alert.alert("Erreur", "Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)");
- }
+ Alert.alert(
+ "Erreur",
+ "Veuillez entrer un numéro de téléphone valide (au moins 8 chiffres)"
+ );
return;
}
-
+
// 显示提交中状态
setIsSubmitting(true);
-
+
try {
// 准备请求数据,添加电话号码
const rechargeData = {
amount: paymentParams.amount,
currency: paymentParams.currency,
payment_method: paymentParams.payment_method,
- phone: phoneNumber // 注意:如果后端API不支持此参数,可能需要调整
+ phone: phoneNumber, // 注意:如果后端API不支持此参数,可能需要调整
};
-
+
console.log("Submitting recharge request:", rechargeData);
-
+
// 调用充值接口(使用可选链避免错误)
const response = await payApi.initiateRecharge(rechargeData);
-
- console.log("Recharge response:", response);
-
if (response && response.success) {
const paymentInfo = response.payment;
-
- // 存储交易ID,以便后续查询
- if (Platform.OS === 'web') {
- sessionStorage.setItem('recharge_transaction_id', paymentInfo.transaction_id || '');
- sessionStorage.setItem('recharge_id', response.recharge_id?.toString() || '');
- }
-
+
// 检查是否有支付URL
if (paymentInfo && paymentInfo.payment_url) {
- // 记录重要信息到控制台
- console.log("Transaction ID:", paymentInfo.transaction_id);
- console.log("Recharge ID:", response.recharge_id);
- console.log("Payment URL:", paymentInfo.payment_url);
-
+ onClose();
// 打开支付页面
- navigation.navigate("Pay", {
- payUrl: paymentInfo.payment_url,
- });
-
- // Web平台添加额外提示,因为可能会被浏览器拦截
- if (Platform.OS === 'web') {
- setTimeout(() => {
- alert(`Si la page de paiement ne s'ouvre pas automatiquement, veuillez cliquer sur le bouton "Continuer" pour procéder au paiement. Vous pouvez également copier ce lien: ${paymentInfo.payment_url}`);
- }, 1500);
- }
+ setTimeout(() => {
+ navigation.navigate("Pay", {
+ payUrl: paymentInfo.payment_url,
+ });
+ }, 1000);
} else {
- // 没有支付URL但交易成功的情况
- if (Platform.OS === 'web') {
- alert("Votre recharge a été traitée avec succès!");
- onClose(); // 关闭充值页面
- } else {
- Alert.alert(
- "Succès",
- "Votre recharge a été traitée avec succès!",
- [{ text: "OK", onPress: onClose }]
- );
- }
+
+ Alert.alert("Succès", "Votre recharge a été traitée avec succès!", [
+ { text: "OK", onPress: onClose },
+ ]);
}
} else {
// 处理失败情况,显示错误消息
- const errorMessage = response?.msg || "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
-
- if (Platform.OS === 'web') {
- alert(errorMessage);
- } else {
- Alert.alert("Erreur", errorMessage);
- }
+ const errorMessage =
+ response?.msg ||
+ "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
+
+ Alert.alert("Erreur", errorMessage);
}
} catch (error) {
// 处理异常
console.error("Recharge error:", error);
-
- let errorMessage = "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
-
+
+ let errorMessage =
+ "Une erreur s'est produite lors du traitement de la recharge. Veuillez réessayer.";
+
// 尝试从错误对象中提取更具体的错误信息
if (error instanceof Error) {
errorMessage = error.message || errorMessage;
}
-
- if (Platform.OS === 'web') {
- alert(errorMessage);
- } else {
- Alert.alert("Erreur", errorMessage);
- }
+
+ Alert.alert("Erreur", errorMessage);
} finally {
// 无论成功失败,都取消提交状态
setIsSubmitting(false);
@@ -324,7 +282,9 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
return (
-
+
Recharger
{!showBlankPage && (
@@ -333,9 +293,12 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
)}
{showBlankPage && (
-
+
-
+
)}
@@ -512,24 +475,36 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{/* 支付方式标题 */}
- Choisissez votre mode de paiement
+
+ Choisissez votre mode de paiement
+
{/* Tab Bar */}
- setActiveTab(0)}
>
-
+
Mode de paiement
- setActiveTab(1)}
>
-
+
Autre
@@ -546,7 +521,9 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
justifyContent: "space-between",
}}
>
-
+
{
Nous ne supportons que{"\n"}les opérateurs affichés.
- handleOperatorSelect("orange")}>
+ handleOperatorSelect("orange")}
+ >
{selectedOperator === "orange" && (
@@ -599,12 +582,18 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{/* 右侧圆圈图标 */}
- handleOperatorSelect("mtn")}>
+ handleOperatorSelect("mtn")}
+ >
{selectedOperator === "mtn" && (
@@ -630,14 +619,22 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{/* 圆形图标(右边) */}
- handleOperatorSelect("balance")}>
+ handleOperatorSelect("balance")}
+ >
{selectedOperator === "balance" && (
@@ -654,15 +651,21 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
source={require("../../assets/img/image_8786995c.png")}
style={styles.currencyImage}
/>
- handleOperatorSelect("currency")}>
+ handleOperatorSelect("currency")}
+ >
{selectedOperator === "currency" && (
@@ -675,31 +678,77 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{selectedOperator === "currency" && (
<>
- Choisissez la devise
+
+ Choisissez la devise
+
- handleCurrencySelect("USD")}
>
- USD
+
+ USD
+
- handleCurrencySelect("EUR")}
>
- EUR
+
+ EUR
+
{isConverting ? (
-
+
- Converting...
+
+ Converting...
+
) : (
- Total: {convertedAmount.length > 0
- ? `${currentCurrency === "USD" ? "$" : "€"}${convertedAmount.find(item => item.item_key === 'total_amount')?.converted_amount.toFixed(2) || '0.00'}`
- : `$${(parseFloat(selectedPrice.replace(/,/g, '')) / 580).toFixed(2)}`}
+ Total:{" "}
+ {convertedAmount.length > 0
+ ? `${currentCurrency === "USD" ? "$" : "€"}${
+ convertedAmount
+ .find(
+ (item) => item.item_key === "total_amount"
+ )
+ ?.converted_amount.toFixed(2) || "0.00"
+ }`
+ : `$${(
+ parseFloat(selectedPrice.replace(/,/g, "")) /
+ 580
+ ).toFixed(2)}`}
)}
>
@@ -715,12 +764,18 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{/* 右侧圆圈图标 */}
- handleOperatorSelect("mtn")}>
+ handleOperatorSelect("mtn")}
+ >
{selectedOperator === "mtn" && (
@@ -735,24 +790,37 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
-
- handleOperatorSelect("mtn")}>
+ handleOperatorSelect("mtn")}
+ >
{selectedOperator === "mtn" && (
-
+
)}
@@ -763,24 +831,37 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
-
- handleOperatorSelect("mtn")}>
+ handleOperatorSelect("mtn")}
+ >
{selectedOperator === "mtn" && (
-
+
)}
@@ -798,7 +879,10 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
Annuler
-
+
Confirmer
@@ -808,33 +892,39 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
{/* 充值金额信息 */}
- Résumé de la recharge
-
+
+ Résumé de la recharge
+
+
Montant:
{paymentParams?.selectedPriceLabel || selectedPrice + " FCFA"}
-
+
{paymentParams?.currency !== "FCFA" && (
- Montant converti:
+
+ Montant converti:
+
{paymentParams?.currency === "USD" ? "$" : "€"}
{paymentParams?.amount.toFixed(2) || "0.00"}
)}
-
+
- Méthode de paiement:
+
+ Méthode de paiement:
+
{paymentParams?.payment_method || "Non sélectionné"}
-
+
{/* 电话号码输入 */}
Numéro de téléphone
@@ -852,10 +942,12 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
/>
-
+
{/* 支持的运营商 */}
- Opérateurs pris en charge
+
+ Opérateurs pris en charge
+
{
/>
-
+
{/* 支付按钮 */}
@@ -882,12 +977,14 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
) : (
- PAYER {paymentParams?.currency === "FCFA"
- ? paymentParams.originalAmount.toLocaleString() + " " + paymentParams.currency
- : (paymentParams?.currency === "USD"
- ? "$" + paymentParams?.amount.toFixed(2)
- : paymentParams?.amount.toFixed(2) + " €")
- }
+ PAYER{" "}
+ {paymentParams?.currency === "FCFA"
+ ? paymentParams.originalAmount.toLocaleString() +
+ " " +
+ paymentParams.currency
+ : paymentParams?.currency === "USD"
+ ? "$" + paymentParams?.amount.toFixed(2)
+ : paymentParams?.amount.toFixed(2) + " €"}
)}
@@ -1044,7 +1141,7 @@ const styles = StyleSheet.create({
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
- paddingRight:6
+ paddingRight: 6,
},
currencyImage: {
width: 80,
@@ -1250,17 +1347,17 @@ const styles = StyleSheet.create({
},
container2: {
- width: '100%',
+ width: "100%",
marginTop: 20,
},
amountRechargeContainer: {
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center',
- width: '100%',
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
height: 60,
- backgroundColor: 'white',
+ backgroundColor: "white",
borderRadius: 5,
},
rechargePromptTextStyle: {
@@ -1269,13 +1366,13 @@ const styles = StyleSheet.create({
margin: 0,
fontSize: 14,
lineHeight: 14,
- color: '#747474',
+ color: "#747474",
// Note: PingFang SC font might not be available by default in React Native
// You may need to load custom fonts using expo-font or other methods
},
tabContainer: {
- flexDirection: 'row',
- backgroundColor: 'white',
+ flexDirection: "row",
+ backgroundColor: "white",
borderRadius: 5,
marginTop: 10,
padding: 5,
@@ -1283,51 +1380,50 @@ const styles = StyleSheet.create({
tab: {
flex: 1,
paddingVertical: 10,
- alignItems: 'center',
+ alignItems: "center",
borderRadius: 5,
},
activeTab: {
- backgroundColor: '#002fa7',
+ backgroundColor: "#002fa7",
},
tabText: {
fontSize: fontSize(14),
- color: '#333',
- fontWeight: '500',
+ color: "#333",
+ fontWeight: "500",
},
activeTabText: {
- color: 'white',
- fontWeight: '600',
+ color: "white",
+ fontWeight: "600",
},
emptyTab: {
- backgroundColor: 'white',
+ backgroundColor: "white",
borderRadius: 5,
padding: 20,
marginTop: 10,
- alignItems: 'center',
- justifyContent: 'center',
+ alignItems: "center",
+ justifyContent: "center",
height: 200,
},
emptyTabText: {
- color: '#666',
+ color: "#666",
fontSize: fontSize(14),
},
outerContainer: {
- width: '100%',
+ width: "100%",
},
flexContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-start',
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "flex-start",
height: 50,
paddingRight: 16,
paddingLeft: 16,
- backgroundColor: 'white',
+ backgroundColor: "white",
borderRadius: 5,
marginTop: 18,
-
},
imageContainer: {
- width: '26.54%',
+ width: "26.54%",
},
imageStyle: {
width: 80,
@@ -1335,9 +1431,9 @@ const styles = StyleSheet.create({
borderWidth: 0,
},
verticalAlignEndContent: {
- flexDirection: 'column',
- alignItems: 'flex-end',
- width: '73.46%',
+ flexDirection: "column",
+ alignItems: "flex-end",
+ width: "73.46%",
},
svgContainer: {
width: 24,
@@ -1368,18 +1464,18 @@ const styles = StyleSheet.create({
paddingRight: 20,
paddingBottom: 333,
paddingLeft: 20,
- backgroundColor: 'white',
+ backgroundColor: "white",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
},
paymentSectionContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-start',
- width: '100%',
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ width: "100%",
},
paymentSection: {
- width: '8.48%',
+ width: "8.48%",
paddingRight: 15,
},
svgContainer1: {
@@ -1387,10 +1483,10 @@ const styles = StyleSheet.create({
height: 18,
},
paymentSection1: {
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'flex-start',
- width: '91.52%',
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ width: "91.52%",
paddingRight: 33,
},
paymentHeadingStyle: {
@@ -1398,24 +1494,25 @@ const styles = StyleSheet.create({
margin: 0,
fontSize: 24,
lineHeight: 22,
- color: 'black',
- textTransform: 'capitalize',
- fontFamily: 'Montserrat-Bold',
+ color: "black",
+ textTransform: "capitalize",
+ fontFamily: "Montserrat-Bold",
},
transactionSummaryContainer1: {
- width: '100%',
+ width: "100%",
},
transactionSummaryContainer: {
- width: '100%',
+ width: "100%",
paddingRight: 15,
paddingLeft: 15,
- backgroundColor: 'linear-gradient(90deg, rgba(206, 229, 255, 1) 0%, rgba(238, 244, 255, 1) 100%',
+ backgroundColor:
+ "linear-gradient(90deg, rgba(206, 229, 255, 1) 0%, rgba(238, 244, 255, 1) 100%",
borderRadius: 5,
},
flexContainerWithImages: {
- flexDirection: 'row',
- alignItems: 'flex-start',
- justifyContent: 'flex-start',
+ flexDirection: "row",
+ alignItems: "flex-start",
+ justifyContent: "flex-start",
},
imageContainerStyled: {
width: 99,
@@ -1429,13 +1526,13 @@ const styles = StyleSheet.create({
borderWidth: 0,
},
amountContainer: {
- width: '100%',
+ width: "100%",
paddingTop: 8,
paddingRight: 11,
paddingBottom: 10,
paddingLeft: 11,
marginTop: -83,
- backgroundColor: 'white',
+ backgroundColor: "white",
borderWidth: 1,
borderRadius: 5,
},
@@ -1443,13 +1540,13 @@ const styles = StyleSheet.create({
padding: 0,
margin: 0,
fontSize: 12,
- color: '#7f7e7e',
- fontFamily: 'PingFangSC-Medium',
+ color: "#7f7e7e",
+ fontFamily: "PingFangSC-Medium",
},
amountContainer1: {
- flexDirection: 'row',
- alignItems: 'flex-start',
- justifyContent: 'flex-start',
+ flexDirection: "row",
+ alignItems: "flex-start",
+ justifyContent: "flex-start",
marginTop: 1,
},
priceHeading: {
@@ -1458,8 +1555,8 @@ const styles = StyleSheet.create({
margin: 0,
fontSize: 24,
lineHeight: 22,
- color: '#161616',
- fontFamily: 'Montserrat-Bold',
+ color: "#161616",
+ fontFamily: "Montserrat-Bold",
},
priceLabel: {
padding: 0,
@@ -1467,41 +1564,41 @@ const styles = StyleSheet.create({
margin: 0,
marginLeft: 3,
fontSize: 12,
- color: '#7f7e7e',
- fontFamily: 'PingFangSC-Medium',
+ color: "#7f7e7e",
+ fontFamily: "PingFangSC-Medium",
},
mobileInfoSection: {
- width: '100%',
+ width: "100%",
marginTop: 30,
},
mobileNumberSection: {
- width: '100%',
+ width: "100%",
},
mobileNumberLabel: {
padding: 0,
margin: 0,
fontSize: 14,
lineHeight: 18,
- color: 'black',
- fontFamily: 'PingFangSC-Regular',
+ color: "black",
+ fontFamily: "PingFangSC-Regular",
},
infoCard: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-start',
- width: '100%',
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ width: "100%",
height: 50,
paddingRight: 12,
paddingLeft: 12,
marginTop: 12,
borderWidth: 1,
- borderColor: '#d8d8d8',
+ borderColor: "#d8d8d8",
borderRadius: 25,
},
flexRowWithIcon: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'flex-start',
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "flex-start",
},
maskedImageWithText: {
width: 20,
@@ -1514,8 +1611,8 @@ const styles = StyleSheet.create({
marginLeft: 3,
fontSize: 16,
lineHeight: 22,
- color: '#1c284e',
- fontFamily: 'PingFangSC-Semibold',
+ color: "#1c284e",
+ fontFamily: "PingFangSC-Semibold",
},
svgContainer2: {
width: 12,
@@ -1527,7 +1624,7 @@ const styles = StyleSheet.create({
height: 30,
marginLeft: 8.5,
borderLeftWidth: 1,
- borderColor: '#b1b1b1',
+ borderColor: "#b1b1b1",
},
statisticText: {
padding: 0,
@@ -1535,18 +1632,18 @@ const styles = StyleSheet.create({
marginLeft: 19.5,
fontSize: 16,
lineHeight: 22,
- color: '#1c284e',
- fontFamily: 'PingFangSC-Semibold',
+ color: "#1c284e",
+ fontFamily: "PingFangSC-Semibold",
},
mobileOperatorsContainer: {
- width: '100%',
+ width: "100%",
marginTop: 20,
},
operatorSupportContainer: {
- flexDirection: 'row',
+ flexDirection: "row",
gap: 10,
- alignItems: 'center',
- justifyContent: 'flex-start',
+ alignItems: "center",
+ justifyContent: "flex-start",
marginTop: 12,
},
imageContainerWithBorder1: {
@@ -1555,26 +1652,26 @@ const styles = StyleSheet.create({
borderWidth: 0,
},
blueBoxContainer: {
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'flex-start',
- width: '100%',
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "flex-start",
+ width: "100%",
marginTop: 50,
- backgroundColor: '#002fa7',
+ backgroundColor: "#002fa7",
borderRadius: 25,
},
paymentNotice1: {
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center',
+ flexDirection: "column",
+ alignItems: "center",
+ justifyContent: "center",
height: 50,
},
paymentNotice: {
padding: 0,
margin: 0,
fontSize: 16,
- color: 'white',
- fontFamily: 'Montserrat-Bold',
+ color: "white",
+ fontFamily: "Montserrat-Bold",
},
paymentConfirmContainer: {
flex: 1,
diff --git a/app/screens/login/Google.tsx b/app/screens/login/Google.tsx
index 853f6ed..e29cb35 100644
--- a/app/screens/login/Google.tsx
+++ b/app/screens/login/Google.tsx
@@ -4,9 +4,10 @@ import { WebView } from "react-native-webview";
import { useNavigation } from "@react-navigation/native";
import { loginApi } from "../../services/api/login";
import { useAuth } from "../../contexts/AuthContext";
+import AsyncStorage from "@react-native-async-storage/async-storage";
export const GoogleScreen = () => {
- const navigation = useNavigation();
+ const navigation = useNavigation();
const { login } = useAuth();
const [loading, setLoading] = useState(true);
const [loginUrl, setLoginUrl] = useState(null);
@@ -15,27 +16,29 @@ export const GoogleScreen = () => {
const fetchLoginUrl = async () => {
try {
const response = await loginApi.google();
- if (response.data.url) {
- setLoginUrl(response.data.url);
+
+
+ if (response.url) {
+ setLoginUrl(response.url);
}
} catch (error) {
- console.error('Failed to fetch login URL:', error);
+ console.error("Failed to fetch login URL:", error);
}
};
fetchLoginUrl();
}, []);
- const handleNavigationStateChange = async (navState: any) => {
+ const handleNavigationStateChange = async (navState: any) => {
console.log(navState.url);
-
+
// 检查URL是否包含重定向URI
- if (navState.url.includes('localhost:8000')) {
+ if (navState.url.includes("localhost:8000")) {
try {
await login();
- navigation.navigate('MainTabs' as never);
+ navigation.navigate("MainTabs" as never);
} catch (error) {
- console.error('Login failed:', error);
+ console.error("Login failed:", error);
}
}
};
@@ -60,13 +63,38 @@ export const GoogleScreen = () => {
domStorageEnabled={true}
startInLoadingState={true}
scalesPageToFit={true}
- originWhitelist={['*']}
+ originWhitelist={["*"]}
+ incognito={true}
+ thirdPartyCookiesEnabled={false}
userAgent="Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Mobile Safari/537.36"
onShouldStartLoadWithRequest={(request) => {
- console.log(request);
-
- // 允许所有请求
- return true;
+ const { url } = request;
+ // 拦截 myapp://login-success
+ if (url.startsWith("myapp://login-success")) {
+ console.log("拦截成功!跳转地址:", url);
+
+ // 提取 token 参数
+ const urlParams = new URLSearchParams(url.split('?')[1]);
+ const token = urlParams.get('token');
+
+ // 如果有 token 则登录成功,否则跳转回登录页
+ if (token) {
+ const tokens = "bearer " + token;
+ AsyncStorage.setItem("token", tokens);
+ // 登录成功,更新认证状态
+ login().then(() => {
+ // 跳转到主页
+ navigation.replace("MainTabs", { screen: "Home" });
+ });
+ } else {
+ // 登录失败,跳转回登录页
+ navigation.replace("Login");
+ }
+
+ return false; // 阻止 WebView 加载这个链接
+ }
+
+ return true; // 其他 URL 继续加载
}}
/>
@@ -79,9 +107,9 @@ const styles = StyleSheet.create({
},
loadingContainer: {
flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: 'white',
+ justifyContent: "center",
+ alignItems: "center",
+ backgroundColor: "white",
},
webview: {
flex: 1,
diff --git a/app/screens/loginList/PhoneLoginModal.tsx b/app/screens/loginList/PhoneLoginModal.tsx
index ba61d11..2c61d93 100644
--- a/app/screens/loginList/PhoneLoginModal.tsx
+++ b/app/screens/loginList/PhoneLoginModal.tsx
@@ -240,7 +240,7 @@ const PhoneLoginModal = ({ visible, onClose }: PhoneLoginModalProps) => {
const user = await userApi.getProfile();
setUser(user);
setLoading(false);
- navigation.navigate("MainTabs", { screen: "Home" });
+ navigation.replace("MainTabs", { screen: "Home" });
onClose();
logLogin(true, "phone");
diff --git a/app/screens/pay/Pay.tsx b/app/screens/pay/Pay.tsx
index 34f7e0c..231c8b2 100644
--- a/app/screens/pay/Pay.tsx
+++ b/app/screens/pay/Pay.tsx
@@ -21,12 +21,8 @@ export const Pay = () => {
const [payInfo, setPayInfo] = useState();
useEffect(() => {
- console.log(route.params);
- console.log(payUrl);
-
// 设置处理深度链接的监听器
const handleDeepLink = ({ url }: { url: string }) => {
- console.log("Deep link received:", url);
if (
url.includes("myapp://payment-success") ||
url.includes("exp://192.168.0.101:8084/--/payment-success")
@@ -47,8 +43,6 @@ export const Pay = () => {
}, []);
const handleNavigationStateChange = (navState: any) => {
- console.log(navState);
-
// 检查URL是否包含支付成功的回调参数
const { url } = navState;
if (url && url.includes("payment_success=true")) {
@@ -60,30 +54,22 @@ export const Pay = () => {
// 导航辅助函数,尝试使用多种方式导航
const safeNavigate = (routeName: string, params: any) => {
- console.log(`尝试导航到 ${routeName},参数:`, params);
- console.log(`navigationRef准备状态: ${navigationRef.isReady()}`);
try {
// 尝试使用组件内的navigation
- console.log("使用组件内navigation导航");
// @ts-ignore 忽略可能的类型错误
navigation.navigate(routeName, params);
} catch (e) {
- console.log("组件内导航失败:", e);
try {
// 尝试使用全局navigation
- console.log("使用全局navigate导航");
navigate(routeName, params);
} catch (e) {
- console.log("全局导航也失败:", e);
// 最后尝试使用setTimeout延迟导航
- console.log("尝试延迟导航");
setTimeout(() => {
try {
// @ts-ignore 忽略可能的类型错误
navigation.navigate(routeName, params);
} catch (e) {
- console.log("所有导航方式都失败");
Alert.alert("导航失败", "无法跳转到目标页面");
}
}, 500);
@@ -107,21 +93,15 @@ export const Pay = () => {
originWhitelist={["*"]}
userAgent="Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Mobile Safari/537.36"
onShouldStartLoadWithRequest={(request) => {
- console.log("Load request:", request);
-
// 检查URL是否包含支付成功的参数
- const { url } = request;
-
+ const { url } = request;
if (url) {
// 解析参数
const parsed = Linking.parse(url);
const params = parsed.queryParams || {};
- console.log("解析的URL参数:", params);
// 检查是否存在paymentId参数并且不为null
if (params.paymentId && params.paymentId !== "null") {
- console.log("检测到有效的paymentId:", params.paymentId);
- Alert.alert("支付成功");
if (params.PayerID && params.PayerID !== "null") {
payApi
.paySuccessCallback(
diff --git a/app/screens/previewOrder/PaymentMethod.tsx b/app/screens/previewOrder/PaymentMethod.tsx
index e7067d2..012884c 100644
--- a/app/screens/previewOrder/PaymentMethod.tsx
+++ b/app/screens/previewOrder/PaymentMethod.tsx
@@ -510,8 +510,10 @@ export const PaymentMethod = () => {
.createOrder(createOrderData as unknown as CreateOrderRequest)
.then((res) => {
setCreateLoading(false);
- logPaymentConfirm(data);
+ logPaymentConfirm(data,navigation.getState().routes[navigation.getState().index - 1]?.name as string);
// go to payment preview
+ console.log(getBurialPointData());
+
navigation.navigate("PreviewOrder", {
data: res,
payMethod: selectedPayment,
diff --git a/app/screens/previewOrder/PreviewAddress.tsx b/app/screens/previewOrder/PreviewAddress.tsx
index db45a3f..2044336 100644
--- a/app/screens/previewOrder/PreviewAddress.tsx
+++ b/app/screens/previewOrder/PreviewAddress.tsx
@@ -225,7 +225,8 @@ export const PreviewAddress = () => {
phone_number: Number(formData.receiver_phone),
whatsApp_number: Number(formData.whatsapp_phone),
}
- logAddressInfo(logData);
+ 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 bd089e3..232ade9 100644
--- a/app/screens/previewOrder/ShippingFee.tsx
+++ b/app/screens/previewOrder/ShippingFee.tsx
@@ -68,13 +68,9 @@ export const ShippingFee = () => {
const [selectedWarehouse, setSelectedWarehouse] = useState();
const [domesticShippingFeeData, setDomesticShippingFeeData] =
useState();
- const [isDomesticShippingLoading, setIsDomesticShippingLoading] =
+ const [isShippingFeeLoading, setIsShippingFeeLoading] =
useState(false);
const [count, setCount] = useState();
- const [apiResponses, setApiResponses] = useState({
- shippingFees: false,
- domesticShippingFees: false,
- });
const { setOrderData, orderData, items } = useCreateOrderStore();
const [countryCode, setCountryCode] = useState();
@@ -110,24 +106,21 @@ export const ShippingFee = () => {
useEffect(() => {
if (state.shippingFees) {
setShippingFeeData(state.shippingFees);
- setCount(t("order.shipping.calculating"));
- setApiResponses((prev) => ({ ...prev, shippingFees: true }));
}
- }, [state.shippingFees, t]);
+ }, [state.shippingFees]);
useEffect(() => {
if (state.domesticShippingFees) {
setDomesticShippingFeeData(state.domesticShippingFees);
- setApiResponses((prev) => ({ ...prev, domesticShippingFees: true }));
}
}, [state.domesticShippingFees]);
- // Effect to handle loading state based on both API responses
+ // 统一处理loading状态
useEffect(() => {
- if (apiResponses.shippingFees && apiResponses.domesticShippingFees) {
- setIsDomesticShippingLoading(false);
+ if (state.shippingFees && state.domesticShippingFees) {
+ setIsShippingFeeLoading(false);
}
- }, [apiResponses]);
+ }, [state.shippingFees, state.domesticShippingFees]);
// Call changeCountryHandel when warehouse changes
useEffect(() => {
@@ -152,14 +145,9 @@ export const ShippingFee = () => {
// Only calculate if we have the necessary data
if (data.items && data.freight_forwarder_address_id) {
- // Set loading state to true before making API calls
- setIsDomesticShippingLoading(true);
+ // 设置loading状态为true,开始计算
+ setIsShippingFeeLoading(true);
setCount(t("order.shipping.calculating"));
- // Reset API response tracking
- setApiResponses({
- shippingFees: false,
- domesticShippingFees: false,
- });
calculateShippingFee(data);
calculateDomesticShippingFee(data);
@@ -177,7 +165,7 @@ export const ShippingFee = () => {
const handleSubmit = () => {
if (
- !isDomesticShippingLoading &&
+ !isShippingFeeLoading &&
domesticShippingFeeData?.total_shipping_fee != null
) {
setOrderData({
@@ -202,8 +190,8 @@ export const ShippingFee = () => {
country_city: selectedWarehouseLabel,
timestamp: new Date().toISOString(),
};
- logShippingConfirm(data);
-
+ 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,
});
@@ -379,84 +367,61 @@ export const ShippingFee = () => {
-
-
- {t("order.shipping.domestic_fee")}:{" "}
-
-
- {isDomesticShippingLoading ? (
+ {isShippingFeeLoading ? (
+ // 统一显示一个加载状态
+
+
+ {count}
+
+
+
+ ) : (
+ // 加载完成后同时显示两个费用
+ <>
+
+
+ {t("order.shipping.domestic_fee")}:{" "}
+
- {count}{" "}
-
+
+ {domesticShippingFeeData?.total_shipping_fee ||
+ 0}{" "}
+ {userStore.user?.currency}
+
- ) : (
-
- {domesticShippingFeeData?.total_shipping_fee ||
- 0}{" "}
+
+
+
+ {t("order.shipping.international_fee")}:{" "}
+
+
+ {shippingMethod === "sea"
+ ? shippingFeeData?.total_shipping_fee_sea
+ : shippingFeeData?.total_shipping_fee_air}{" "}
{userStore.user?.currency}
- )}
-
-
- {isDomesticShippingLoading ? (
-
-
- {t("order.shipping.international_fee")}:{" "}
-
-
- {count}{" "}
-
-
-
- ) : (
-
-
- {t("order.shipping.international_fee")}:{" "}
-
-
- {shippingMethod === "sea"
- ? shippingFeeData?.total_shipping_fee_sea
- : shippingFeeData?.total_shipping_fee_air}{" "}
- {userStore.user?.currency}
-
-
+
+ >
)}
)}
@@ -467,14 +432,14 @@ export const ShippingFee = () => {
@@ -755,4 +720,15 @@ const styles = StyleSheet.create({
disabledButtonStyle: {
backgroundColor: "#ccc",
},
+ loadingFeesContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginVertical: 15,
+ },
+ calculatingText: {
+ color: "#ff6000",
+ fontSize: fontSize(14),
+ fontWeight: "500"
+ },
});
diff --git a/app/screens/previewOrder/perviewOrder.tsx b/app/screens/previewOrder/perviewOrder.tsx
index 7b70cb7..565857d 100644
--- a/app/screens/previewOrder/perviewOrder.tsx
+++ b/app/screens/previewOrder/perviewOrder.tsx
@@ -23,6 +23,8 @@ import { Order } from "../../services/api/orders";
import { payApi } from "../../services/api/payApi";
import { useTranslation } from "react-i18next";
import fontSize from "../../utils/fontsizeUtils";
+import { getBurialPointData } from "../../store/burialPoint";
+import useBurialPointStore from "../../store/burialPoint";
// Define the param list for navigation
type RootStackParamList = {
@@ -46,7 +48,7 @@ export const PreviewOrder = () => {
const [loading, setLoading] = useState(false);
const { user } = useUserStore();
const { t } = useTranslation();
-
+ const { logPreviewOrder } = useBurialPointStore();
useEffect(() => {
if (!user.user_id) {
return Alert.alert(t("order.preview.login_required"));
@@ -97,8 +99,10 @@ export const PreviewOrder = () => {
.getPayInfo(data)
.then((res) => {
if (res.success) {
+ logPreviewOrder(navigation.getState().routes[navigation.getState().index - 1]?.name as string);
+ console.log(getBurialPointData());
- navigation.navigate("Pay", {
+ navigation.replace("Pay", {
payUrl: res.payment_url,
});
}
diff --git a/app/screens/productStatus/OrderDatails.tsx b/app/screens/productStatus/OrderDatails.tsx
index 89f9dc4..fe5fad9 100644
--- a/app/screens/productStatus/OrderDatails.tsx
+++ b/app/screens/productStatus/OrderDatails.tsx
@@ -248,7 +248,7 @@ export const OrderDetails = () => {