| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- import { Image } from 'expo-image';
- import React from 'react';
- import { ImageBackground, StyleSheet, Text, View } from 'react-native';
- import { Images } from '@/constants/images';
- interface ProductItem {
- id: string;
- name: string;
- cover: string;
- level: string;
- probability: number;
- price?: number;
- quantity?: number;
- }
- interface ProductListProps {
- products: ProductItem[];
- levelList?: any[];
- poolId: string;
- price: number;
- }
- const LEVEL_CONFIG: Record<string, { title: string; bg: string }> = {
- A: { title: '超神款', bg: Images.box.detail.productItemA },
- B: { title: '欧皇款', bg: Images.box.detail.productItemB },
- C: { title: '隐藏款', bg: Images.box.detail.productItemC },
- D: { title: '普通款', bg: Images.box.detail.productItemD },
- };
- const ignoreRatio0 = (val: number) => {
- const str = String(val);
- const match = str.match(/^(\d+\.?\d*?)0*$/);
- return match ? match[1].replace(/\.$/, '') : str;
- };
- export const ProductList: React.FC<ProductListProps> = ({ products, levelList }) => {
- // 按等级分组
- const groupedProducts = products.reduce(
- (acc, item) => {
- const level = item.level || 'D';
- if (!acc[level]) acc[level] = [];
- acc[level].push(item);
- return acc;
- },
- {} as Record<string, ProductItem[]>
- );
- // 计算各等级概率
- const levelProbabilities =
- levelList?.reduce(
- (acc, item) => {
- acc[item.level] = item.probability;
- return acc;
- },
- {} as Record<string, number>
- ) || {};
- const renderLevelSection = (level: string, items: ProductItem[]) => {
- const config = LEVEL_CONFIG[level] || { title: level, bg: Images.box.detail.productItemD };
- const probability = levelProbabilities[level] || items.reduce((sum, i) => sum + (i.probability || 0), 0);
- return (
- <View key={level} style={styles.levelSection}>
- {/* 等级标题 */}
- <ImageBackground source={{ uri: Images.box.detail.levelBoxBg }} style={styles.levelHeader} resizeMode="stretch">
- <Text style={styles.levelTitle}>{config.title}</Text>
- <Text style={styles.levelProbability}>概率: {ignoreRatio0(probability * 100)}%</Text>
- </ImageBackground>
- {/* 商品网格 */}
- <View style={styles.productGrid}>
- {items.map((item, index) => (
- <View key={item.id || index} style={styles.productItem}>
- <ImageBackground source={{ uri: config.bg }} style={styles.productItemBg} resizeMode="stretch">
- <View style={styles.productImageBox}>
- <Image source={{ uri: item.cover }} style={styles.productImage} contentFit="cover" />
- </View>
- <Text style={styles.productName} numberOfLines={2}>
- {item.name}
- </Text>
- <Text style={styles.productProbability}>概率: {ignoreRatio0((item.probability || 0) * 100)}%</Text>
- </ImageBackground>
- </View>
- ))}
- </View>
- </View>
- );
- };
- const levelOrder = ['A', 'B', 'C', 'D'];
- return (
- <View style={styles.container}>
- {/* 标题 */}
- <View style={styles.titleBox}>
- <Image source={{ uri: Images.box.detail.productTitle }} style={styles.titleImg} contentFit="contain" />
- </View>
- {levelOrder.map((level) => {
- const items = groupedProducts[level];
- if (!items || items.length === 0) return null;
- return renderLevelSection(level, items);
- })}
- </View>
- );
- };
- const styles = StyleSheet.create({
- container: {
- paddingHorizontal: 10,
- marginTop: -40,
- },
- titleBox: {
- alignItems: 'center',
- marginBottom: 10,
- },
- titleImg: {
- width: 121,
- height: 29,
- },
- levelSection: {
- marginBottom: 15,
- },
- levelHeader: {
- height: 40,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- paddingHorizontal: 15,
- marginBottom: 10,
- },
- levelTitle: {
- color: '#fff',
- fontSize: 16,
- fontWeight: 'bold',
- },
- levelProbability: {
- color: 'rgba(255,255,255,0.8)',
- fontSize: 12,
- },
- productGrid: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- marginHorizontal: -5,
- },
- productItem: {
- width: '33.33%',
- paddingHorizontal: 5,
- marginBottom: 10,
- },
- productItemBg: {
- width: '100%',
- aspectRatio: 0.75,
- padding: 8,
- alignItems: 'center',
- },
- productImageBox: {
- width: '100%',
- aspectRatio: 1,
- borderRadius: 5,
- overflow: 'hidden',
- backgroundColor: 'rgba(255,255,255,0.1)',
- },
- productImage: {
- width: '100%',
- height: '100%',
- },
- productName: {
- color: '#fff',
- fontSize: 10,
- marginTop: 5,
- textAlign: 'center',
- height: 26,
- },
- productProbability: {
- color: '#FBC400',
- fontSize: 9,
- marginTop: 2,
- },
- });
|