feat(product): 实现产品需求管理模块(后端 + 前端)
后端:Product Module(CRUD)、Requirement Module(CRUD + 状态机流转)、PrismaService 前端:产品列表页、产品详情页(含需求池 Tab)、Zustand Store、API 封装 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
30
apps/web/components/product/ProductCard.tsx
Normal file
30
apps/web/components/product/ProductCard.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
'use client';
|
||||
|
||||
import { Product } from '@ftb/shared';
|
||||
|
||||
interface ProductWithCount extends Product {
|
||||
_count?: { requirements: number; projects: number };
|
||||
}
|
||||
|
||||
interface Props {
|
||||
product: ProductWithCount;
|
||||
onClick: (id: string) => void;
|
||||
}
|
||||
|
||||
export function ProductCard({ product, onClick }: Props) {
|
||||
return (
|
||||
<div
|
||||
className="cursor-pointer rounded-lg border border-gray-200 p-5 transition-shadow hover:shadow-md"
|
||||
onClick={() => onClick(product.id)}
|
||||
>
|
||||
<h3 className="text-lg font-semibold text-gray-900">{product.name}</h3>
|
||||
{product.description && (
|
||||
<p className="mt-1 text-sm text-gray-500 line-clamp-2">{product.description}</p>
|
||||
)}
|
||||
<div className="mt-4 flex gap-4 text-xs text-gray-400">
|
||||
<span>{product._count?.requirements ?? 0} 需求</span>
|
||||
<span>{product._count?.projects ?? 0} 项目</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user