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: "#FF3366" }, // Neon Pink B: { title: "欧皇", color: "#FFD700" }, // Gold C: { title: "隐藏", color: "#00E5FF" }, // Cyan D: { title: "普通", color: "#B0BEC5" }, // Grey SUBSTITUTE: { title: "置换款", color: "#B0BEC5" }, OTHER: { title: "其他", color: "#B0BEC5" }, }; 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) => { // @ts-ignore 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: "/cloud-warehouse/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 }, });