| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { Colors } from "@/constants/Colors";
- import { GoodsItem } from "@/services/mall";
- import { Image } from "expo-image";
- import React from "react";
- import {
- Dimensions,
- StyleSheet,
- Text,
- TouchableOpacity,
- View,
- } from "react-native";
- const { width: SCREEN_WIDTH } = Dimensions.get("window");
- const CARD_WIDTH = (SCREEN_WIDTH - 24) / 2; // Slightly more margin
- const IMG_BOX_WIDTH = CARD_WIDTH - 2; // Full width minus border
- interface GoodsCardProps {
- data: GoodsItem;
- onPress?: (item: GoodsItem) => void;
- }
- export function GoodsCard({ data, onPress }: GoodsCardProps) {
- return (
- <TouchableOpacity activeOpacity={0.8} onPress={() => onPress?.(data)}>
- <View style={[styles.card, { width: CARD_WIDTH }]}>
- <View style={styles.imgBox}>
- <Image
- source={
- typeof data.cover === "string" ? { uri: data.cover } : data.cover
- }
- style={styles.image}
- contentFit="cover"
- />
- {/* Cyberpunk Overlay/Border */}
- <View style={styles.cyberOverlay} />
- </View>
- <View style={styles.textBox}>
- <Text style={styles.name} numberOfLines={2}>
- {data.name}
- </Text>
- <View style={styles.priceRow}>
- <Text style={styles.currency}>¥</Text>
- <Text style={styles.price}>{data.price}</Text>
- </View>
- {data.sellType === 2 && (
- <View style={styles.presellTag}>
- <Text style={styles.presellText}>预售</Text>
- </View>
- )}
- </View>
- {/* Deco corners */}
- <View style={styles.cornerTL} />
- <View style={styles.cornerBR} />
- </View>
- </TouchableOpacity>
- );
- }
- const styles = StyleSheet.create({
- card: {
- backgroundColor: Colors.darkCard,
- borderRadius: 4,
- marginBottom: 12,
- overflow: "hidden",
- borderWidth: 1,
- borderColor: "rgba(0, 243, 255, 0.3)", // Neon Blue low opacity
- paddingBottom: 8,
- },
- imgBox: {
- width: "100%",
- aspectRatio: 1,
- backgroundColor: "#000",
- position: "relative",
- },
- image: {
- width: "100%",
- height: "100%",
- },
- cyberOverlay: {
- ...StyleSheet.absoluteFillObject,
- borderWidth: 1,
- borderColor: "rgba(0, 243, 255, 0.1)",
- zIndex: 1,
- },
- textBox: {
- padding: 8,
- },
- name: {
- fontSize: 12,
- color: Colors.textPrimary,
- lineHeight: 16,
- height: 32, // Fixed height for 2 lines
- marginBottom: 4,
- fontWeight: "500",
- },
- priceRow: {
- flexDirection: "row",
- alignItems: "baseline",
- },
- currency: {
- fontSize: 10,
- color: Colors.neonBlue,
- marginRight: 2,
- },
- price: {
- fontSize: 16,
- fontWeight: "bold",
- color: Colors.neonBlue,
- textShadowColor: "rgba(0, 243, 255, 0.5)",
- textShadowOffset: { width: 0, height: 0 },
- textShadowRadius: 4,
- },
- presellTag: {
- position: "absolute",
- right: 8,
- bottom: 0,
- backgroundColor: Colors.neonPink,
- paddingHorizontal: 6,
- paddingVertical: 2,
- borderRadius: 2,
- },
- presellText: {
- fontSize: 10,
- color: "#fff",
- fontWeight: "bold",
- },
- // Corner decorations
- cornerTL: {
- position: "absolute",
- top: 0,
- left: 0,
- width: 6,
- height: 6,
- borderTopWidth: 2,
- borderLeftWidth: 2,
- borderColor: Colors.neonBlue,
- },
- cornerBR: {
- position: "absolute",
- bottom: 0,
- right: 0,
- width: 6,
- height: 6,
- borderBottomWidth: 2,
- borderRightWidth: 2,
- borderColor: Colors.neonBlue,
- },
- });
|