feat(mp): 积分商城 V2 重设计 — design-handoff 全流程
- 新增 4 个 UI 组件: PointsCard/ProductCard/CheckinCalendar/CheckinModal - 商城首页 V2: 积分卡 + 快捷操作 + 分类标签 + 商品网格 - 商品详情 V2: 大图 + 信息卡 + 库存/余额状态 + 底部操作栏 - TabBar 新增商城入口(5 Tab: 首页/健康/商城/助手/我的) - 设计原型 docs/design/mp-05-mall-v2.html + SPEC.md 交付包 - CLAUDE.md 安全规范加固: 新增 §3.7 安全规范 6 条 + Feature DoD 安全清单扩展
This commit is contained in:
58
apps/miniprogram/src/components/ui/ProductCard/index.tsx
Normal file
58
apps/miniprogram/src/components/ui/ProductCard/index.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import type { PointsProduct } from '@/services/points';
|
||||
import './index.scss';
|
||||
|
||||
interface ProductCardProps {
|
||||
product: PointsProduct;
|
||||
onPress?: (product: PointsProduct) => void;
|
||||
}
|
||||
|
||||
const TYPE_BG_CLASS: Record<string, string> = {
|
||||
physical: 'product-card__thumb--physical',
|
||||
service: 'product-card__thumb--service',
|
||||
privilege: 'product-card__thumb--privilege',
|
||||
};
|
||||
|
||||
const TYPE_LABELS: Record<string, string> = {
|
||||
physical: '实物',
|
||||
service: '服务券',
|
||||
privilege: '权益',
|
||||
};
|
||||
|
||||
const ProductCard: React.FC<ProductCardProps> = ({ product, onPress }) => {
|
||||
const isSoldOut = product.stock <= 0;
|
||||
const isLowStock = product.stock > 0 && product.stock <= 10;
|
||||
|
||||
return (
|
||||
<View
|
||||
className='product-card'
|
||||
onClick={() => onPress?.(product)}
|
||||
>
|
||||
<View className='product-card__thumb-wrap'>
|
||||
<View className={`product-card__thumb ${TYPE_BG_CLASS[product.product_type] || ''}`}>
|
||||
<Text className='product-card__thumb-type'>{TYPE_LABELS[product.product_type] || '商品'}</Text>
|
||||
</View>
|
||||
{isSoldOut && (
|
||||
<View className='product-card__soldout'>
|
||||
<Text className='product-card__soldout-text'>已兑完</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View className='product-card__info'>
|
||||
<Text className='product-card__name'>{product.name}</Text>
|
||||
<View className='product-card__bottom'>
|
||||
<View className='product-card__points-row'>
|
||||
<Text className='product-card__points-num'>{product.points_cost}</Text>
|
||||
<Text className='product-card__points-unit'>积分</Text>
|
||||
</View>
|
||||
</View>
|
||||
{isLowStock && (
|
||||
<Text className='product-card__low-stock'>仅剩{product.stock}件</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(ProductCard);
|
||||
Reference in New Issue
Block a user