import { Image } from 'expo-image'; import { useRouter } from 'expo-router'; import React, { useCallback, useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, ImageBackground, Platform, RefreshControl, ScrollView, StatusBar, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Images } from '@/constants/images'; import { getStore, getTakeList, moveOutSafeStore, moveToSafeStore, } from '@/services/award'; import CheckoutModal from './components/CheckoutModal'; const LEVEL_MAP: Record = { A: { title: '超神', color: '#ffae00' }, B: { title: '欧皇', color: '#ff0000' }, C: { title: '隐藏', color: '#9745e6' }, D: { title: '普通', color: '#666666' }, }; const LEVEL_TABS = [ { title: '全部', value: '' }, { title: '普通', value: 'D' }, { title: '隐藏', value: 'C' }, { title: '欧皇', value: 'B' }, { title: '超神', value: 'A' }, ]; const FROM_TYPE_MAP: Record = { LUCK: '奖池', MALL: '商城', LUCK_ROOM: '福利房', LUCK_WHEEL: '魔天轮', DOLL_MACHINE: '扭蛋', ACTIVITY: '活动', SUBSTITUTE: '置换', TRANSFER: '转赠', }; interface StoreItem { id: string; level: string; safeFlag: number; magicAmount?: number; fromRelationType: string; spu: { id: string; name: string; cover: string }; } interface PickupItem { tradeNo: string; createTime: string; status: number; contactName: string; contactNo: string; province: string; city: string; district: string; address: string; expressAmount: number; paymentTime?: string; paymentTimeoutTime?: string; cancelRemark?: string; itemList: Array<{ id: string; spuId: string; level: string; cover: string }>; } const STATUS_MAP: Record = { 0: { text: '待支付运费', color: '#ff6b00' }, 1: { text: '已进仓库进行配货', color: '#ff6b00' }, 2: { text: '待收货', color: '#ff6b00' }, 10: { text: '已取消', color: '#ff6b00' }, 11: { text: '超时取消', color: '#ff6b00' }, 12: { text: '系统取消', color: '#ff6b00' }, 99: { text: '已完成', color: '#52c41a' }, }; export default function StoreScreen() { const router = useRouter(); const insets = useSafeAreaInsets(); const [mainTabIndex, setMainTabIndex] = useState(0); const [levelTabIndex, setLevelTabIndex] = useState(0); const [list, setList] = useState([]); const [loading, setLoading] = useState(false); const [refreshing, setRefreshing] = useState(false); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [checkMap, setCheckMap] = useState>({}); const [checkoutVisible, setCheckoutVisible] = useState(false); const mainTabs = ['未使用', '保险柜', '已提货']; const loadData = useCallback(async (pageNum: number, isRefresh = false) => { if (loading && !isRefresh) return; if (!hasMore && pageNum > 1 && !isRefresh) return; try { if (pageNum === 1) setLoading(true); let res: any; if (mainTabIndex === 0) { res = await getStore(pageNum, 20, 0, LEVEL_TABS[levelTabIndex].value); } else if (mainTabIndex === 1) { res = await getStore(pageNum, 20, 1); } else { res = await getTakeList(pageNum, 20); } let records = Array.isArray(res) ? res : (res?.records || res || []); // 处理已提货数据,合并相同商品 if (mainTabIndex === 2 && records.length > 0) { records = records.map((item: PickupItem) => { const goodsMap: Record = {}; (item.itemList || []).forEach((goods: any) => { const key = `${goods.spuId}_${goods.level}`; if (goodsMap[key]) { goodsMap[key].total += 1; } else { goodsMap[key] = { total: 1, data: goods }; } }); return { ...item, groupedList: Object.values(goodsMap) }; }); } if (records.length < 20) setHasMore(false); if (pageNum === 1 || isRefresh) setList(records); else setList(prev => [...prev, ...records]); } catch (e) { console.error('加载仓库数据失败:', e); } finally { setLoading(false); setRefreshing(false); } }, [mainTabIndex, levelTabIndex, loading, hasMore]); useEffect(() => { setPage(1); setList([]); setHasMore(true); setCheckMap({}); loadData(1, true); }, [mainTabIndex]); useEffect(() => { if (mainTabIndex === 0) { setPage(1); setList([]); setHasMore(true); setCheckMap({}); loadData(1, true); } }, [levelTabIndex]); const handleRefresh = () => { setRefreshing(true); setPage(1); setHasMore(true); loadData(1, true); }; const handleLoadMore = () => { if (!loading && hasMore) { const np = page + 1; setPage(np); loadData(np); } }; const handleChoose = (item: StoreItem) => { if (item.safeFlag === 1 && mainTabIndex === 0) return; setCheckMap(prev => { const newMap = { ...prev }; if (newMap[item.id]) delete newMap[item.id]; else newMap[item.id] = item; return newMap; }); }; const handleLock = async (item: StoreItem, index: number) => { const res = await moveToSafeStore([item.id]); if (res) { const newList = [...list]; newList[index] = { ...item, safeFlag: 1 }; setList(newList); setCheckMap(prev => { const m = { ...prev }; delete m[item.id]; return m; }); showAlert('已锁定到保险柜'); } }; const handleUnlock = async (item: StoreItem, index: number) => { const res = await moveOutSafeStore([item.id]); if (res) { if (mainTabIndex === 1) setList(list.filter((_, i) => i !== index)); else { const newList = [...list]; newList[index] = { ...item, safeFlag: 0 }; setList(newList); } showAlert('已从保险柜移出'); } }; const handleMoveOutAll = async () => { const selected = Object.values(checkMap); if (selected.length === 0) { showAlert('请至少选择一个商品!'); return; } const res = await moveOutSafeStore(selected.map(i => i.id)); if (res) { setCheckMap({}); handleRefresh(); showAlert('已从保险柜移出'); } }; const handleTakeGoods = () => { const selected = Object.values(checkMap); if (selected.length === 0) { showAlert('请至少选择一个商品!'); return; } setCheckoutVisible(true); }; const handleCheckoutSuccess = () => { setCheckoutVisible(false); setCheckMap({}); handleRefresh(); }; const showAlert = (msg: string) => { if (Platform.OS === 'web') window.alert(msg); else Alert.alert('提示', msg); }; const renderStoreItem = ({ item, index }: { item: StoreItem; index: number }) => { const levelInfo = LEVEL_MAP[item.level] || LEVEL_MAP.D; const isChecked = !!checkMap[item.id]; const canSelect = mainTabIndex === 1 || item.safeFlag !== 1; return ( canSelect && handleChoose(item)}> {canSelect && ( {isChecked && } )} {levelInfo.title} item.safeFlag !== 1 ? handleLock(item, index) : handleUnlock(item, index)}> {item.safeFlag !== 1 ? '锁定' : '解锁'} {item.spu?.name} 从{FROM_TYPE_MAP[item.fromRelationType] || '其他'}获得 ); }; const copyToClipboard = (text: string) => { showAlert(`订单号已复制: ${text}`); }; const showExpress = (item: PickupItem) => { router.push({ pathname: '/store/packages' as any, params: { tradeNo: item.tradeNo } }); }; const renderPickupItem = ({ item }: { item: PickupItem & { groupedList?: Array<{ total: number; data: any }> } }) => { const statusInfo = STATUS_MAP[item.status] || { text: '未知', color: '#999' }; return ( {/* 顶部信息 */} 下单时间:{item.createTime} {statusInfo.text} {item.status === 0 && item.paymentTimeoutTime && ( {item.paymentTimeoutTime} 将自动取消该订单,如有优惠券,将自动退回 )} {/* 收货地址 */} 📍 {item.contactName},{item.contactNo} {item.province}{item.city}{item.district}{item.address} {/* 商品列表 */} {(item.groupedList || []).map((goods, idx) => ( x{goods.total} ))} {/* 订单号 */} 订单号: {item.tradeNo} copyToClipboard(item.tradeNo)}> 复制 {item.paymentTime && ( 付款时间: {item.paymentTime} )} {item.status === 12 && item.cancelRemark && ( 备注 {item.cancelRemark} )} {/* 底部操作 */} 配送费:¥{item.expressAmount} {[1, 2, 99].includes(item.status) && ( showExpress(item)}> 物流信息 )} ); }; const selectedCount = Object.keys(checkMap).length; return ( router.back()}> 仓库 {mainTabs.map((tab, index) => ( setMainTabIndex(index)}> {tab} {mainTabIndex === index && } ))} {mainTabIndex === 0 && ( {LEVEL_TABS.map((tab, index) => ( setLevelTabIndex(index)}> {tab.title} ))} )} item.id || item.tradeNo || index.toString()} contentContainerStyle={styles.listContent} refreshControl={} onEndReached={handleLoadMore} onEndReachedThreshold={0.3} ListHeaderComponent={mainTabIndex === 2 ? ( ⚠️ 您的包裹一般在5个工作日内发货,如遇特殊情况可能会有延迟,敬请谅解~ ) : null} ListFooterComponent={loading && list.length > 0 ? : null} ListEmptyComponent={!loading ? 暂无物品 : null} /> {mainTabIndex !== 2 && list.length > 0 && ( 已选 {selectedCount} 件商品 {mainTabIndex === 0 ? '立即提货' : '移出保险柜'} )} {/* 提货弹窗 */} setCheckoutVisible(false)} onSuccess={handleCheckoutSuccess} /> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#1a1a2e' }, background: { flex: 1 }, headerBg: { position: 'absolute', top: 0, left: 0, width: '100%', height: 160 }, header: { position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 10, paddingBottom: 10 }, backBtn: { width: 40, height: 40, justifyContent: 'center', alignItems: 'center' }, backIcon: { fontSize: 32, color: '#fff', fontWeight: 'bold' }, title: { color: '#fff', fontSize: 16, fontWeight: 'bold' }, placeholder: { width: 40 }, content: { flex: 1 }, mainTabs: { flexDirection: 'row', justifyContent: 'space-around', paddingVertical: 10 }, mainTabItem: { alignItems: 'center', paddingHorizontal: 15 }, mainTabText: { color: '#aaa', fontSize: 14 }, mainTabTextActive: { color: '#fff', fontWeight: 'bold', fontSize: 16 }, mainTabLine: { width: 20, height: 3, backgroundColor: '#fff', marginTop: 5, borderRadius: 2 }, levelTabs: { flexDirection: 'row', paddingHorizontal: 10, paddingVertical: 8 }, levelTabItem: { paddingHorizontal: 12, paddingVertical: 6, marginRight: 8, borderRadius: 15, backgroundColor: 'rgba(255,255,255,0.1)' }, levelTabItemActive: { backgroundColor: '#FC7D2E' }, levelTabText: { color: '#aaa', fontSize: 12 }, levelTabTextActive: { color: '#fff' }, listContent: { paddingHorizontal: 10, paddingBottom: 150 }, cell: { width: '100%', minHeight: 154, marginBottom: 10, padding: 15 }, cellHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.1)', paddingBottom: 10, marginBottom: 10 }, headerLeft: { flexDirection: 'row', alignItems: 'center' }, checkBox: { width: 18, height: 18, borderWidth: 2, borderColor: '#000', backgroundColor: '#fff', marginRight: 10, justifyContent: 'center', alignItems: 'center' }, checkBoxChecked: { backgroundColor: '#000' }, checkIcon: { color: '#fff', fontSize: 12 }, levelTitle: { fontSize: 16, fontWeight: 'bold' }, lockBox: { flexDirection: 'row', alignItems: 'center' }, lockText: { fontSize: 12, color: '#666' }, lockIcon: { width: 16, height: 16, marginLeft: 5 }, cellBody: { flexDirection: 'row' }, goodsImgBg: { width: 65, height: 65, justifyContent: 'center', alignItems: 'center', marginRight: 10 }, goodsImg: { width: 55, height: 55 }, goodsInfo: { flex: 1, justifyContent: 'space-between' }, goodsName: { fontSize: 14, color: '#333', fontWeight: 'bold' }, goodsSource: { fontSize: 12, color: '#999' }, bottomBar: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: 'rgba(0,0,0,0.8)', paddingHorizontal: 15, paddingTop: 10, alignItems: 'center' }, bottomInfoText: { color: '#fff', fontSize: 14, marginBottom: 10 }, bottomInfoCount: { fontWeight: 'bold', fontSize: 18 }, bottomBtn: { width: 260 }, bottomBtnBg: { width: 260, height: 60, justifyContent: 'center', alignItems: 'center' }, bottomBtnText: { color: '#000', fontSize: 16, fontWeight: 'bold' }, emptyBox: { marginTop: 100, alignItems: 'center' }, emptyText: { color: '#999', fontSize: 14 }, // 已提货样式 pickupTip: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#1FA4FF', padding: 8, marginBottom: 10, borderRadius: 4 }, pickupTipIcon: { fontSize: 14, marginRight: 6 }, pickupTipText: { flex: 1, color: '#fff', fontSize: 12 }, pickupCell: { width: '100%', marginBottom: 10, padding: 15 }, pickupTop: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.05)', paddingBottom: 10 }, pickupTime: { fontSize: 12, color: '#666' }, pickupStatus: { fontSize: 12, fontWeight: 'bold' }, pickupTimeout: { fontSize: 11, color: '#ff6b00', marginTop: 5 }, pickupAddress: { flexDirection: 'row', alignItems: 'flex-start', paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.05)' }, locationIcon: { fontSize: 16, marginRight: 10 }, addressInfo: { flex: 1 }, addressName: { fontSize: 14, color: '#333', fontWeight: 'bold' }, addressDetail: { fontSize: 12, color: '#666', marginTop: 4 }, pickupGoodsBox: { backgroundColor: '#f8f8f8', borderRadius: 6, padding: 10, marginVertical: 10 }, pickupGoodsList: { flexDirection: 'row' }, pickupGoodsItem: { width: 79, height: 103, backgroundColor: '#fff', borderRadius: 6, marginRight: 8, alignItems: 'center', justifyContent: 'center', position: 'relative', borderWidth: 1, borderColor: '#eaeaea' }, pickupGoodsImg: { width: 73, height: 85 }, pickupGoodsCount: { position: 'absolute', top: 0, right: 0, backgroundColor: '#ff6b00', borderRadius: 2, paddingHorizontal: 4, paddingVertical: 2 }, pickupGoodsCountText: { color: '#fff', fontSize: 10, fontWeight: 'bold' }, pickupOrderRow: { flexDirection: 'row', alignItems: 'center', borderTopWidth: 1, borderTopColor: 'rgba(0,0,0,0.05)', paddingTop: 14 }, pickupOrderLabel: { fontSize: 12, color: '#666' }, pickupOrderNo: { flex: 1, fontSize: 12, color: '#333', textAlign: 'right' }, copyBtn: { backgroundColor: '#1FA4FF', borderRadius: 4, paddingHorizontal: 6, paddingVertical: 4, marginLeft: 5 }, copyBtnText: { color: '#fff', fontSize: 12 }, pickupInfoRow: { flexDirection: 'row', alignItems: 'center', paddingTop: 10 }, pickupInfoLabel: { fontSize: 12, color: '#666' }, pickupInfoValue: { fontSize: 12, color: '#333' }, pickupBottom: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end', paddingTop: 10 }, pickupExpressAmount: { fontSize: 12, color: '#333' }, priceText: { color: '#ff6b00' }, expressBtn: { backgroundColor: '#1FA4FF', borderRadius: 12, paddingHorizontal: 10, paddingVertical: 6, marginLeft: 15 }, expressBtnText: { color: '#fff', fontSize: 12 }, });