diff --git a/src/app/HomeClient.tsx b/src/app/HomeClient.tsx index 26779740..7914ea12 100644 --- a/src/app/HomeClient.tsx +++ b/src/app/HomeClient.tsx @@ -10,19 +10,53 @@ import { useDebounce } from '@/hooks/usePerformance' type TabType = 'models' | 'hardware' | 'bom' | 'docs' +// 产品 SKU 类型(与 ProductListItem 兼容) +interface ProductSku { + id: string + skuCode: string + price: number + stock: number + isActive: boolean + name?: string | null +} + +// 产品类型(与 ProductListItem 兼容) +interface ProductWithSkus { + id: string + name: string + modelNumber: string + description?: string | null + category: string | null + modelUrl?: string | null + thumbnailUrl?: string | null + visibility?: 'TEAM' | 'DEPARTMENT' | 'PUBLIC' + skus: ProductSku[] + createdAt: Date | string + updatedAt?: Date | string + _count: { + assemblySteps: number + shareLinks: number + skus: number + } + shareLinks: Array<{ + token: string + viewCount: number + }> +} + interface HomeClientProps { - products: any[] + products: ProductWithSkus[] } export default function HomeClient({ products: initialProducts }: HomeClientProps) { const [activeTab, setActiveTab] = useState('models') const [isUploadModalOpen, setIsUploadModalOpen] = useState(false) - const [products, setProducts] = useState(initialProducts) + const [products, setProducts] = useState(initialProducts) const [searchQuery, setSearchQuery] = useState('') // 控制“新建型号”弹窗 const [isCreateModalOpen, setIsCreateModalOpen] = useState(false) // 控制“编辑产品”弹窗以及当前要编辑的产品 - const [editingProduct, setEditingProduct] = useState(null) + const [editingProduct, setEditingProduct] = useState(null) // 新建型号表单状态 const [newModelNumber, setNewModelNumber] = useState('') const [newName, setNewName] = useState('') @@ -77,12 +111,12 @@ export default function HomeClient({ products: initialProducts }: HomeClientProp const query = raw.toLowerCase() - return products.filter((product: any) => { + return products.filter((product) => { const inModelNumber = product.modelNumber?.toLowerCase().includes(query) const inName = product.name?.toLowerCase().includes(query) const inDescription = product.description?.toLowerCase().includes(query) const inSkuCodes = Array.isArray(product.skus) - ? product.skus.some((sku: any) => + ? product.skus.some((sku) => sku.skuCode?.toLowerCase().includes(query) ) : false @@ -174,7 +208,7 @@ export default function HomeClient({ products: initialProducts }: HomeClientProp }, [newModelNumber, newName, newCategory, newDescription, newVisibility, reloadProducts]) // 打开“编辑产品”弹窗,并根据当前产品初始化表单 - const handleOpenEditProduct = useCallback((product: any) => { + const handleOpenEditProduct = useCallback((product: ProductWithSkus) => { setEditingProduct(product) setEditName(product.name || '') setEditCategory(product.category || '') @@ -734,7 +768,7 @@ interface TabCardProps { id: TabType name: string description: string - icon: any + icon: React.ComponentType> } isActive: boolean onClick: (tabId: TabType) => void diff --git a/src/app/page.tsx b/src/app/page.tsx index 0d7f7cd0..7117d2eb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -68,6 +68,7 @@ export default async function HomePage() { // 手动计算 count 并转换 Decimal 类型 const productsWithCount = products.map(product => ({ ...product, + visibility: product.visibility as 'TEAM' | 'DEPARTMENT' | 'PUBLIC', skus: product.skus.map(sku => ({ ...sku, price: sku.price.toNumber() // 将 Prisma Decimal 转换为 number diff --git a/src/components/ui/ProductListItem.tsx b/src/components/ui/ProductListItem.tsx index 74176d40..3324b5bc 100644 --- a/src/components/ui/ProductListItem.tsx +++ b/src/components/ui/ProductListItem.tsx @@ -9,16 +9,15 @@ * - 使用 useMemo 缓存计算结果 * * @created 2025-12-12 - * @updated 2025-12-13 - 性能优化 + * @updated 2025-12-22 - 修复类型兼容性 */ 'use client' import React, { memo, useCallback, useMemo } from 'react' import Link from 'next/link' -import { ChevronDown, ChevronRight, Package, Eye, User } from 'lucide-react' +import { ChevronDown, ChevronRight, Package, User } from 'lucide-react' import Badge from '@/components/ui/Badge' -import Image from 'next/image' // 产品列表项组件的入参类型 interface ProductListItemProps { @@ -27,7 +26,10 @@ interface ProductListItemProps { name: string modelNumber: string category: string | null - createdAt: Date + createdAt: Date | string + updatedAt?: Date | string + description?: string | null + visibility?: 'TEAM' | 'DEPARTMENT' | 'PUBLIC' _count: { assemblySteps: number shareLinks: number @@ -45,8 +47,9 @@ interface ProductListItemProps { isActive: boolean }> } - // 当点击“编辑产品”按钮时触发,由父组件控制弹窗 - onEdit?: (product: ProductListItemProps['product']) => void + // 当点击"编辑产品"按钮时触发,由父组件控制弹窗 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + onEdit?: (product: any) => void } const ProductListItem = memo(function ProductListItem({ product, onEdit }: ProductListItemProps) { @@ -142,7 +145,6 @@ const ProductListItem = memo(function ProductListItem({ product, onEdit }: Produ color: 'var(--color-label-primary)', cursor: 'pointer' }} - // 交给父组件决定如何编辑(弹窗形式) onClick={() => onEdit?.(product)} > 编辑产品 @@ -205,7 +207,7 @@ const ProductListItem = memo(function ProductListItem({ product, onEdit }: Produ {sku.isActive ? '已上架' : '未上架'} - {/* SKU 预览按钮 - 去掉图标 */} + {/* SKU 预览按钮 */} {shareLink && (