From b29469e53af1b60d9326184719cad9bee45f1830 Mon Sep 17 00:00:00 2001 From: Mac Date: Thu, 1 May 2025 13:20:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.tsx | 11 + app.json | 28 +- app/screens/LoginScreen.tsx | 65 +- app/screens/ProfileScreen.tsx | 30 +- app/screens/Recipient/Recipient.tsx | 1239 ++++++++++-------- app/screens/login/Google.tsx | 89 ++ app/screens/{ => login}/PhoneLoginScreen.tsx | 7 +- app/services/api/login.tsx | 8 + assets/img/google.png | Bin 0 -> 8568 bytes package-lock.json | 84 +- package.json | 6 +- yarn.lock | 50 +- 12 files changed, 1022 insertions(+), 595 deletions(-) create mode 100644 app/screens/login/Google.tsx rename app/screens/{ => login}/PhoneLoginScreen.tsx (98%) create mode 100644 app/services/api/login.tsx create mode 100644 assets/img/google.png diff --git a/App.tsx b/App.tsx index 7749325..6eadfb4 100644 --- a/App.tsx +++ b/App.tsx @@ -7,6 +7,7 @@ import { CountrySelect } from "./app/screens/CountrySelect"; import { MainApp } from "./app/screens/MainApp"; import { LoginScreen } from "./app/screens/LoginScreen"; import { EmailLoginScreen } from "./app/screens/EmailLoginScreen"; +import { GoogleScreen } from "./app/screens/login/Google"; import "./app/i18n"; import { TabNavigator } from "./app/navigation/TabNavigator"; import { AuthProvider } from "./app/contexts/AuthContext"; @@ -46,6 +47,7 @@ export type RootStackParamList = { CartScreen:undefined; PaymentSuccessScreen:undefined; MyAccount:undefined; + Google: undefined; }; const Stack = createNativeStackNavigator(); @@ -218,6 +220,15 @@ export default function App() { gestureDirection: "horizontal", }} /> + diff --git a/app.json b/app.json index 640e935..4cc9d50 100644 --- a/app.json +++ b/app.json @@ -7,19 +7,43 @@ "icon": "./assets/icon.png", "userInterfaceStyle": "light", "newArchEnabled": true, + "scheme": "auth0sample", "splash": { "image": "./assets/splash-icon.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "ios": { - "supportsTablet": true + "supportsTablet": true, + "bundleIdentifier": "com.brainnel.app", + "infoPlist": { + "CFBundleURLTypes": [ + { + "CFBundleURLSchemes": ["auth0sample"] + } + ] + } }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" - } + }, + "package": "com.brainnel.app", + "intentFilters": [ + { + "action": "VIEW", + "data": [ + { + "scheme": "auth0sample" + } + ], + "category": [ + "BROWSABLE", + "DEFAULT" + ] + } + ] }, "web": { "favicon": "./assets/favicon.png" diff --git a/app/screens/LoginScreen.tsx b/app/screens/LoginScreen.tsx index fb8865c..749f797 100644 --- a/app/screens/LoginScreen.tsx +++ b/app/screens/LoginScreen.tsx @@ -14,13 +14,25 @@ import { Keyboard, Modal, InteractionManager, + Image, } from 'react-native'; import { useTranslation } from 'react-i18next'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import { RootStackParamList } from '../navigation/types'; import { Country, countries } from '../constants/countries'; import { useAuth } from '../contexts/AuthContext'; +import { settingApi } from "../services/api/setting"; +import { userApi } from "../services/api/userApi"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +type RootStackParamList = { + Login: undefined; + EmailLogin: undefined; + MainTabs: undefined; + Google: undefined; + Home: undefined; +}; + + // 常见邮箱后缀列表 const EMAIL_DOMAINS = [ @@ -74,6 +86,16 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { const [emailLoginMounted, setEmailLoginMounted] = useState(false); const [phoneLoginMounted, setPhoneLoginMounted] = useState(false); + + + + + + + + + + // 处理邮箱输入变化,生成邮箱建议 const handleEmailChange = (text: string) => { setEmail(text); @@ -285,8 +307,9 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { } }; - const handleGoogleLogin = () => { - // 处理Google登录 + // 处理谷歌登录 + const handleGoogleLogin = async () => { + navigation.navigate('Google'); }; const handleFacebookLogin = () => { @@ -306,15 +329,33 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { openEmailLogin(); }; + // const handleEmailContinue = async () => { - if (emailPassword === '123') { - setEmailPasswordError(false); - await login(); - closeEmailLogin(); - navigation.replace('MainTabs'); - } else { - setEmailPasswordError(true); - } + // if (emailPassword === '123') { + // setEmailPasswordError(false); + // await login(); + // closeEmailLogin(); + // navigation.replace('MainTabs'); + // } else { + // setEmailPasswordError(true); + // } + + + + const params = { + grant_type: "password", + username: "test", + password: "string", + client_id: "2", + client_secret: "", + scope: "", + }; + const res = await userApi.login(params); + const token = res.token_type + " " + res.access_token; + await AsyncStorage.setItem("token", token); + navigation.navigate("Home"); + const data = await settingApi.postFirstLogin(221); + console.log(data); }; const handlePhoneLogin = () => { @@ -387,7 +428,7 @@ export const LoginScreen = ({ onClose, isModal }: LoginScreenProps) => { onPress={handleGoogleLogin} > - G + {t('continueWithGoogle')} diff --git a/app/screens/ProfileScreen.tsx b/app/screens/ProfileScreen.tsx index 3a377e0..3b1d42d 100644 --- a/app/screens/ProfileScreen.tsx +++ b/app/screens/ProfileScreen.tsx @@ -26,25 +26,27 @@ type RootStackParamList = { SettingList: undefined; Home: undefined; MyAccount:undefined; + Login:undefined; }; export const ProfileScreen = () => { const handleLogin = async () => { - const data = settingApi.postFirstLogin(221); - console.log(data); + navigation.navigate("Login"); + // const data = settingApi.postFirstLogin(221); + // console.log(data); - const params = { - grant_type: "password", - username: "test", - password: "string", - client_id: "2", - client_secret: "", - scope: "", - }; - const res = await userApi.login(params); - const token = res.token_type + " " + res.access_token; - await AsyncStorage.setItem("token", token); - navigation.navigate("Home"); + // const params = { + // grant_type: "password", + // username: "test", + // password: "string", + // client_id: "2", + // client_secret: "", + // scope: "", + // }; + // const res = await userApi.login(params); + // const token = res.token_type + " " + res.access_token; + // await AsyncStorage.setItem("token", token); + // navigation.navigate("Home"); }; const navigation = diff --git a/app/screens/Recipient/Recipient.tsx b/app/screens/Recipient/Recipient.tsx index acf474e..27c4aec 100644 --- a/app/screens/Recipient/Recipient.tsx +++ b/app/screens/Recipient/Recipient.tsx @@ -26,7 +26,12 @@ import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { eventBus } from "../../utils/eventBus"; import LocationPinIcon from "../../components/LocationPinIcon"; import fontSize from "../../utils/fontsizeUtils"; -import { ordersApi, OrderData,AddressDataItem ,DomesticShippingFeeData} from "../../services/api/orders"; +import { + ordersApi, + OrderData, + AddressDataItem, + DomesticShippingFeeData, +} from "../../services/api/orders"; import AsyncStorage from "@react-native-async-storage/async-storage"; export function Recipient({ @@ -52,8 +57,22 @@ export function Recipient({ const [addressList, setAddressList] = useState(); const [defaultAddress, setDefaultAddress] = useState(); const [addressId, setAddressId] = useState(); - const [freightForwarderAddress, setFreightForwarderAddress] = useState(); - const [domesticShippingFee, setDomesticShippingFee] = useState(); + const [freightForwarderAddress, setFreightForwarderAddress] = + useState(); + const [domesticShippingFee, setDomesticShippingFee] = + useState(); + const [tabs, setTabs] = useState([ + { + id: "Online Payment", + label: "Online Payment", + }, + { + id: "Offline Payment", + label: "Offline Payment", + }, + ]); + const [currentTab, setCurrentTab] = useState("Online Paymen"); + const getAddress = async () => { const response = await addressApi.addressesDefault(); setAddressId(response.address_id); @@ -78,16 +97,16 @@ export function Recipient({ const getFreightForwarderAddress = async () => { const response = await ordersApi.freightForwarderAddress(1); - setWarehouse(response.current_country_address.country as number) + setWarehouse(response.current_country_address.country as number); setFreightForwarderAddress(response); }; const getDomesticShippingFee = async () => { const data = { items: route.params.items, - } + }; const response = await ordersApi.calcDomesticShippingFee(data); - + setDomesticShippingFee(response); }; @@ -95,8 +114,8 @@ export function Recipient({ getAddress(); getAddressList(); getOrders(); - getFreightForwarderAddress() - getDomesticShippingFee() + getFreightForwarderAddress(); + getDomesticShippingFee(); const listener = (data: any) => { if (data.type === "add") { data.address_id = new Date().getTime(); @@ -207,644 +226,719 @@ export function Recipient({ ); addressApi.deleteAddress(address_id); }; - const changeCountryHandel = async (value:number) => { + const changeCountryHandel = async (value: number) => { const data = { items: route.params.items, - country_code: value - } + country_code: value, + }; const response = await ordersApi.calcShippingFee(data); if (orderData) { setOrderData({ ...orderData, shipping_fee_sea: response?.total_shipping_fee_sea, - shipping_fee_air: response?.total_shipping_fee_air + shipping_fee_air: response?.total_shipping_fee_air, }); } - } + }; return ( - - {/* Header */} - - navigation.goBack()}> - - - Checkout - - - {/* Recipient Info */} - - - 👤 - Recipient Information + + + {/* Header */} + + navigation.goBack()}> + + + Checkout - {defaultAddress && ( - - - - - - - {defaultAddress?.receiver_first_name} .{" "} - {defaultAddress?.receiver_last_name} - - - {defaultAddress?.country} - - - {defaultAddress?.receiver_phone} - - - - )} - - - Add Recipient Information - - - - - {/* Shipping Method */} - - - 🚢 - Shipping Method - - - {[ - { - id: "sea", - label: "Sea Shipping", - icon: "🚢", - detail: "Economical", - }, - { id: "air", label: "Air Shipping", icon: "✈️", detail: "Express" }, - ].map((option, index) => ( - { - setShippingMethod(option.id); - }} - > - {index === 0 && ( - - - - )} - {option.icon} - {option.label} - {option.detail} - - ))} - - - - - {/* Warehouse Selection */} - - - 🏭 - Delivery Warehouse - - - - Select a warehouse: - - { - setWarehouse(value); - changeCountryHandel(value) - }} - > - { - freightForwarderAddress?.other_addresses.map((item,index) => ( - - )) - } - - - - + {/* Recipient Info */} + + + 👤 + Recipient Information - {warehouse && ( - - - - Estimated Arrival:{" "} - + {defaultAddress && ( + + + + + + + {defaultAddress?.receiver_first_name} .{" "} + {defaultAddress?.receiver_last_name} - - {shippingMethod === "sea" - ? orderData?.shipping_fee_sea_time - : orderData?.shipping_fee_air_time} - - - - - - International Fee:{" "} - + + {defaultAddress?.country} + + + {defaultAddress?.receiver_phone} - - {shippingMethod === "sea" - ? orderData?.shipping_fee_sea - : orderData?.shipping_fee_air} - - (Cash on Delivery) )} + + + + Add Recipient Information + + - - - - + + + {/* Shipping Method */} + - 💳 - Payment Method + 🚢 + Shipping Method + + + {[ + { + id: "sea", + label: "Sea Shipping", + icon: "🚢", + detail: "Economical", + }, + { + id: "air", + label: "Air Shipping", + icon: "✈️", + detail: "Express", + }, + ].map((option, index) => ( + { + setShippingMethod(option.id); + }} + > + {index === 0 && ( + + + + )} + {option.icon} + {option.label} + {option.detail} + + ))} + + - {[ - { id: "balance", icon: "💰", label: "Account Balance" }, - { id: "mobile_money", icon: "📱", label: "Mobile Money" }, - { id: "paypal", icon: "🅿️", label: "PayPal" }, - { id: "card", icon: "💳", label: "Credit/Debit Card" }, - ].map((option) => ( - { - setPaymentMethod(option.id); - }} - > - {option.icon} - {option.label} - - ))} - - {/* Mobile Money 表单 */} - {paymentMethod === "mobile_money" && ( - - Mobile Number - - { - const next = - countryCode === "225" - ? "234" - : countryCode === "234" - ? "233" - : "225"; - setCountryCode(next); + {/* Warehouse Selection */} + + + 🏭 + Delivery Warehouse + + + + Select a warehouse: + + { + setWarehouse(value); + changeCountryHandel(value); }} > - {countryCode} - - + {freightForwarderAddress?.other_addresses.map( + (item, index) => ( + + ) + )} + - )} - {/* PayPal Currency 切换 */} - {paymentMethod === "paypal" && ( - - Select Currency - - {["usd", "eur"].map((cur) => ( - { - setCurrency(cur); + {warehouse && ( + + + + Estimated Arrival:{" "} + + + {shippingMethod === "sea" + ? orderData?.shipping_fee_sea_time + : orderData?.shipping_fee_air_time} + + + + + + International Fee:{" "} + + - - {cur.toUpperCase()} - - - ))} + {shippingMethod === "sea" + ? orderData?.shipping_fee_sea + : orderData?.shipping_fee_air} + + + (Cash on Delivery) + - - )} + )} + - - - - - - - - 📦 - Order Summary + + + + 💳 + Payment Method - - - - Products({orderData?.items.length} items) - - - - {expanded ? "Hide Details" : "View Details"} - - + + + Online Payment + + + Offline Payment + - - {orderData?.items.map((item) => ( - - {item.sku_image_url ? ( - - ) : ( - - )} + + {/* {[ + { id: "balance", icon: "💰", label: "Account Balance" }, + { id: "mobile_money", icon: "📱", label: "Mobile Money" }, + { id: "paypal", icon: "🅿️", label: "PayPal" }, + { id: "card", icon: "💳", label: "Credit/Debit Card" }, + ].map((option) => ( + { + setPaymentMethod(option.id); + }} + > + {option.icon} + {option.label} + + ))} */} + {tabs.map((item, index) => ( + { + setCurrentTab(item.id); + }} + > + + {item.label} + + + ))} - - - {item.product_name} - - {item.attributes.map((attribute) => ( - + Mobile Number + + { + const next = + countryCode === "225" + ? "234" + : countryCode === "234" + ? "233" + : "225"; + setCountryCode(next); + }} + > + {countryCode} + + + + + )} + + {/* PayPal Currency 切换 */} + {paymentMethod === "paypal" && ( + + Select Currency + + {["usd", "eur"].map((cur) => ( + { + setCurrency(cur); + }} + style={[ + styles.currencyButton, + currency === cur && styles.currencyButtonSelected, + ]} > - {attribute?.attribute_name}: {attribute?.value} - + + {cur.toUpperCase()} + + ))} - Qty: {item.quantity} - - - - ${item?.total_price} - - {/* +${item?.shipping.toFixed(2)} domestic */} - - - Supplier to warehouse shipping - - ))} + )} - - - - - - 🎟️ - Coupons - setCouponModalVisible(true)}> - - Select - - - - - {appliedCoupons.length === 0 ? ( + + + + + + 📦 + Order Summary + + + - No coupons applied. Click "Select" to browse available coupons. + Products({orderData?.items.length} items) - ) : null} - - - {appliedCoupons.map((coupon) => ( - - {coupon.name} - - {coupon.type === "percent" - ? `${coupon.discount}% Off` - : `$${coupon.discount.toFixed(2)} Off`} - - removeCoupon(coupon.code)}> - × - + + + {expanded ? "Hide Details" : "View Details"} + + + + + {orderData?.items.map((item) => ( + + {item.sku_image_url ? ( + + ) : ( + + )} + + + + {item.product_name} + + {item.attributes.map((attribute) => ( + + {attribute?.attribute_name}: {attribute?.value} + + ))} + + Qty: {item.quantity} + + + + + ${item?.total_price} + + {/* +${item?.shipping.toFixed(2)} domestic */} + + + Supplier to warehouse shipping + + ))} + + + + + + 🎟️ + Coupons + setCouponModalVisible(true)}> + + Select + + + - - - Subtotal - {orderData?.total_amount} + + {appliedCoupons.length === 0 ? ( + + No coupons applied. Click "Select" to browse available + coupons. + + ) : null} + + + {appliedCoupons.map((coupon) => ( + + {coupon.name} + + {coupon.type === "percent" + ? `${coupon.discount}% Off` + : `$${coupon.discount.toFixed(2)} Off`} + + removeCoupon(coupon.code)}> + × + + + ))} + - - Domestic Shipping - { - domesticShippingFee?.currency ? ( + + + + Subtotal + {orderData?.total_amount} + + + Domestic Shipping + {domesticShippingFee?.currency ? ( {domesticShippingFee?.total_shipping_fee} - ):( + ) : ( 报价中... - ) - } - + )} + - - Estimated International Shipping - {shippingMethod === "sea" + + Estimated International Shipping + + {shippingMethod === "sea" ? orderData?.shipping_fee_sea - : orderData?.shipping_fee_air} + : orderData?.shipping_fee_air} + + - - {/* 实际支付金额 */} - - - - Total - - - {((orderData?.total_amount ?? 0) + (shippingMethod === "sea" - ? (orderData?.shipping_fee_sea ?? 0) - : (orderData?.shipping_fee_air ?? 0)) + (domesticShippingFee?.total_shipping_fee ?? 0)).toFixed(2)} - - - - 1 + {/* 实际支付金额 */} + + + + Total + + + {( + (orderData?.total_amount ?? 0) + + (shippingMethod === "sea" + ? orderData?.shipping_fee_sea ?? 0 + : orderData?.shipping_fee_air ?? 0) + + (domesticShippingFee?.total_shipping_fee ?? 0) + ).toFixed(2)} + + + + + + $ + {shippingMethod === "sea" + ? orderData?.shipping_fee_sea + : orderData?.shipping_fee_air}{" "} + Estimated International Shipping + + - - {/* Coupon Modal */} - setCouponModalVisible(false)} - > - - - - Available Coupons - setCouponModalVisible(false)} - > - × - - + {/* Coupon Modal */} + setCouponModalVisible(false)} + > + + + + + Available Coupons + + setCouponModalVisible(false)} + > + × + + - - - - - Welcome 10% Off - - 10% off your total order - - - Valid until: 31/12/2023 - + + + + + Welcome 10% Off + + 10% off your total order + + + Valid until: 31/12/2023 + + + addCoupon("WELCOME10")} + disabled={isCouponApplied("WELCOME10")} + > + + {isCouponApplied("WELCOME10") ? "Used" : "Use"} + + - addCoupon("WELCOME10")} - disabled={isCouponApplied("WELCOME10")} - > - - {isCouponApplied("WELCOME10") ? "Used" : "Use"} - - - - - - $20 Off - - $20 off your order over $100 - - - Valid until: 30/11/2023 - + + + $20 Off + + $20 off your order over $100 + + + Valid until: 30/11/2023 + + + addCoupon("SAVE20")} + disabled={isCouponApplied("SAVE20")} + > + + {isCouponApplied("SAVE20") ? "Used" : "Use"} + + - addCoupon("SAVE20")} - disabled={isCouponApplied("SAVE20")} - > - - {isCouponApplied("SAVE20") ? "Used" : "Use"} - - - - - - - Free Domestic Shipping - - - Free domestic shipping on your order - - - Valid until: 15/12/2023 - + + + + Free Domestic Shipping + + + Free domestic shipping on your order + + + Valid until: 15/12/2023 + + + addCoupon("FREESHIP")} + disabled={isCouponApplied("FREESHIP")} + > + + {isCouponApplied("FREESHIP") ? "Used" : "Use"} + + - addCoupon("FREESHIP")} - disabled={isCouponApplied("FREESHIP")} - > - - {isCouponApplied("FREESHIP") ? "Used" : "Use"} - - - - + + - - + + - - - - {/* Modal 表单 */} - - - - - 选择收件人 - - - - - - - - {addressList?.map((item) => ( - - { - setAddressId(item.address_id); - }} - > - + + + + 选择收件人 + + + + + + + + + {addressList?.map((item) => ( + + { + setAddressId(item.address_id); + }} > - - - - {item.country} {item.receiver_first_name}{" "} - . {item.receiver_last_name} - - - {item.receiver_phone} - - - 设置默认地址 - - deleteAddress(item.address_id) - } + + + + + {item.country}{" "} + {item.receiver_first_name} .{" "} + {item.receiver_last_name} + + - 删除 - + {item.receiver_phone} + + + 设置默认地址 + + deleteAddress(item.address_id) + } + > + 删除 + + + {item.is_default === 1 && ( + + + 默认 + + + )} - {item.is_default === 1 && ( - - - 默认 - + { + setShowModal(false), + navigation.navigate("AddRess", { + address: item, + }); + }} + > + + - )} + - { - setShowModal(false), - navigation.navigate("AddRess", { - address: item, - }); - }} - > - - - - - - + + + ))} + + + { + setShowModal(false), navigation.navigate("AddRess"); + }} + > + + + + + 新增收件人 + - ))} - + + {/* Placeholder for additional button component */} + + + + + {/* Cancel Button */} + setShowModal(false)} + > + 取消 + + + {/* Confirm Button */} { - setShowModal(false), navigation.navigate("AddRess"); + setShowModal(false), + setDefaultAddress( + addressList?.find( + (item) => item.address_id === addressId + ) + ); }} > - - - - - 新增收件人 - - + 确认 - - {/* Placeholder for additional button component */} - - - {/* Cancel Button */} - setShowModal(false)} - > - 取消 - - - {/* Confirm Button */} - { - setShowModal(false), - setDefaultAddress( - addressList?.find( - (item) => item.address_id === addressId - ) - ); - }} - > - 确认 - - - - - + + + + + { + console.log(123); + }} + > + + + {domesticShippingFee?.currency ? "确认订单" : "报价中..."} + + + + + ); } const styles = StyleSheet.create({ - container: { flex: 1,backgroundColor:"#fff" }, + mainContainer: { + flex: 1, + backgroundColor: "#fff", + }, + container: { flex: 1, backgroundColor: "#fff" }, header: { flexDirection: "row", alignItems: "center", @@ -865,7 +959,6 @@ const styles = StyleSheet.create({ borderRadius: 8, paddingLeft: 16, paddingRight: 16, - }, sectionHeader: { flexDirection: "row", @@ -880,6 +973,12 @@ const styles = StyleSheet.create({ fontSize: fontSize(13), fontWeight: "500", }, + paymentOptions:{ + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + width: "100%", + }, recipientInfo: { backgroundColor: "#fff", borderRadius: 8, @@ -1028,15 +1127,19 @@ const styles = StyleSheet.create({ borderColor: "#ddd", padding: 12, borderRadius: 6, - marginTop: 10, + width: "50%", }, paymentSelected: { borderColor: "#ff6000", backgroundColor: "#fff8f3", }, + paymentIcon: { fontSize: fontSize(20), marginRight: 10 }, paymentLabel: { fontSize: fontSize(14), fontWeight: "500" }, - + tabContainer: { + width: 100, + flexDirection: "row", + }, mobileForm: { marginTop: 12 }, countryCode: { paddingVertical: 12, @@ -1549,4 +1652,26 @@ const styles = StyleSheet.create({ backgroundColor: "#f5f5f5", marginTop: 12, }, + bottomButton: { + width: "100%", + justifyContent: "center", + alignItems: "center", + marginTop: 12, + paddingHorizontal: 16, + marginBottom: 12, + backgroundColor: "#fff", + }, + bottomButtonContent: { + backgroundColor: "#ff611a", + width: "100%", + justifyContent: "center", + alignItems: "center", + paddingVertical: 16, + borderRadius: 25, + }, + bottomButtonText: { + color: "#fff", + fontSize: fontSize(16), + fontWeight: "500", + }, }); diff --git a/app/screens/login/Google.tsx b/app/screens/login/Google.tsx new file mode 100644 index 0000000..853f6ed --- /dev/null +++ b/app/screens/login/Google.tsx @@ -0,0 +1,89 @@ +import React, { useState, useEffect } from "react"; +import { View, StyleSheet, ActivityIndicator } from "react-native"; +import { WebView } from "react-native-webview"; +import { useNavigation } from "@react-navigation/native"; +import { loginApi } from "../../services/api/login"; +import { useAuth } from "../../contexts/AuthContext"; + +export const GoogleScreen = () => { + const navigation = useNavigation(); + const { login } = useAuth(); + const [loading, setLoading] = useState(true); + const [loginUrl, setLoginUrl] = useState(null); + + useEffect(() => { + const fetchLoginUrl = async () => { + try { + const response = await loginApi.google(); + if (response.data.url) { + setLoginUrl(response.data.url); + } + } catch (error) { + console.error('Failed to fetch login URL:', error); + } + }; + + fetchLoginUrl(); + }, []); + + const handleNavigationStateChange = async (navState: any) => { + console.log(navState.url); + + // 检查URL是否包含重定向URI + if (navState.url.includes('localhost:8000')) { + try { + await login(); + navigation.navigate('MainTabs' as never); + } catch (error) { + console.error('Login failed:', error); + } + } + }; + + if (!loginUrl) { + return ( + + + + ); + } + + return ( + + setLoading(true)} + onLoadEnd={() => setLoading(false)} + javaScriptEnabled={true} + domStorageEnabled={true} + startInLoadingState={true} + scalesPageToFit={true} + 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(request); + + // 允许所有请求 + return true; + }} + /> + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + loadingContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'white', + }, + webview: { + flex: 1, + }, +}); diff --git a/app/screens/PhoneLoginScreen.tsx b/app/screens/login/PhoneLoginScreen.tsx similarity index 98% rename from app/screens/PhoneLoginScreen.tsx rename to app/screens/login/PhoneLoginScreen.tsx index ae379b4..66e5ea1 100644 --- a/app/screens/PhoneLoginScreen.tsx +++ b/app/screens/login/PhoneLoginScreen.tsx @@ -9,13 +9,12 @@ import { Platform, Modal, FlatList, - SafeAreaView, } from 'react-native'; import { useTranslation } from 'react-i18next'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import { RootStackParamList } from '../navigation/types'; -import { Country, countries } from '../constants/countries'; +import { RootStackParamList } from '../../navigation/types'; +import { Country, countries } from '../../constants/countries'; export const PhoneLoginScreen = () => { const { t } = useTranslation(); @@ -35,6 +34,8 @@ export const PhoneLoginScreen = () => { }; const handleContinue = () => { + console.log(123); + // 处理继续操作,发送验证码 if (phoneNumber.trim()) { // 这里可以添加发送验证码的逻辑 diff --git a/app/services/api/login.tsx b/app/services/api/login.tsx new file mode 100644 index 0000000..1cd6910 --- /dev/null +++ b/app/services/api/login.tsx @@ -0,0 +1,8 @@ +import axios from "axios"; + + +export const loginApi = { + google:() => { + return axios.get<{url:string}>('http://124.70.102.7:8000/api/auth/google') + } +}; \ No newline at end of file diff --git a/assets/img/google.png b/assets/img/google.png new file mode 100644 index 0000000000000000000000000000000000000000..e57cb2f6278eba1298129e1e67f72a013709075d GIT binary patch literal 8568 zcmV-;A&1_HP)PyA07*naRCr$PT?u$q)wTZDx%XteVKj*ru%$d}t*A&6a70KVIMr7L!XS?H>uasN zs@19qR2-n9uhsh6+P+t7)k+94=yO8g-kYc(gnQ$FL-hgrswh)HAPFS7_n!57E`x+j zcR0g7H~V}ahL5bh*1!I}fA<;oUYj5<$$(^_TLwsSBN>nkbkBekhy|l#@1(N_wT9b< z5-URp$`B3OP*NyEVPr&rOaf(qIFlF|05Tbf0Ney9`#`*p82bS1(+Eup^FG$FPXX@= zg|$ykc;oGz7NpQ;Lr8%b)b+bd3;KtMMk*RcGASd$tp6Dbq9OXAHz-V3ZglZ{0$?+P zK2e};)__mai8c@L2K0ZIR}u_Jfh0iQSK~(wXm_QJSAcUEJd%Ks3=B)al?6>`HJDcu z(HgiT4Y?~CwptK0WkN`S#L$&r3xdznfb$6$6GJmmP2OW*twLx(L}|#at#1$&s0g^E zK)UILofF3vK#LSJQ!#+^0c4BNVTNNM+63km#8`3M;QcG8`h#}EV>sBM6v&~@`||q* zS?YdQvBp|4QB)LXIJjREh5k8!6#%cG*7Oy*Yt}R+>L^v(^?8A8Eh(7bf@>DQmjcL7 zm5wzakL>`hAi|2~aMrTnb#<)<_;j3$J}Z!IrDJ9)%(DPo?6_XD9`Hs6DqRt+^0>N& zkE{=GU&KBoknJU7^8sxZ0lF|o*+;uGBNGr}a3w&MdA`7_&dee{)O|uA+a`_~u4vk9 zfNlWeg!m|u*4;4hIx|(e(`oVG<@Nfvn3TLyS|E+3XPpw^$ZP^;0~nB!J!o@M417kw zA9Eww4^s+0r=+Anc9a&L38vW$=;F|qZ^+Ah2HsJK9zM>y{wecASr;Lt1hTVa%y*cz zn?N+jItpc^qZuI3%Np?``QCsx6_`m0fowhh%v>eSJx3wBiJ1qcLdQ5g2WI@YOL0AX zoOj*dot%rK1;XRUyBpojb2O$o1Ppg_N2DnBz0CZ`=X-fUVM9a6i8(q}AloJsUalx~ zH-OPjB)%_UW?-EHT9E5o|B}=4cAP*yKl|*=jI78#48GlIWcPWzM889r7v$9iwmF3h zM+szmN#TV6-Alk(P9a$0?8LxEfEMKW)<5Y4ZX6?!?IlIJFy=XdREe>728gIK64n+T zUl)A8cWe7Bgcr!xlCj@&LHiAWN%qksBb&hh0lUF;N3MVUpUv=ZgioObvZJJM3P8Fz z1l_G?L>EXO41O@*7raA6CWIBp&XS^e4BRUsX%dqO3^0~K%f2?RuCCbx?+LpUP9Qrc z6`a6fMV~dMC!CdR=uie|0~EeCZ&lzOQ4$bJAUnnvje?7x1n6{82$DD~XW#%6U!Cs_ z)>t07i-5uiWLN3fvozMK85k-8F%pB#3^3i9=U>0bW)u)YAP2X-Dt^1kknu%ffH#na zvfSF>$95yKT_8J4#$3kW7wslO#utWxx0toEe1F4c5fIrbke#K4w=>g&A`l@l*v|kF z)w>WW8{}>H%ziWn5!fb>?Zt)jiK2@QI|M+}0fOZMk>U_-2-u5<0I!;nUN+$6)nD0*r0eLG3Pg%S#35iSrdO#o ztxV(!j+O~Tio@1{C|qy?UOX<6T_$=Z6iWoMv$W_(%=nXVy(9tI#lUm92gMP#3qY)K zO&5s#&Jk-@^btEkb)Gj+=9Fwr70AvBV+&Z()&X!kg%F9;JO+rdIM*Mz%Df21dp1oV zhgRj*0yx=t*wUlZ7+~;I`M%(_PQz`QKz5WAy&@~8J8d|ag_j@C^96rsmUlD#nj(wl4Gdy(21CXgK^MZX7dqe#iwfaOaD z>Rq69|2zov^}*hH{S~)m*RJBCb0P|gnRya{&a*6V$3VZz^99OnifwpULj9a*uuCHGI2i9t~_tx0mJ+W zc51c>?kRkc5p@^{e1X@F9L4M^#y*N zumiyxCMA#^B}K~sTp@Ul3B!vXd(2p*x!WE%e&vRigdGXoaBFGdcsDDv7_1+38t-*; zo-gp*cpEv%K4F3EC@s7JOpiM$*?6!r_<5Jc4;)w9P#;e_r`qbPt~KyH0>;FWg97~Y zIA7oovDiAU$S-<(rX<3@ z<$44E<>Y}MEB1s0vc0(IHX=L}YY@lS5gtJpi=1=Ilyve>xFOFQ zc*2ahBKnM5AlpmE<`c9aQmaJhIws6Zm7|M|7-;%zqP0bCVIuvgyKLPjGhdVM4?b;# zf2a6}TOcX;TK7pc61sVy;NLRr8c_OdLd>@i_^-LX;1auV*cCS}fqXHc@MO0_`YX>& zy8s&;w>-}m_?5vvQ_h_}n+#rFzc1wyiy@)71hVte(NA-$YgP`fF-= zNd~%QAZCHIdNaO_UGB~Mmwmf7+?YPW$(*{NoI2Q7|Dls}kl3wZAZCGtylM9W96e=r z|0}~*x4t|0d-{F_YhW4{<>TBz-#V45t0RVal#WuGftUosFCr_P>HZj?BZu3B-W&M8 zEw2u1=CCr_2@Emg{d|AmG$&w{7{y^ACV{kj)gKW$7k-O0W?=vG-+C>)GvfkrQtA@P z-aKDmfZ!Mx(HViry zKu)}Ejk0H^hx7gGWo<5_2<@YOdK5_eD)mt!BvjX^{k=h(TV5S{0AXdM)!Z`C)A`=@ z*H|4_#!Ed0x)lho$Q%}Sh2I4*FwwNNW);nqBi@WOW}K6#kGR_r-fwfcFBrCB?e4hS z$_A2wV;JaGAQ7*6qXy`ue3HIeUi#+x_V)(rw_MRxp=Mqh^UUM@!Adh@NZ);jfo=s7 z^17b`=m$no5&CGrrj{2^3~^XF#VDU$_<1tV7r4$u|I&3IW1vfca4iOeBkJb>JVx@t zZ7wuDby9t#F=MQeeh>ND21OZ{x2k@l3BIMvKFUCs0%`N6U8R8kW)>&=UmjN9x?%7c z1Y{T%gLzJ#KlnSt{7FZW0qDoKcX5Ti>Jto@daDxJ+;3CMbKlZ9q;2pBIEs$G~Nc~u5z9-)woNpyw8LRIw&`BU|tI{4+i1m&7mR{k{vo|(X zjZhF$M#K?#pXQ=b$FE%fX&h~&sbnB#2096(-K)M&fd0+GmTTV=->Hvm%Zl|a*Q0s9 zz|U*}Dueb32093YU&|OC4n=HV7Ji`agg4vP=8xfCj*lkR3Ud7oZ}o|ul1bXaKnH=e zuTtj_;Za+V91}FMEpy|(XHIgVUHNubc=Te@xxPS36p#>sZ;7F62092N>{Fj&j+Vw3 z=4yKSq&49!+2d5LA>g_1e`8frmbu9)*Pt&hQ8qOAYS5? zdEVe8(QryUsmDMEfrPv&i<)9&SH|Y1r%r0;R+qk(YkHn9P$eo>i7Ry&I3f`Crkx%J z>&x4PzM3jWygumhk3=sLAvA{)TV>hi0g)x^D;YqPdg%zkT2~aFyCe>3PYUpM71=$$`DtAIw@YzEbOhWpp+#I zi;4cVwmkcVV;vn4NZ6OQf|(~K9m!+|?g61RDn!WSFt)mv0lwtW zZUc~S2eg=D65dx!LMdMzQ3@pH5n-g^5`TqfMwc@PdyyYTR3L(1v`8&&zf*9KNyC!@ zNt(j=9S}b7mwP%D7>Ujxtt;IVT?(y;->bDPNYO5J7e`*PHmdc}q(H3aT#x8Z2xRqoqBB>b6!ZdWLWCZO3K`mBp81!5i7M@M4dqS^{ihl%2#K)h)W0DOl% zuwst-mRcGrh}qh~hEgE5b>5x+3eTcWGf3E{{wFhTvJF-&ff>RwvUR{#ha{y0`aB24CYI0f)!g>=8Mz|!@|F5i!GU+t)xJVU@;*d zTl^KCVV#~qLS9ub(l9O|mlic*LP1(ds88%3lmfA6P<0B!`}`F-{ksxK5P;Bch}^3C zM7rRBUhOgEFDVfFy4YXg>97Ul&@GnwcQC$dAFSRZZ`&Qp8din_y<0lpLJGvbK1^@V z?!WvV+IJYip@($$=SQDlYahIBBR8w1A=?h)v6>Gl5UUygI-cfMhSlAXwdELrsQOtN z37-REb~*%n>Mjj+S-ipQ*mn4r0A08`^HUMe%!Rk3O1A(;C&=^ti z8I4N{#Arri_eZ3i<16pCwu3;zUbQWevY)YsP0msZBsuo^!-kRNp0|8RPn9kOlywMP@{PC=|JOQU_aldt3kI z_Y6MvJBa!^fb&I8Q!X_Txpz_r+u(Py-PP3;Ic5e)TMqC=LZ>MgD+=8`DFUwbpBtt! zkIv=rm-J@=nk;gXB$vC3+&w9Rjd%Gga*pdHkan;7BmvimoTc0_C35ei47Shw6`pT) z7RV~~4@CHh;Ay6O$WA6`l^Kt3_|I+E%4Kq>%7sM?X+YL!Igt*+!*_ zfu%r9B)2EmL;-(!c84WRhXmrDuMpjB6ReoSy2GKtbP@E0l_`Bmf!Nc%OsK0Z_e|(? zixu{zUBS%D?12?~)V}hdE(H?%m@v|ki5{;l&;DU2fwcP4N4Qu!@_F6Jpho&4;IHn| z(Dg?86w#Lyh&{c+tX0&`?YFR#K=gkId(|ceJoZ3~H7ajWOT!&D)yLY>Np?~o_Vkv< zJiTsiPKT4rj;`*$20(|JK=#1wIci^c4v_+}XXI&2MRjwt_4*7)uCGs+TBSZlgdf`j zE%vB=;W9<+JUJPu!YWIY9tIJkS6&9ocz@$J7ATdrC3qH@GU3v0`> zD|!@2$m?DP&=sO2p_lt9`>OcE&mx{nI{_zL7?@V$6$Pur(K7?Z3!3$P-lvPolcs4u ztee;G@g4=zwo05OCmTY8yf^MWcSr`*Z_?d?3%ToGbUDUx8FRlr{YAGO%JG?%P z*N55mn#L3A=H=A&D3JD5>X}5ay+HJTw4DAwHLc&e6byGy#4xy^Vfr%L@tWOvPWNB3 zpy{U!`kknG5UAZ(k)7TZz7BrHA`@2n%ROB_({>ifD)mt!%&|I|_2JytZ{2fNZg;m--Qd}$ zv@4_5UsL_5)p%vR*ch1jP*YyGojwLIAhs6PTM^+7U%BVOm}ZdBD)%H1y=o=Qh0UW@ zyx4l8zRWoO@~6!A1ZOOpZzWzCD|QA-7Pic0=0C^Y!g@=M!$oy-2Xy(2)M*CcAk^@l zXfbQk7cPdOY@fEfc;lB^)_F^ zX(xdkdJg#;0aqCjy*nRuZQrP$+f?9*fI4h(Oe7`&F9oL8d_R%4vWgisC27x#{S}^W$9mTS@u}Ala&d7FUY@wc|F1-sqft-T{dpXIu|x)g|R8S<*D0F)X9bw%6I zckXW<p1*=!K4LK7)cA`FFZl_^paAr+q%=XgIa0aF>W!J8aE&2ysVV9OflO{ak zFZbNi69L@{q-7h1ph!9&fbg~L$Jh{fJuo2P@* zYlN;8X>h*6xEsHqd6WXwiu_?PN*3c?|6I?g-iYg2Ab!^+tSK+|=H%Gl-`hO;jpeOF z_2BlMOiOq;IIZT^c(F_SH`qd+Ndp&tk$3J zJG=g~NcIK21-9t-bA!`s7FZOk&xdi!tyT2#BN7?o`(^)LA0c`bNZ6}h%fMfI>-`s6 zzxmOBG><$Gf=hoG7v>_uw7|5QrNRJ8Q6R{kB{An&lVS6YXCw5a8bmUdQp{Lm5)c9U)24^FQ! z?IWeh*oAdpd|%UiDB>4B|C&I4-d~Xu^S1Js1fn}{^QJ9Qz`xM{zOZ@J8!xt=s4p_? zR7XhIo;(QbOYIRxlku&H7$15~E=ZPcwaqtFzxhLjzhA|7Ib$R;9Ta>Ji%J&x4 zexl`cC=oAoFLnXWr6{M?msNl0G~6QLb)q;3*b2%%%~wvlV&yVsf#?p4t1f?fAFC-* zD1kte1Jj=s{>X<|JJL!!CyGPohY;JhkE6MaOCW_$Pdyo`_BMbHCxKeoIY!1J;_|?> zWxq1gXR7-uUeK)Ho;Yzq=q_-mz(03jT&vXM5{TaUg-a&i|IatSoeFF@bzl(T$xvG4 z=69}meveagunKqa!j`3Ac52zzMg9uUo$+!Nw?M`&o{=A+_8+|}@y;mr1f#?(#RZh8$i93B45mf-OTR*NNo~uL11cD(vi_%pdkwcoJHdmykflKXF|~b4F7=NbvRkiS^(nFh3BS zv8+=W%Ea6`x7CFEn-&mJxpOm!B5xy7NBhdt6MAczkU*l(B9)VG03nqJ(euoBpkYQ$ zy~77c-0+L4rp(LO`tPTxEu&||-B_>&4ElX-MfOdJ!b(^m(Oa#mDa)8S=C6{8g0!(+ zh?o|&g)$%5aLv;#HsY`(bm5Z8w-e|t1`pH&s!d~F%GmMK0s>C31c32D*aeJURpEIj zQP)Wcq@Z&0SR$+jdaj|HC^&)Iz0JhWxI?I_pS5g@K)4KnQm|z5PYBRUxSo8hL*k5$ zo=+d$Oq_m^A;BzkqL-%im3xvZO`DWJqPJQp_S(0{{v+%GQx%g|)i71HD$6$@=mai`@rKo#~*2KXQlof|c`gb|iy2X@Q*k_~kjR+3Fhv*s--XncS0Y ztM7fN3Lns_-nrg6-%tvcPCZYF@FXVIi#5mfW=d@u_gv zIcb4JXOXJOGr(A!EEq?&Cu||6D$*h~>t{ZT~NDyNh%;WB{r>XS*GAV%SV?|VLb zXgjf5B4VzGF#XM6;knufe1-@_2U4(P%I^t$qYw~{!Mm;H5=VH8WSH0lTOQ#mN zG_8Oc<3Z3xVR)V8>@R+~*ws2hyjw294h`A`b>;m&GGZJVCXln2PR$HynqC#&$`U_D zaA2YjZUm#A71WYO{@{!neI1*j*AX!Q`rD=g1}xj3lfL(&>h#8$mjG;jy|WluW9FaL z&dqr=M)O|H3=@bRsc6ZSMU3dt3Buo__R5So1|bl1(df&q8v*?%Hv)9%-?$MP?b6(c zD8xBn>Ide21nQ?D`ZEXMegO3&Am2(cbVr9PG_)c6v-?^A#rFR(67aIG!gHCCU1z93 z4vOT8>lw;lj07otiO+y%%Y93fwiE5#b{i&A#`()EqXTp-bh_9c^l4IrVlFX9gc ziLg5c(sxg(PXFriD**2CY)MlX)c79%yd1+1QZhv#heYxUfQwBbLpl|f0axpH*JXWi z2MEep7J~e%zru698SzXLNI}h&Cs2s=k7=F0&YF>k^eGMl#ObZsTjsx{w0~oY*{B$_ zx-~Ov;@Vs3fElq&6NnC0f5W0^ntn8z^;51HY)PMSF_77KZH>COcye5g;xyJsJ*BQZ z-H=zhU4=GPAbP+tOQu|=fnSU>Z)u()47ghgS7&XTqgPuTZFEYcMK1Qu>u>6Tv!)B= z;G3<ttMKSAgG{|F5lHl*z4FTWASV?V zGnMx~={$4Wk6%z*&Q4w=jFtYm9(^sD>6c{!ks>j@FC7s;-FLwonLDl@1WNpLV}FIm zvTS0JJ`tv$<<93B;V`AcTLx9^RT zzL_zBej1qm>>otSURZ%dUjtWOIRzA*O@@g^oWx@o1DiC$O>a%BSz(w*104x15IxVa zOQ(KM)3o0(V9DY%1G$y1dS_rc!#$^Ade!FMP3^G|ULc2QDX6^iULu-j4^1+v(F_pN z{ecs3MvslY?k`B1HZL&qIa4<}8AYs6gF4 z0Q6-l@^TOZ4E#1DGc<3_zrJAUg2QAea-2X8CtFx~<>iMqU>UxZGZ{i<+b$XSm_hRz zraxQlG=3Z_5S{4pwd38*+Xl}8VGe-dP9wih;AQ+J0(IWoGnRbm#C#nski&$ZxpZo- z5{b-FNV)0o=}1oOjFiGm^eTuR3zk*C;N-kgLLi4bV9b&$zN5i)6Tte6A}@OwsAbS& zPQ0D!imsFr$dTuhXD6SD2xfyZ8$gCV0y%Q)wRGxmP19zBa0A$}C$@^EDS}=MurfHU zrcx|m#-iyH0y#|C*u|IUhh6Sj#54=QC}XMY1K#v=O$e2WqAXrtR&D4p1ER9mrv!3z zClpj(Ig=P`4K>o!Xx`G7_we1o*IMh5{G@Ak&~Q z-MV4m{|ML&&?bO4D~hs-L)yE6t7<+mJ9aAjmjbb%ch6orbx>Pa8>%QYgn=Q%+E7v` zLt|u6R6LYH;7lfDfTLp4`=yPU+eo2SX0#EgjfmT#e`jjbz&lC7CXlk(^Wo0Tb@S^i yt9Wh!Wx|Az0uiPwBoGl9kOC30S0pB382EqiE}vhtsoVqr0000