diff --git a/app/constants/config.ts b/app/constants/config.ts
index 995b1fc..5614a50 100644
--- a/app/constants/config.ts
+++ b/app/constants/config.ts
@@ -18,6 +18,7 @@ export const STORAGE_KEYS = {
AUTH_TOKEN: 'auth_token',
USER_INFO: 'user_info',
LANGUAGE: 'app_language',
+ CURRENCY: 'app_currency',
};
// 默认请求头
diff --git a/app/locales/en/translation.json b/app/locales/en/translation.json
index c20377d..84004e5 100644
--- a/app/locales/en/translation.json
+++ b/app/locales/en/translation.json
@@ -97,6 +97,7 @@
"my":"My",
"categories": "Categories",
"chat": {
+ "tab_label": "Chat",
"customer_service": "Customer Service",
"product_support": "Product Support",
"notifications": "Notifications",
@@ -181,6 +182,12 @@
},
"settings": {
"title": "Settings",
+ "country": "Country",
+ "currency": "Currency",
+ "language": "Language",
+ "success": "Settings saved successfully",
+ "login_required": "Please login first",
+ "confirm": "Confirm",
"profile": "My Profile",
"change_password": "Change Password",
"change_phone": "Change Phone Number",
diff --git a/app/locales/fr/translation.json b/app/locales/fr/translation.json
index 794aa61..7e1de0e 100644
--- a/app/locales/fr/translation.json
+++ b/app/locales/fr/translation.json
@@ -97,6 +97,7 @@
"my":"Mon",
"categories":"Catégories",
"chat": {
+ "tab_label": "Chat",
"customer_service": "Service Client",
"product_support": "Support Produit",
"notifications": "Notifications",
@@ -114,13 +115,27 @@
"sales":"ventes",
"productPicture":"Image du produit",
"no_stock": "Pas de stock",
- "setting": {
- "title": "Sélectionner la langue et la devise",
+ "settings": {
+ "title": "Paramètres",
"country": "Pays",
"currency": "Devise",
"language": "Langue",
"confirm": "Confirmer",
- "success": "Paramètres enregistrés avec succès"
+ "success": "Paramètres enregistrés avec succès",
+ "login_required": "Veuillez vous connecter d'abord",
+ "profile": "Mon profil",
+ "change_password": "Modifier le mot de passe",
+ "change_phone": "Changer le numéro de téléphone",
+ "my_address": "Mon adresse",
+ "feedback": "Commentaires",
+ "privacy_policy": "Politique de confidentialité de Brainnel",
+ "terms_of_use": "Conditions d'utilisation",
+ "clear_cache": "Vider le cache",
+ "language_currency": "Sélectionner la langue et la devise",
+ "add_new_address": "Ajouter une nouvelle adresse",
+ "address_management": "Gestion des adresses",
+ "set_default": "Définir comme adresse par défaut",
+ "delete": "Supprimer"
},
"login.now": "Se connecter maintenant",
"login.button": "Connexion",
@@ -307,22 +322,6 @@
"submit_order": "Soumettre la commande",
"select_payment": "Moyens de paiement"
},
- "settings": {
- "title": "Paramètres",
- "profile": "Mon profil",
- "change_password": "Modifier le mot de passe",
- "change_phone": "Changer le numéro de téléphone",
- "my_address": "Mon adresse",
- "feedback": "Commentaires",
- "privacy_policy": "Politique de confidentialité de Brainnel",
- "terms_of_use": "Conditions d'utilisation",
- "clear_cache": "Vider le cache",
- "language_currency": "Sélectionner la langue et la devise",
- "add_new_address": "Ajouter une nouvelle adresse",
- "address_management": "Gestion des adresses",
- "set_default": "Définir comme adresse par défaut",
- "delete": "Supprimer"
- },
"login": {
"logInOrSignUp": "Se connecter ou s'inscrire",
"phoneNumber": "Numéro de téléphone",
diff --git a/app/locales/zh/translation.json b/app/locales/zh/translation.json
index 78a5c63..89f05ef 100644
--- a/app/locales/zh/translation.json
+++ b/app/locales/zh/translation.json
@@ -96,6 +96,7 @@
"my": "我的",
"categories": "分类",
"chat": {
+ "tab_label": "聊天",
"customer_service": "客服聊天",
"product_support": "产品咨询",
"notifications": "消息通知",
@@ -114,13 +115,27 @@
"no_stock": "缺货",
"loginRequired": "需要登录",
"loginPrompt": "请登录以访问此功能。登录后您将获得更好的体验并能跟踪您的订单。",
- "setting": {
- "title": "选择语言和货币",
+ "settings": {
+ "title": "设置",
"country": "国家",
"currency": "货币",
"language": "语言",
"confirm": "确认",
- "success": "设置成功"
+ "success": "设置成功",
+ "login_required": "请先登录",
+ "profile": "我的资料",
+ "change_password": "修改密码",
+ "change_phone": "更换手机号",
+ "my_address": "我的地址",
+ "feedback": "意见反馈",
+ "privacy_policy": "Brainnel隐私政策",
+ "terms_of_use": "使用条款",
+ "clear_cache": "清除缓存",
+ "language_currency": "选择语言和货币",
+ "add_new_address": "添加新地址",
+ "address_management": "地址管理",
+ "set_default": "设为默认地址",
+ "delete": "删除"
},
"homePage": {
"searchPlaceholder": "搜索商品",
diff --git a/app/navigation/TabNavigator.tsx b/app/navigation/TabNavigator.tsx
index ff14010..9d0ac98 100644
--- a/app/navigation/TabNavigator.tsx
+++ b/app/navigation/TabNavigator.tsx
@@ -186,7 +186,7 @@ export const TabNavigator = () => {
name="Chat"
component={ChatScreen}
options={{
- tabBarLabel: t('chat'),
+ tabBarLabel: t('chat.tab_label'),
tabBarIcon: ({ color, size }: TabBarIconProps) => (
),
@@ -251,11 +251,11 @@ export const TabNavigator = () => {
×
- {t('login.loginRequired')}
- {t('login.loginPrompt')}
+ {t('loginRequired')}
+ {t('loginPrompt')}
- {t('login.loginNow')}
+ {t('loginNow')}
diff --git a/app/screens/HomeScreen.tsx b/app/screens/HomeScreen.tsx
index aa7ba15..32ac1f2 100644
--- a/app/screens/HomeScreen.tsx
+++ b/app/screens/HomeScreen.tsx
@@ -657,7 +657,7 @@ export const HomeScreen = () => {
- {getSubjectTransLanguage(item)}
+ {getSubjectTransLanguage(item) || item.subject_trans}
@@ -673,7 +673,7 @@ export const HomeScreen = () => {
- {item.sold_out || "0"}+ ventes
+ {item.sold_out || "0"}+ {t("homePage.sales")}
);
diff --git a/app/screens/ImageSearchResultScreen.tsx b/app/screens/ImageSearchResultScreen.tsx
index 2900576..34b4093 100644
--- a/app/screens/ImageSearchResultScreen.tsx
+++ b/app/screens/ImageSearchResultScreen.tsx
@@ -1,4 +1,10 @@
-import React, { useState, useEffect, useCallback, useRef, useMemo } from "react";
+import React, {
+ useState,
+ useEffect,
+ useCallback,
+ useRef,
+ useMemo,
+} from "react";
import {
View,
Text,
@@ -17,7 +23,11 @@ import Ionicons from "@expo/vector-icons/Ionicons";
import { useNavigation, useRoute } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { RouteProp } from "@react-navigation/native";
-import { productApi, type Product, ProductParams } from "../services/api/productApi";
+import {
+ productApi,
+ type Product,
+ ProductParams,
+} from "../services/api/productApi";
import { useTranslation } from "react-i18next";
import isSmallScreen from "../utils/isSmallScreen";
import { Svg, Path } from "react-native-svg";
@@ -230,113 +240,152 @@ export const ImageSearchResultScreen = ({
const [isFilterVisible, setIsFilterVisible] = useState(false);
const [sortOrder, setSortOrder] = useState<"asc" | "desc" | null>(null);
const [sortField, setSortField] = useState<"price" | "time">("price");
- const [activeTab, setActiveTab] = useState<"default" | "volume" | "price">("default");
-
+ const [activeTab, setActiveTab] = useState<"default" | "volume" | "price">(
+ "default"
+ );
+
// 获取初始图片URI
const imageUri = useMemo(() => {
- console.log('获取图片URI', route.params?.image);
+ console.log("获取图片URI", route.params?.image);
return route.params?.image || null;
}, [route.params?.image]);
-
- // 将图片URI转换为FormData
- const uriToFormData = async (uri: string) => {
+
+ // 将图片URI转换为base64
+ const uriToBase64 = async (uri: string): Promise => {
try {
- console.log('开始转换图片', uri);
- const formData = new FormData();
-
- const filename = uri.split("/").pop() || "image.jpg";
- const match = /\.(\w+)$/.exec(filename);
- const type = match ? `image/${match[1]}` : "image/jpeg";
-
+ console.log("开始转换图片为base64", uri);
+
const imageUri = Platform.OS === "ios" ? uri.replace("file://", "") : uri;
-
+
const imageFetchResponse = await fetch(imageUri);
const imageBlob = await imageFetchResponse.blob();
-
- formData.append("image", imageBlob, filename);
-
- console.log('图片转换完成');
- return formData;
+
+ // 转换为base64
+ const reader = new FileReader();
+ const base64Promise = new Promise((resolve, reject) => {
+ reader.onload = () => {
+ const result = reader.result as string;
+ resolve(result);
+ };
+ reader.onerror = reject;
+ reader.readAsDataURL(imageBlob);
+ });
+
+ const base64Data = await base64Promise;
+
+ // 记录图片大小信息
+ console.log(
+ "原始Blob大小:",
+ imageBlob.size,
+ "bytes =",
+ (imageBlob.size / 1024).toFixed(2),
+ "KB"
+ );
+ console.log("Base64数据长度:", base64Data.length, "字符");
+ console.log(
+ "Base64数据大小:",
+ (base64Data.length * 0.75).toFixed(0),
+ "bytes ≈",
+ ((base64Data.length * 0.75) / 1024).toFixed(2),
+ "KB"
+ );
+
+ // 提取base64数据部分(去掉data:image/jpeg;base64,前缀)
+ const base64String = base64Data.split(",")[1];
+ console.log("纯Base64字符串长度:", base64String.length);
+
+ console.log("图片转换为base64完成");
+ return base64String;
} catch (error) {
- console.error('图片转换出错:', error);
+ console.error("图片转换base64出错:", error);
throw error;
}
};
-
+
// 搜索图片
const searchByImage = async (uri: string) => {
if (!uri) {
- console.log('没有有效的图片URI');
+ console.log("没有有效的图片URI");
setLoading(false);
setShowSkeleton(false);
return;
}
-
+
try {
- console.log('开始搜索图片:', uri);
+ console.log("开始搜索图片:", uri);
+ console.log("用户信息:", userStore.user);
setLoading(true);
setShowSkeleton(true);
-
- const formData = await uriToFormData(uri);
+
+ const base64String = await uriToBase64(uri);
+
+ const userId = userStore.user?.user_id || null;
const data = {
- formData: formData as FormData,
- user_id: userStore.user?.user_id,
- type: 'formData',
+ image_base64: base64String,
+ user_id: userId,
};
-
- console.log('调用图片搜索API');
+
+ console.log("调用图片搜索API,用户ID:", userId);
const response = await productApi.searchByImage(data);
-
- console.log('图片搜索完成,返回数据:', JSON.stringify(response));
-
+
+ console.log("图片搜索完成,返回数据:", JSON.stringify(response));
+
// 确保我们有有效的产品数组
const productList = Array.isArray(response) ? response : [];
-
+
setProducts(productList);
setOriginalProducts(productList);
-
+
// 立即更新状态,无需等待
setLoading(false);
setShowSkeleton(false);
- } catch (error) {
- console.error('图片搜索出错:', error);
+ } catch (error: any) {
+ console.error("图片搜索出错:", error);
+ // 更详细的错误处理
+ if (error.code === "ERR_NETWORK") {
+ console.error("网络连接错误,请检查:");
+ console.error("1. 手机是否连接到同一WiFi网络");
+ console.error("2. 开发服务器是否正在运行");
+ console.error("3. 后端API服务是否正常");
+ }
setProducts([]);
setOriginalProducts([]);
setLoading(false);
setShowSkeleton(false);
}
};
-
+
// 只在组件加载时执行一次搜索
useEffect(() => {
- console.log('imageUri', imageUri);
-
+ console.log("imageUri", imageUri);
+ console.log(imageUri);
+
// 重置状态,确保每次都是新的开始
imageProcessed.current = false;
setLoading(true);
setShowSkeleton(true);
-
+
// 如果没有图片URI,立即结束加载状态
if (!imageUri) {
- console.log('没有图片URI,结束加载');
+ console.log("没有图片URI,结束加载");
setLoading(false);
setShowSkeleton(false);
return;
}
-
+
// 如果已经处理过图片,则跳过
if (imageProcessed.current) {
- console.log('已处理过图片,跳过');
+ console.log("已处理过图片,跳过");
return;
}
-
- console.log('首次加载,处理图片', imageUri);
+
+ console.log("首次加载,处理图片", imageUri);
imageProcessed.current = true;
-
+
// 执行图片搜索
searchByImage(imageUri);
}, [imageUri]);
-
+
// 搜索产品的API调用
const searchProducts = useCallback(
async (keyword: string, isLoadMore = false) => {
@@ -356,7 +405,7 @@ export const ImageSearchResultScreen = ({
language: "en",
user_id: userStore.user?.user_id,
};
-
+
const res = await productApi.getSearchProducts(params);
if (isLoadMore) {
setProducts((prev) => [...prev, ...res.products]);
@@ -384,7 +433,7 @@ export const ImageSearchResultScreen = ({
},
[userStore.user]
);
-
+
// 处理搜索提交
const handleSearch = useCallback(() => {
if (searchText.trim()) {
@@ -398,12 +447,12 @@ export const ImageSearchResultScreen = ({
searchProducts(searchText.trim());
}
}, [searchText, searchProducts]);
-
+
// 切换筛选器显示状态
const toggleFilter = useCallback(() => {
setIsFilterVisible(!isFilterVisible);
}, [isFilterVisible]);
-
+
// 处理点击产品
const handleProductPress = useCallback(
(product: Product) => {
@@ -414,26 +463,24 @@ export const ImageSearchResultScreen = ({
},
[navigation]
);
-
+
// 返回上一页
const goBack = useCallback(() => {
navigation.goBack();
}, [navigation]);
-
+
// 渲染列表为空时的组件
const renderEmptyList = useCallback(
() => (
-
- {t("noResults")}
-
+ {t("noResults")}
{t("tryDifferentImage")}
),
[t]
);
-
+
// 渲染产品项
const renderProductItem = useCallback(
({ item }: { item: Product }) => (
@@ -446,29 +493,29 @@ export const ImageSearchResultScreen = ({
),
[handleProductPress, t, userStore]
);
-
+
// 创建产品列表项的key提取器
const keyExtractor = useCallback(
(item: Product, index: number) => `${item.offer_id}-${index}`,
[]
);
-
+
// 处理滚动事件
const handleScroll = useCallback((event: any) => {
const offsetY = event.nativeEvent.contentOffset.y;
// 当滚动超过屏幕高度的一半时显示回到顶部按钮
setShowBackToTop(offsetY > 300);
}, []);
-
+
// 回到顶部
const scrollToTop = useCallback(() => {
flatListRef.current?.scrollToOffset({ offset: 0, animated: true });
}, []);
-
+
// 渲染骨架屏网格
const renderSkeletonGrid = useCallback(() => {
const skeletonArray = Array(8).fill(null);
-
+
return (
);
}, []);
-
+
// 处理排序
const handleSort = useCallback(
(field: "price" | "time", order: "asc" | "desc") => {
@@ -510,7 +557,7 @@ export const ImageSearchResultScreen = ({
},
[]
);
-
+
// 处理标签切换
const handleTabChange = useCallback(
(tab: "default" | "volume" | "price") => {
@@ -546,7 +593,7 @@ export const ImageSearchResultScreen = ({
},
[handleSort, activeTab, sortOrder, originalProducts, scrollToTop]
);
-
+
// 渲染列表底部加载更多
const renderFooter = useCallback(() => {
if (!hasMore)
@@ -564,7 +611,7 @@ export const ImageSearchResultScreen = ({
);
return ;
}, [loadingMore, hasMore, t]);
-
+
return (
@@ -604,7 +651,7 @@ export const ImageSearchResultScreen = ({
)}
-
+
{/* 标签筛选 */}
- {t('default')}
+ {t("default")}
- {t('volume')}
+ {t("volume")}
- {t('price')}
+ {t("price")}
{activeTab === "price" && (
@@ -667,7 +716,7 @@ export const ImageSearchResultScreen = ({
-
+
{/* 搜索结果 */}
{/* 搜索结果标题栏和排序选项 */}
@@ -739,7 +788,7 @@ export const ImageSearchResultScreen = ({
- {t('time')}:
+ {t("time")}:
{
if (res.access_token) {
const token = res.token_type + " " + res.access_token;
await AsyncStorage.setItem("token", token);
- const data = await settingApi.postFirstLogin(221);
+ const data = await settingApi.postFirstLogin(selectedCountry?.country || 221);
setSettings(data);
const user = await userApi.getProfile();
setUser(user);
diff --git a/app/screens/setting/CountrySetting.tsx b/app/screens/setting/CountrySetting.tsx
index 4d99333..b1c6600 100644
--- a/app/screens/setting/CountrySetting.tsx
+++ b/app/screens/setting/CountrySetting.tsx
@@ -16,10 +16,8 @@ import { useTranslation } from "react-i18next";
import { useGlobalStore } from "../../store/useGlobalStore";
import { userApi } from "../../services/api/userApi";
import useUserStore from "../../store/user";
+import { saveCurrency, saveLanguage } from "../../utils/storage";
-
-
-// Define CountryList type to match API response
type CountryList = {
country: number;
currency: string;
@@ -37,14 +35,14 @@ export const CountrySetting = () => {
const navigation =
useNavigation>();
const route = useRoute>();
- const [changeType, setChangeType] = useState("country");
+ const [changeType, setChangeType] = useState("language");
const [countryList, setCountryList] = useState([]);
const [currencyList, setCurrencyList] = useState([]);
const [languageList, setLanguageList] = useState([]);
const [country, setCountry] = useState(0);
const [currency, setCurrency] = useState("");
const [language, setLanguage] = useState("");
- const { setUser } = useUserStore();
+ const { user, setUser } = useUserStore();
const getCountry = async () => {
const res = await settingApi.getCountryList();
@@ -70,8 +68,16 @@ export const CountrySetting = () => {
getLanguage();
}, []);
+ useEffect(() => {
+ // 根据用户登录状态设置初始选项卡
+ if (user?.user_id && changeType === "language") {
+ setChangeType("country");
+ } else if (!user?.user_id) {
+ setChangeType("language");
+ }
+ }, [user?.user_id]);
+
const putSettinghandel = async () => {
- // Only include the property that corresponds to the active tab
let data = {};
if (changeType === "country") {
data = { country: country };
@@ -79,23 +85,40 @@ export const CountrySetting = () => {
} else if (changeType === "currency") {
data = { currency: currency };
setGlobalCurrency({ currency: currency });
+ await saveCurrency(currency);
} else if (changeType === "language") {
data = { language: language };
setGlobalLanguage({ language: language });
+ await saveLanguage(language);
}
-
+
Toast.show({
- text1: t('setting.success'),
+ text1: t('settings.success'),
type: "success",
visibilityTime: 1000,
});
- await settingApi.putSetting(data);
- if (changeType === "language" && language) {
- await changeLanguage(language);
+
+ // 只有在用户已登录的情况下才调用服务器接口
+ if (user?.user_id) {
+ try {
+ await settingApi.putSetting(data);
+ if (changeType === "language" && language) {
+ await changeLanguage(language);
+ }
+ eventBus.emit("refreshSetting");
+ const userData = await userApi.getProfile();
+ setUser(userData);
+ } catch (error) {
+ console.error('保存设置到服务器失败:', error);
+ // 即使服务器保存失败,本地设置已经保存,不影响用户体验
+ }
+ } else {
+ // 用户未登录,只保存到本地
+ if (changeType === "language" && language) {
+ await changeLanguage(language);
+ }
+ console.log('用户未登录,设置已保存到本地');
}
- eventBus.emit("refreshSetting");
- const userData = await userApi.getProfile();
- setUser(userData);
};
return (
@@ -108,36 +131,43 @@ export const CountrySetting = () => {
>
- {t('setting.title')}
+ {t('settings.title')}
- setChangeType("country")}
- >
- {t('setting.country')}
-
- setChangeType("currency")}
- >
- {t('setting.currency')}
-
+ {user?.user_id && (
+ setChangeType("country")}
+ >
+ {t('settings.country')}
+
+ )}
+ {user?.user_id && (
+ setChangeType("currency")}
+ >
+ {t('settings.currency')}
+
+ )}
setChangeType("language")}
>
- {t('setting.language')}
+ {t('settings.language')}
{changeType === "country" && (
@@ -225,7 +255,7 @@ export const CountrySetting = () => {
)}
- {t('setting.confirm')}
+ {t('settings.confirm')}
@@ -296,6 +326,12 @@ const styles = StyleSheet.create({
borderBottomColor: "#ff611a",
color: "#ff611a",
},
+ changeTypeTextLoggedIn: {
+ width: "33%",
+ },
+ changeTypeTextFullWidth: {
+ width: "100%",
+ },
countryList: {
backgroundColor: "white",
borderRadius: 10,
diff --git a/app/services/api/productApi.ts b/app/services/api/productApi.ts
index 4bc33cc..ae08871 100644
--- a/app/services/api/productApi.ts
+++ b/app/services/api/productApi.ts
@@ -209,8 +209,10 @@ export interface HotTerms {
return apiService.get(url);
},
// 图片搜索
- searchByImage: (data:{formData: FormData,user_id?:number}) => {
- return apiService.upload('/api/search/image_search/?user_id='+data.user_id,data.formData);
+ searchByImage: (data:{image_base64: string,user_id?:number | null}) => {
+ return apiService.post('/api/search/image_search/?user_id='+data.user_id,{
+ image_base64: data.image_base64
+ });
}
}
diff --git a/app/utils/languageUtils.ts b/app/utils/languageUtils.ts
index 9874aa0..486696a 100644
--- a/app/utils/languageUtils.ts
+++ b/app/utils/languageUtils.ts
@@ -3,6 +3,8 @@ import { getCurrentLanguage } from '../i18n';
export const getSubjectTransLanguage = >(data: T): string => {
// 获取当前i18n语言
const currentLang = getCurrentLanguage();
+ console.log('currentLang', currentLang);
+
// 特殊处理中文
if (currentLang === 'zh' && 'subject' in data) {
@@ -28,28 +30,28 @@ export const getSubjectTransLanguage = >(data: T):
-export const getSkuTransLanguage = >(data: T): string => {
- // 获取当前i18n语言
- const currentLang = getCurrentLanguage();
+// export const getSkuTransLanguage = >(data: T): string => {
+// // 获取当前i18n语言
+// const currentLang = getCurrentLanguage();
- // 特殊处理中文
- if (currentLang === 'zh' && 'value' in data) {
- return data.value as string;
- }
-
- // 获取所有subject_trans开头的字段
- const translationFields = Object.keys(data).filter(key =>
- key.startsWith('value_trans')
- );
-
- // 查找匹配的字段
- const matchedField = translationFields.find(field => {
- // 从字段名中提取语言代码
- const langCode = field.replace('value_trans_', '');
- // 如果没有后缀,则为法语
- return langCode === '' ? currentLang === 'fr' : langCode === currentLang;
- });
-
- // 返回匹配的翻译值,如果没有匹配则返回法语
- return (data[matchedField || 'value_trans'] as string) || '';
-};
+// // 特殊处理中文
+// if (currentLang === 'zh' && 'value' in data) {
+// return data.value as string;
+// }
+
+// // 获取所有subject_trans开头的字段
+// const translationFields = Object.keys(data).filter(key =>
+// key.startsWith('value_trans')
+// );
+
+// // 查找匹配的字段
+// const matchedField = translationFields.find(field => {
+// // 从字段名中提取语言代码
+// const langCode = field.replace('value_trans_', '');
+// // 如果没有后缀,则为法语
+// return langCode === '' ? currentLang === 'fr' : langCode === currentLang;
+// });
+
+// // 返回匹配的翻译值,如果没有匹配则返回法语
+// return (data[matchedField || 'value_trans'] as string) || '';
+// };
diff --git a/app/utils/storage.ts b/app/utils/storage.ts
new file mode 100644
index 0000000..46b9478
--- /dev/null
+++ b/app/utils/storage.ts
@@ -0,0 +1,42 @@
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import { STORAGE_KEYS } from '../constants/config';
+
+// 保存货币设置到本地存储
+export const saveCurrency = async (currency: string) => {
+ try {
+ await AsyncStorage.setItem(STORAGE_KEYS.CURRENCY, currency);
+ } catch (error) {
+ console.error('保存货币设置失败:', error);
+ }
+};
+
+// 从本地存储加载货币设置
+export const loadCurrency = async (): Promise => {
+ try {
+ const savedCurrency = await AsyncStorage.getItem(STORAGE_KEYS.CURRENCY);
+ return savedCurrency;
+ } catch (error) {
+ console.error('加载货币设置失败:', error);
+ return null;
+ }
+};
+
+// 保存语言设置到本地存储
+export const saveLanguage = async (language: string) => {
+ try {
+ await AsyncStorage.setItem(STORAGE_KEYS.LANGUAGE, language);
+ } catch (error) {
+ console.error('保存语言设置失败:', error);
+ }
+};
+
+// 从本地存储加载语言设置
+export const loadLanguage = async (): Promise => {
+ try {
+ const savedLanguage = await AsyncStorage.getItem(STORAGE_KEYS.LANGUAGE);
+ return savedLanguage;
+ } catch (error) {
+ console.error('加载语言设置失败:', error);
+ return null;
+ }
+};
\ No newline at end of file