| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- import { Image } from 'expo-image';
- import React, { forwardRef, useImperativeHandle, useState } from 'react';
- import { Modal, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
- import { Images } from '@/constants/images';
- interface BoxItem {
- boxNumber: number;
- leftQuantity: number;
- quantity: number;
- isCompleted: boolean;
- }
- interface BoxPopupProps {
- onSelect: (item: BoxItem) => void;
- }
- export interface BoxPopupRef {
- open: (list: BoxItem[]) => void;
- close: () => void;
- }
- export const BoxPopup = forwardRef<BoxPopupRef, BoxPopupProps>(({ onSelect }, ref) => {
- const [visible, setVisible] = useState(false);
- const [list, setList] = useState<BoxItem[]>([]);
- useImperativeHandle(ref, () => ({
- open: (data: BoxItem[]) => {
- setList(data);
- setVisible(true);
- },
- close: () => setVisible(false),
- }));
- const handleSelect = (item: BoxItem) => {
- onSelect(item);
- setVisible(false);
- };
- return (
- <Modal visible={visible} transparent animationType="slide" onRequestClose={() => setVisible(false)}>
- <View style={styles.overlay}>
- <View style={styles.container}>
- {/* 标题区域 */}
- <View style={styles.titleSection}>
- <View style={styles.titleBg}>
- <Text style={styles.titleText}>选择盒子</Text>
- </View>
- <TouchableOpacity style={styles.closeBtn} onPress={() => setVisible(false)}>
- <Text style={styles.closeBtnText}>×</Text>
- </TouchableOpacity>
- </View>
- {/* 盒子列表 */}
- <View style={styles.content}>
- <ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
- <View style={styles.grid}>
- {list.map((item, index) => (
- <TouchableOpacity key={index} style={styles.item} onPress={() => handleSelect(item)}>
- <View style={styles.imgBox}>
- <Image
- source={{ uri: item.isCompleted ? Images.box.detail.packagingBox2 : Images.box.detail.packagingBox1 }}
- style={styles.boxImg}
- contentFit="contain"
- />
- </View>
- <View style={styles.numBadge}>
- <Text style={styles.numText}>{item.boxNumber}箱</Text>
- </View>
- <Text style={styles.remaining}>
- {item.leftQuantity}/{item.quantity}
- </Text>
- </TouchableOpacity>
- ))}
- </View>
- </ScrollView>
- </View>
- </View>
- </View>
- </Modal>
- );
- });
- const styles = StyleSheet.create({
- overlay: {
- flex: 1,
- backgroundColor: 'rgba(0,0,0,0.5)',
- justifyContent: 'flex-end',
- },
- container: {
- backgroundColor: '#ffc901',
- borderTopLeftRadius: 10,
- borderTopRightRadius: 10,
- maxHeight: '80%',
- },
- titleSection: {
- position: 'relative',
- alignItems: 'center',
- paddingVertical: 15,
- },
- titleBg: {
- backgroundColor: '#ff8c16',
- paddingHorizontal: 40,
- paddingVertical: 10,
- borderRadius: 20,
- },
- titleText: {
- color: '#fff',
- fontSize: 16,
- fontWeight: 'bold',
- },
- closeBtn: {
- position: 'absolute',
- right: 15,
- top: 10,
- width: 30,
- height: 30,
- justifyContent: 'center',
- alignItems: 'center',
- },
- closeBtnText: {
- fontSize: 24,
- color: '#333',
- fontWeight: 'bold',
- },
- content: {
- backgroundColor: '#fff',
- marginHorizontal: 10,
- marginBottom: 20,
- borderRadius: 13,
- borderWidth: 1,
- borderColor: '#000',
- maxHeight: 470,
- },
- scrollView: {
- padding: 10,
- },
- grid: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- },
- item: {
- width: '25%',
- alignItems: 'center',
- marginBottom: 15,
- },
- imgBox: {
- width: 54,
- height: 54,
- },
- boxImg: {
- width: '100%',
- height: '100%',
- },
- numBadge: {
- backgroundColor: '#959595',
- borderRadius: 15,
- paddingHorizontal: 10,
- paddingVertical: 2,
- marginTop: 5,
- },
- numText: {
- color: '#fff',
- fontSize: 12,
- fontWeight: '500',
- },
- remaining: {
- fontSize: 12,
- color: '#999',
- fontWeight: 'bold',
- marginTop: 3,
- },
- });
|