GoodsCard.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { Images } from '@/constants/images';
  2. import { GoodsItem } from '@/services/mall';
  3. import { Image } from 'expo-image';
  4. import React from 'react';
  5. import { Dimensions, ImageBackground, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
  6. const { width: SCREEN_WIDTH } = Dimensions.get('window');
  7. // 小程序: width = (screenWidth - 18) / 2, height = 504rpx = 252pt
  8. const CARD_WIDTH = (SCREEN_WIDTH - 18) / 2;
  9. const CARD_HEIGHT = 252;
  10. // 图片区域: 340rpx = 170pt, 356rpx = 178pt
  11. const IMG_BOX_WIDTH = 170;
  12. const IMG_BOX_HEIGHT = 178;
  13. interface GoodsCardProps {
  14. data: GoodsItem;
  15. onPress?: (item: GoodsItem) => void;
  16. }
  17. export function GoodsCard({ data, onPress }: GoodsCardProps) {
  18. return (
  19. <TouchableOpacity activeOpacity={0.8} onPress={() => onPress?.(data)}>
  20. <ImageBackground
  21. source={{ uri: Images.home.cellGoodsBg }}
  22. style={[styles.cell, { width: CARD_WIDTH }]}
  23. resizeMode="cover"
  24. >
  25. <View style={[styles.content, { width: CARD_WIDTH - 10 }]}>
  26. <View style={styles.imgBox}>
  27. <Image source={data.cover} style={styles.image} contentFit="contain" />
  28. {/* 图片边框装饰 */}
  29. <ImageBackground
  30. source={{ uri: Images.home.imgBoxBorder }}
  31. style={styles.imgBoxBorder}
  32. resizeMode="center"
  33. />
  34. </View>
  35. <View style={styles.textBox}>
  36. <Text style={styles.name} numberOfLines={1}>
  37. {data.name}
  38. </Text>
  39. <View style={styles.priceRow}>
  40. <Text style={styles.currency}>¥</Text>
  41. <Text style={styles.price}>{data.price}</Text>
  42. {data.sellType === 2 && (
  43. <View style={styles.presellTag}>
  44. <Text style={styles.presellText}>预售</Text>
  45. </View>
  46. )}
  47. </View>
  48. </View>
  49. </View>
  50. </ImageBackground>
  51. </TouchableOpacity>
  52. );
  53. }
  54. const styles = StyleSheet.create({
  55. cell: {
  56. height: CARD_HEIGHT,
  57. marginBottom: 12,
  58. },
  59. content: {
  60. overflow: 'hidden',
  61. borderRadius: 8,
  62. },
  63. imgBox: {
  64. width: IMG_BOX_WIDTH,
  65. height: IMG_BOX_HEIGHT,
  66. borderRadius: 7,
  67. overflow: 'hidden',
  68. paddingHorizontal: 6,
  69. alignSelf: 'center',
  70. },
  71. image: {
  72. width: '100%',
  73. height: '100%',
  74. },
  75. imgBoxBorder: {
  76. position: 'absolute',
  77. left: 0,
  78. top: 0,
  79. width: '100%',
  80. height: '100%',
  81. },
  82. textBox: {
  83. paddingHorizontal: 9,
  84. marginTop: 6,
  85. },
  86. name: {
  87. fontSize: 12,
  88. color: '#fff',
  89. },
  90. priceRow: {
  91. flexDirection: 'row',
  92. alignItems: 'baseline',
  93. marginTop: 3,
  94. },
  95. currency: {
  96. fontSize: 10,
  97. color: '#fff',
  98. },
  99. price: {
  100. fontSize: 16,
  101. fontWeight: 'bold',
  102. color: '#fff',
  103. },
  104. presellTag: {
  105. width: 64,
  106. height: 22,
  107. lineHeight: 22,
  108. borderRadius: 11,
  109. marginLeft: 8,
  110. justifyContent: 'center',
  111. alignItems: 'center',
  112. backgroundColor: 'rgba(255,255,255,0.2)',
  113. },
  114. presellText: {
  115. fontSize: 12,
  116. color: '#fff',
  117. textAlign: 'center',
  118. },
  119. });