import { Image } from 'expo-image';
import Alipay from 'expo-native-alipay';
import { useRouter } from 'expo-router';
import React, { useEffect, useState } from 'react';
import {
ActivityIndicator,
Alert,
ImageBackground,
Modal,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Images } from '@/constants/images';
import { Address, getDefaultAddress } from '@/services/address';
import { takeApply, takePreview } from '@/services/award';
interface GroupedGoods {
total: number;
data: { id: string; cover: string; spuId: string; level: string; name?: string };
}
interface CheckoutModalProps {
visible: boolean;
selectedItems: Array<{ id: string; spu: { id: string; name: string; cover: string }; level: string }>;
onClose: () => void;
onSuccess: () => void;
}
export default function CheckoutModal({ visible, selectedItems, onClose, onSuccess }: CheckoutModalProps) {
const router = useRouter();
const insets = useSafeAreaInsets();
const [loading, setLoading] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [address, setAddress] = useState
(null);
const [expressAmount, setExpressAmount] = useState(0);
const [goodsList, setGoodsList] = useState([]);
const showAlert = (msg: string) => {
if (Platform.OS === 'web') window.alert(msg);
else Alert.alert('提示', msg);
};
useEffect(() => {
if (visible && selectedItems.length > 0) {
loadData();
}
}, [visible, selectedItems]);
const loadData = async () => {
setLoading(true);
try {
// 获取默认地址
const addr = await getDefaultAddress();
setAddress(addr);
// 获取提货预览
const ids = selectedItems.map(item => item.id);
const res = await takePreview(ids, addr?.id || '');
if (res) {
setExpressAmount(res.expressAmount || 0);
}
// 合并相同商品
const goodsMap: Record = {};
selectedItems.forEach((item) => {
const key = `${item.spu.id}_${item.level}`;
if (goodsMap[key]) {
goodsMap[key].total += 1;
} else {
goodsMap[key] = {
total: 1,
data: {
id: item.id,
cover: item.spu.cover,
spuId: item.spu.id,
level: item.level,
name: item.spu.name,
},
};
}
});
setGoodsList(Object.values(goodsMap));
} catch (e) {
console.error('加载提货信息失败:', e);
}
setLoading(false);
};
const goToAddress = () => {
onClose();
router.push('/address?type=1' as any);
};
/*
* Handle Submit with Payment Choice
*/
const handleSubmit = async () => {
if (!address) {
showAlert('请选择收货地址');
return;
}
if (expressAmount > 0) {
Alert.alert(
'支付运费',
`需支付运费 ¥${expressAmount}`,
[
{ text: '取消', style: 'cancel' },
{ text: '钱包支付', onPress: () => processTakeApply('WALLET') },
{ text: '支付宝支付', onPress: () => processTakeApply('ALIPAY_APP') }
]
);
} else {
processTakeApply('WALLET');
}
};
const processTakeApply = async (paymentType: string) => {
if (submitting) return;
setSubmitting(true);
try {
const ids = selectedItems.map(item => item.id);
const res: any = await takeApply(ids, address!.id, paymentType);
console.log('Take Apply Res:', res, paymentType);
if (paymentType === 'ALIPAY_APP' && res?.payInfo) {
Alipay.setAlipayScheme('alipay2021005175632205');
const result = await Alipay.pay(res.payInfo);
console.log('Alipay Result:', result);
if (result?.resultStatus === '9000') {
showAlert('提货成功');
onSuccess();
} else {
showAlert('支付未完成');
}
} else if (res) {
// Wallet payment or free success
showAlert('提货成功');
onSuccess();
}
} catch (e) {
console.error('提货失败:', e);
// Usually axios interceptor handles error alerts, but just in case
// showAlert('提货失败');
}
setSubmitting(false);
};
return (
{/* 标题 */}
提货
×
{loading ? (
) : (
<>
{/* 商品列表 */}
{goodsList.map((goods, idx) => (
x{goods.total}
))}
{/* 运费 */}
{expressAmount > 0 && (
运费
¥{expressAmount}
)}
{/* 收货地址 */}
{!address ? (
请填写收货地址
) : (
{address.contactName} {address.contactNo}
{address.province}{address.city}{address.district}{address.address}
)}
›
{/* 提交按钮 */}
{submitting ? '提交中...' : '确定发货'}
>
)}
);
}
const styles = StyleSheet.create({
overlay: { flex: 1, justifyContent: 'flex-end' },
overlayBg: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' },
container: { backgroundColor: '#fff', borderTopLeftRadius: 15, borderTopRightRadius: 15, paddingHorizontal: 14 },
header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 20, position: 'relative' },
title: { fontSize: 16, fontWeight: 'bold', color: '#000' },
closeBtn: { position: 'absolute', right: 0, top: 15, width: 24, height: 24, backgroundColor: '#ebebeb', borderRadius: 12, justifyContent: 'center', alignItems: 'center' },
closeBtnText: { fontSize: 18, color: '#a2a2a2', lineHeight: 20 },
loadingBox: { height: 200, justifyContent: 'center', alignItems: 'center' },
goodsSection: { paddingVertical: 10 },
goodsItem: { width: 79, height: 103, backgroundColor: '#fff', borderRadius: 6, marginRight: 8, alignItems: 'center', justifyContent: 'center', position: 'relative', borderWidth: 1, borderColor: '#eaeaea' },
goodsImg: { width: 73, height: 85 },
goodsCount: { position: 'absolute', top: 0, right: 0, backgroundColor: '#ff6b00', borderRadius: 2, paddingHorizontal: 4, paddingVertical: 2 },
goodsCountText: { color: '#fff', fontSize: 10, fontWeight: 'bold' },
feeRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 8 },
feeLabel: { fontSize: 14, color: '#333' },
feeValue: { fontSize: 14, color: '#ff6b00', fontWeight: 'bold' },
addressSection: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, borderTopWidth: 1, borderTopColor: '#f0f0f0' },
noAddress: { flex: 1, fontSize: 16, fontWeight: 'bold', color: '#333' },
addressInfo: { flex: 1 },
addressName: { fontSize: 14, color: '#333', fontWeight: 'bold' },
addressDetail: { fontSize: 12, color: '#666', marginTop: 4 },
arrowIcon: { fontSize: 20, color: '#999', marginLeft: 10 },
submitBtn: { alignItems: 'center', marginTop: 15 },
submitBtnBg: { width: 260, height: 60, justifyContent: 'center', alignItems: 'center' },
submitBtnText: { color: '#000', fontSize: 16, fontWeight: 'bold' },
});