import { Image } from 'expo-image'; import { useRouter } from 'expo-router'; import React, { useCallback, useEffect, useState } from 'react'; import { ActivityIndicator, Alert, FlatList, ImageBackground, Platform, Pressable, 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: '#ff0000' }, // 红色 B: { title: '欧皇', color: '#ffae00' }, // 黄色 C: { title: '隐藏', color: '#9745e6' }, D: { title: '普通', color: '#666666' }, SUBSTITUTE: { title: '置换款', color: '#666666' }, OTHER: { title: '其他', color: '#666666' }, }; const LEVEL_TABS = [ { title: '全部', value: '' }, { title: '普通', value: 'D' }, { title: '隐藏', value: 'C' }, { title: '欧皇', value: 'B' }, { title: '超神', value: 'A' }, { title: '其他', value: 'OTHER' }, ]; const FROM_TYPE_MAP: Record = { LUCK: '奖池', MALL: '商城', LUCK_ROOM: '福利房', LUCK_WHEEL: '魔天轮', DOLL_MACHINE: '扭蛋', ACTIVITY: '活动', SUBSTITUTE: '商品置换', TRANSFER: '商品转赠', DISTRIBUTION: '分销', LUCK_PICKUP: '商品提货', LUCK_EXCHANGE: '商品兑换', RECHARGE: '充值', WITHDRAW: '提现', OFFICIAL: '官方', LUCK_ACTIVITY: '奖池活动', CONSUMPTION_ACTIVITY: '消费活动', NEW_USER_RANK_ACTIVITY: '拉新排名活动', CONSUMPTION_RANK_ACTIVITY: '消费排行榜活动', WHEEL_ACTIVITY: '大转盘活动', TA_ACTIVITY: '勇者之塔活动', ISLAND_ACTIVITY: '海岛活动', REDEEM_CODE_ACTIVITY: '兑换码活动', }; 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; }); } }; 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); } } }; 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(); } }; const handleTakeGoods = () => { const selected = Object.values(checkMap); if (selected.length === 0) { showAlert('请至少选择一个商品!'); return; } setCheckoutVisible(true); }; const handleSelectAll = () => { const allSelected = list.every(item => checkMap[item.id]); if (allSelected) { setCheckMap({}); } else { const newMap: Record = {}; list.forEach(item => { newMap[item.id] = item; }); setCheckMap(newMap); } }; 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 ( { console.log('[仓库store] 点击商品详情, id:', item.id); router.push({ pathname: '/store/detail', params: { id: item.id } } as any); }}> 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) => { const isActive = mainTabIndex === index; // Use Yellow L bg for active, Grey (Hui) for inactive const bg = isActive ? Images.common.butBgL : Images.common.butBgHui; return ( setMainTabIndex(index)}> {tab} ); })} {mainTabIndex === 0 && ( {LEVEL_TABS.map((tab, index) => { const isActive = levelTabIndex === index; return ( setLevelTabIndex(index)} > {isActive && } {tab.title} {isActive && } ); })} )} 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 && ( {mainTabIndex === 1 ? ( {list.length > 0 && list.every(item => checkMap[item.id]) ? '取消全选' : '全选'} 移出保险柜 ) : ( 立即提货 )} 已选 {selectedCount} 件商品 )} {/* 提货弹窗 */} 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-between', paddingHorizontal: 12, // Reduced from 15 to match everything else paddingBottom: 2 }, mainTabItem: { width: '30%', height: 44, // Slightly taller justifyContent: 'center', alignItems: 'center' }, mainTabBg: { width: '100%', height: '100%', justifyContent: 'center', alignItems: 'center' }, mainTabText: { fontSize: 15, color: '#333', fontWeight: 'bold' }, mainTabTextActive: { fontSize: 16, color: '#000', fontWeight: 'bold' }, mainTabLine: { display: 'none' }, levelTabs: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 10, // Add some padding back for the text content since container is full width paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: 'rgba(255,255,255,0.15)' }, levelTabItem: { marginRight: 25, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 6, paddingVertical: 2, position: 'relative', minWidth: 40 }, levelTabItemActive: { backgroundColor: 'transparent' }, levelTabText: { color: '#666', fontSize: 15, fontWeight: 'bold' }, levelTabTextActive: { color: '#ff6b00', fontSize: 17, fontWeight: '900', textShadowColor: 'rgba(0, 0, 0, 0.3)', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1 }, // Corner Decorations - Larger and jagged simulation decorTL: { position: 'absolute', top: 0, left: -4, width: 0, height: 0, borderTopWidth: 8, borderRightWidth: 8, borderTopColor: '#ff6b00', borderRightColor: 'transparent', }, decorBR: { position: 'absolute', bottom: 0, right: -4, width: 0, height: 0, borderBottomWidth: 8, borderLeftWidth: 8, borderBottomColor: '#ff6b00', borderLeftColor: 'transparent', }, levelInd: { display: 'none' }, listContent: { paddingHorizontal: 8, paddingVertical: 10, paddingBottom: 150, }, cell: { marginBottom: 0, width: '100%', minHeight: 154, // 原项目 308rpx }, cellContent: { paddingTop: 15, paddingBottom: 15, paddingLeft: 18, paddingRight: 18, // 原项目 36rpx }, cellHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10, paddingBottom: 10, borderBottomWidth: 1, borderBottomColor: 'rgba(0,0,0,0.15)', }, headerLeft: { flexDirection: 'row', alignItems: 'center' }, checkBox: { width: 16, height: 16, borderWidth: 2, borderColor: '#000', marginRight: 8, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fff' }, checkBoxChecked: { backgroundColor: '#000' }, checkIcon: { color: '#fff', fontSize: 10, fontWeight: 'bold' }, levelTitle: { fontSize: 16, fontWeight: 'bold', textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 0 }, lockBox: { flexDirection: 'row', alignItems: 'center' }, lockText: { fontSize: 12, color: '#666', marginRight: 4 }, lockIcon: { width: 16, height: 16 }, cellBody: { flexDirection: 'row', alignItems: 'center', }, goodsImgBg: { width: 65, height: 65, justifyContent: 'center', alignItems: 'center', marginRight: 12, padding: 7 }, goodsImg: { width: '100%', height: '100%' }, goodsInfo: { flex: 1, justifyContent: 'center', paddingRight: 8 }, goodsName: { fontSize: 15, color: '#333', fontWeight: 'bold', marginBottom: 6 }, goodsDesc: { fontSize: 12, color: '#999' }, arrowIcon: { fontSize: 18, color: '#ccc', marginLeft: 8 }, bottomBar: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 100, // Taller for Top Button / Bottom Text layout paddingBottom: 20, alignItems: 'center', justifyContent: 'center', backgroundColor: 'transparent' // Screenshot shows transparent or gradient? }, bottomBtn: { width: '80%', height: 45, marginBottom: 5 }, buttonRow: { flexDirection: 'row', justifyContent: 'center', width: '100%', paddingHorizontal: 20, marginBottom: 5 }, actionBtn: { height: 45, borderRadius: 22, justifyContent: 'center', alignItems: 'center' }, selectAllBtn: { width: '30%', backgroundColor: '#fff', marginRight: 10, borderWidth: 1, borderColor: '#ccc' }, removeBtn: { width: '65%' }, btnBg: { width: '100%', height: '100%', justifyContent: 'center', alignItems: 'center' }, selectAllText: { fontSize: 16, fontWeight: 'bold', color: '#333' }, removeText: { fontSize: 16, fontWeight: 'bold', color: '#000' }, bottomBtnSecondary: { display: 'none' }, // Removed bottomBtnSecondaryText: { display: 'none' }, // Removed bottomBtnBg: { width: '100%', height: '100%', justifyContent: 'center', alignItems: 'center' }, bottomBtnText: { color: '#000', fontSize: 16, fontWeight: 'bold' }, bottomInfoText: { color: '#333', fontSize: 12 }, // Text below button bottomInfoCount: { fontWeight: 'bold' }, emptyBox: { marginTop: 100, alignItems: 'center' }, emptyText: { color: '#999', fontSize: 14 }, pickupCell: { width: '100%', marginBottom: 10, padding: 12 }, pickupTop: { flexDirection: 'row', justifyContent: 'space-between', paddingBottom: 8, borderBottomWidth: 1, borderBottomColor: '#eee' }, pickupTime: { fontSize: 12, color: '#999' }, pickupStatus: { fontSize: 12, fontWeight: 'bold' }, pickupTimeout: { fontSize: 11, color: '#ff6b00', marginTop: 4 }, pickupAddress: { flexDirection: 'row', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }, locationIcon: { fontSize: 16, marginRight: 8 }, addressInfo: { flex: 1 }, addressName: { fontSize: 14, fontWeight: 'bold', color: '#333' }, addressDetail: { fontSize: 12, color: '#666', marginTop: 4 }, pickupGoodsBox: { paddingVertical: 10 }, pickupGoodsList: { flexDirection: 'row' }, pickupGoodsItem: { marginRight: 10, alignItems: 'center' }, pickupGoodsImg: { width: 60, height: 60, borderRadius: 4 }, pickupGoodsCount: { position: 'absolute', right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)', paddingHorizontal: 4, borderRadius: 4 }, pickupGoodsCountText: { color: '#fff', fontSize: 10 }, pickupOrderRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 8 }, pickupOrderLabel: { fontSize: 12, color: '#666' }, pickupOrderNo: { flex: 1, fontSize: 12, color: '#333' }, copyBtn: { paddingHorizontal: 8, paddingVertical: 4, backgroundColor: '#f5f5f5', borderRadius: 4 }, copyBtnText: { fontSize: 12, color: '#666' }, pickupInfoRow: { flexDirection: 'row', paddingVertical: 4 }, pickupInfoLabel: { fontSize: 12, color: '#666' }, pickupInfoValue: { fontSize: 12, color: '#333' }, pickupBottom: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: 10 }, pickupExpressAmount: { fontSize: 12, color: '#333' }, priceText: { color: '#ff6b00', fontWeight: 'bold' }, expressBtn: { paddingHorizontal: 12, paddingVertical: 6, backgroundColor: '#fec433', borderRadius: 4 }, expressBtnText: { fontSize: 12, color: '#000', fontWeight: 'bold' }, pickupTip: { flexDirection: 'row', alignItems: 'center', padding: 10, backgroundColor: 'rgba(255,235,200,0.8)', marginHorizontal: 8, borderRadius: 6, marginBottom: 10 }, pickupTipIcon: { fontSize: 14, marginRight: 6 }, pickupTipText: { flex: 1, fontSize: 11, color: '#ff6b00' }, goodsSource: { fontSize: 12, color: '#666', opacity: 0.8 }, arrow: { fontSize: 18, color: '#fec433', marginLeft: 8 }, });