Browse Source

首页无限滚动

main
unknown 3 weeks ago
parent
commit
5cf46eacd5
  1. 110
      app/screens/HomeScreen.tsx
  2. 97
      app/screens/RechargeScreen.tsx

110
app/screens/HomeScreen.tsx

@ -324,12 +324,17 @@ export const HomeScreen = () => {
const [searchParams, setSearchParams] = useState<ProductParams>({ const [searchParams, setSearchParams] = useState<ProductParams>({
keyword: "pen", keyword: "pen",
page: 1, page: 1,
page_size: 20, page_size: 10,
sort_order: "desc", sort_order: "desc",
sort_by: "default", sort_by: "default",
language: "en", language: "en",
}); });
const [products, setProducts] = useState<Product[]>([]); const [products, setProducts] = useState<Product[]>([]);
const [hasMore, setHasMore] = useState(true);
const [isLoadingMore, setIsLoadingMore] = useState(false);
const [totalProducts, setTotalProducts] = useState(0);
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
const [currentPage, setCurrentPage] = useState(1); // 添加当前页码状态
const flatListRef = useRef<FlatList>(null); const flatListRef = useRef<FlatList>(null);
const data = [ const data = [
{ {
@ -346,21 +351,62 @@ export const HomeScreen = () => {
}, },
]; ];
const [galleryUsed, setGalleryUsed] = useState(false); // 标记是否使用过相册 const [galleryUsed, setGalleryUsed] = useState(false); // 标记是否使用过相册
const getProductData = async () => { const [loadingPlaceholders, setLoadingPlaceholders] = useState(0); // 添加占位符数量状态
setLoading(true); // 开始加载,显示骨架屏 const getProductData = async (isLoadMore = false) => {
if (isLoadMore) {
setIsLoadingMore(true);
} else {
setLoading(true);
}
try { try {
const currentParams = { const currentParams = {
...searchParams, ...searchParams,
page: isLoadMore ? currentPage + 1 : 1,
...(userStore.user?.user_id ? { user_id: userStore.user.user_id } : {}), ...(userStore.user?.user_id ? { user_id: userStore.user.user_id } : {}),
}; };
const res = await productApi.getSearchProducts(currentParams); const res = await productApi.getSearchProducts(currentParams);
setProducts(res.products);
setTotalProducts(res.total || 0);
if (isLoadMore) {
setProducts(prev => [...prev, ...res.products]);
setCurrentPage(prev => prev + 1);
} else {
setProducts(res.products);
setCurrentPage(1);
}
const currentTotal = isLoadMore ? products.length + res.products.length : res.products.length;
setHasMore(currentTotal < (res.total || 0));
if (!isLoadMore && !initialLoadComplete) {
setInitialLoadComplete(true);
const remainingParams = {
...currentParams,
page: 2,
page_size: 30
};
const remainingRes = await productApi.getSearchProducts(remainingParams);
setProducts(prev => {
const newProducts = [...prev, ...remainingRes.products];
setHasMore(newProducts.length < (res.total || 0));
return newProducts;
});
setCurrentPage(2);
}
} catch (error) { } catch (error) {
console.error("Error fetching products:", error); console.error("Error fetching products:", error);
} finally { } finally {
setTimeout(() => { if (isLoadMore) {
setLoading(false); // 延迟结束加载状态,让骨架屏显示更平滑 setIsLoadingMore(false);
}, 300); setLoadingPlaceholders(0); // 清除占位符
} else {
setTimeout(() => {
setLoading(false);
}, 300);
}
} }
}; };
const handleProductPress = useCallback( const handleProductPress = useCallback(
@ -377,6 +423,9 @@ export const HomeScreen = () => {
); );
const onRefresh = useCallback(async () => { const onRefresh = useCallback(async () => {
setRefreshing(true); setRefreshing(true);
setInitialLoadComplete(false); // 重置初始加载标记
setCurrentPage(1); // 重置页码
setSearchParams(prev => ({ ...prev, page_size: 10 })); // 只重置每页数量
try { try {
await getProductData(); await getProductData();
} catch (error) { } catch (error) {
@ -700,6 +749,34 @@ export const HomeScreen = () => {
Alert.alert("已重置", "现在您可以使用相机功能了"); Alert.alert("已重置", "现在您可以使用相机功能了");
}, []); }, []);
// 修改加载更多函数
const loadMore = () => {
if (!hasMore || isLoadingMore) {
console.log('不加载更多:', { hasMore, isLoadingMore });
return;
}
console.log('开始加载更多, 当前页码:', currentPage);
setLoadingPlaceholders(10); // 设置10个占位符
getProductData(true);
};
// 修改滚动到底部处理函数
const handleEndReached = () => {
console.log('触发加载更多');
loadMore();
};
// 修改渲染函数
const renderItem = ({ item, index }: { item: Product; index: number }) => {
// 如果是占位符
if (index >= products.length && index < products.length + loadingPlaceholders) {
return <ProductSkeleton />;
}
return renderProductItem({ item });
};
// 渲染列表头部内容 // 渲染列表头部内容
const renderHeader = () => ( const renderHeader = () => (
<> <>
@ -884,28 +961,35 @@ export const HomeScreen = () => {
<View style={styles.safeAreaContent}> <View style={styles.safeAreaContent}>
<View style={styles.container}> <View style={styles.container}>
{loading ? ( {loading ? (
// 显示骨架屏
<View> <View>
{renderHeader()} {renderHeader()}
{renderSkeletonGrid()} {renderSkeletonGrid()}
</View> </View>
) : ( ) : (
// 显示正常内容
<FlatList <FlatList
ref={flatListRef} ref={flatListRef}
data={products} data={[...products, ...Array(loadingPlaceholders).fill(null)]}
numColumns={2} numColumns={2}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
columnWrapperStyle={styles.productCardGroup} columnWrapperStyle={styles.productCardGroup}
renderItem={renderProductItem} renderItem={renderItem}
keyExtractor={(item, index) => keyExtractor={(item, index) =>
item.offer_id?.toString() || index.toString() item?.offer_id?.toString() || `placeholder-${index}`
} }
contentContainerStyle={{ contentContainerStyle={{
paddingBottom: 15, paddingBottom: 15,
backgroundColor: "transparent", backgroundColor: "transparent",
}} }}
ListHeaderComponent={renderHeader} ListHeaderComponent={renderHeader}
onEndReached={handleEndReached}
onEndReachedThreshold={3}
ListFooterComponent={() => (
!hasMore && !loadingPlaceholders ? (
<View style={{ padding: 10, alignItems: 'center' }}>
<Text></Text>
</View>
) : null
)}
refreshControl={ refreshControl={
<RefreshControl <RefreshControl
refreshing={refreshing} refreshing={refreshing}
@ -1522,4 +1606,4 @@ const styles = StyleSheet.create<StylesType>({
fontSize: fontSize(16), fontSize: fontSize(16),
color: "#999", color: "#999",
}, },
}); });

97
app/screens/RechargeScreen.tsx

@ -210,103 +210,6 @@ const RechargeScreen = ({ onClose }: RechargeScreenProps) => {
handleCurrencyConversion(selectedPrice, currency); handleCurrencyConversion(selectedPrice, currency);
}; };
// 处理支付URL的函数
const openPaymentURL = useCallback((url: string) => {
console.log("Opening payment URL:", url);
// 判断运行平台
if (Platform.OS === 'web') {
try {
// Web平台首先尝试通过window.location跳转
// 保存当前URL作为回调地址,以便支付完成后返回
const currentUrl = window.location.href;
sessionStorage.setItem('payment_return_url', currentUrl);
// 尝试多种方式打开支付链接
// 方式1:直接修改当前窗口location
window.location.href = url;
// 方式2:如果直接跳转不生效,尝试打开新窗口
setTimeout(() => {
// 检查是否已经跳转
if (window.location.href === currentUrl) {
console.log("Direct navigation did not work, trying popup window...");
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
console.warn("Popup blocked or failed to open. Trying iframe method.");
// 方式3:尝试使用iframe
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe);
// 显示手动跳转提示
alert(`La page de paiement n'a pas pu s'ouvrir automatiquement. Veuillez cliquer sur OK pour essayer à nouveau.`);
window.location.href = url;
}
}
}, 1000);
} catch (error) {
console.error("Failed to open payment URL on web:", error);
// 最后尝试
try {
window.open(url, '_self');
} catch (e) {
console.error("All payment URL opening methods failed:", e);
alert(`Impossible d'ouvrir la page de paiement. URL: ${url}`);
}
}
} else {
// 移动平台使用Linking打开
Linking.canOpenURL(url).then(supported => {
if (supported) {
Linking.openURL(url).catch(err => {
console.error("Error opening URL with Linking:", err);
// 尝试使用WebView组件导航
if (navigationRef.current) {
navigationRef.current.navigate('Pay', { payUrl: url });
} else {
Alert.alert(
"Erreur",
"Impossible d'ouvrir la page de paiement. Veuillez réessayer.",
[
{
text: "Réessayer",
onPress: () => Linking.openURL(url)
},
{ text: "Annuler" }
]
);
}
});
} else {
console.error("Cannot open URL: " + url);
Alert.alert(
"Erreur",
"Cette URL ne peut pas être ouverte. Veuillez contacter le support technique.",
[
{
text: "Copier l'URL",
onPress: () => {
Clipboard.setString(url);
Alert.alert("Info", "URL copiée dans le presse-papiers");
}
},
{ text: "Fermer" }
]
);
}
}).catch(err => {
console.error("Couldn't check if URL can be opened:", err);
Alert.alert("Erreur", "Impossible de vérifier si l'URL peut être ouverte");
});
}
}, []);
// 更新处理支付提交的函数 // 更新处理支付提交的函数
const handlePaySubmit = async () => { const handlePaySubmit = async () => {
if (!paymentParams) { if (!paymentParams) {

Loading…
Cancel
Save