- Fraunces 衬线 display + DM Sans body + JetBrains Mono 数字标签 - 暖米白主题(#f7f4ee)+ 蓝色强调色(#2563eb) - 引入 lucide-react 图标库替代 emoji - Sidebar 加入编号索引、Logo、用户区域、杂志风分组标题 - 产品列表页加入大号 display 标题、搜索、卡片悬浮动画 - 产品详情页面包屑、tab 编号、需求表格重做 - 状态徽章改为色点 + 文字,"已拒绝"用红色避免与"评审中"冲突 - 全局加入 grain 噪点纹理、入场交错动画 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
'use client';
|
|
|
|
import { Package } from 'lucide-react';
|
|
|
|
interface ProductWithCount {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
createdAt: string | Date;
|
|
_count?: { requirements: number; projects: number };
|
|
}
|
|
|
|
interface Props {
|
|
product: ProductWithCount;
|
|
index: number;
|
|
onClick: (id: string) => void;
|
|
}
|
|
|
|
export function ProductCard({ product, index, onClick }: Props) {
|
|
const reqCount = product._count?.requirements ?? 0;
|
|
const projCount = product._count?.projects ?? 0;
|
|
|
|
return (
|
|
<article
|
|
onClick={() => onClick(product.id)}
|
|
style={{ animationDelay: `${index * 60}ms` }}
|
|
className="group animate-fade-up relative cursor-pointer overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--bg-elevated)] p-6 transition-all duration-300 hover:-translate-y-0.5 hover:border-[var(--ink)] hover:shadow-[0_12px_32px_-12px_rgba(26,24,20,0.18)]"
|
|
>
|
|
<div className="flex items-start justify-between">
|
|
<span className="font-mono text-[10px] tabular-nums uppercase tracking-[0.18em] text-[var(--ink-muted)]">
|
|
№ {String(index + 1).padStart(3, '0')}
|
|
</span>
|
|
<Package className="h-4 w-4 text-[var(--ink-muted)] transition-colors group-hover:text-[var(--accent)]" strokeWidth={1.75} />
|
|
</div>
|
|
|
|
<h3 className="mt-6 font-display text-[26px] font-medium leading-[1.15] tracking-tight text-[var(--ink)]">
|
|
{product.name}
|
|
</h3>
|
|
|
|
{product.description ? (
|
|
<p className="mt-2 line-clamp-2 text-[13px] leading-relaxed text-[var(--ink-soft)]">
|
|
{product.description}
|
|
</p>
|
|
) : (
|
|
<p className="mt-2 text-[13px] italic text-[var(--ink-muted)]">暂无描述</p>
|
|
)}
|
|
|
|
<div className="mt-8 flex items-end justify-between border-t border-[var(--line-soft)] pt-4">
|
|
<div className="flex gap-6">
|
|
<div>
|
|
<p className="font-display text-2xl font-semibold tabular-nums text-[var(--ink)]">{reqCount}</p>
|
|
<p className="mt-0.5 font-mono text-[10px] uppercase tracking-[0.18em] text-[var(--ink-muted)]">需求</p>
|
|
</div>
|
|
<div className="h-10 w-px bg-[var(--line-soft)]" />
|
|
<div>
|
|
<p className="font-display text-2xl font-semibold tabular-nums text-[var(--ink)]">{projCount}</p>
|
|
<p className="mt-0.5 font-mono text-[10px] uppercase tracking-[0.18em] text-[var(--ink-muted)]">项目</p>
|
|
</div>
|
|
</div>
|
|
<span className="font-mono text-[11px] text-[var(--ink-muted)] opacity-0 transition-opacity group-hover:opacity-100">
|
|
→
|
|
</span>
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|