| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- 'use client'
- import React, {useEffect, useMemo, useState} from 'react';
- import Link from 'next/link';
- import Image from 'next/image';
- interface ProductMenuProps {
- products: ProductCategory[]
- }
- export default function CoreProducts({products}: ProductMenuProps) {
- const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL as string
- const filteredProducts = useMemo(() => {
- return (products ?? []).filter((item) => item.productCategoryName !== "软件产品")
- }, [products])
- const orderedProducts = useMemo(() => {
- return [...filteredProducts].reverse()
- }, [filteredProducts])
- const tabs = useMemo(() => {
- const allTypes = (orderedProducts ?? []).flatMap((category) => category.productTypes ?? [])
- return Array.from(new Set(allTypes.map((type) => type.productTypeName)))
- }, [orderedProducts])
- const [activeTab, setActiveTab] = useState(() => tabs[0] ?? "")
- const [isPaused, setIsPaused] = useState(false)
- useEffect(() => {
- if (tabs.length === 0) return
- if (!activeTab || !tabs.includes(activeTab)) {
- setActiveTab(tabs[0])
- }
- }, [tabs, activeTab])
- useEffect(() => {
- if (tabs.length === 0 || isPaused) return
- const intervalId = setInterval(() => {
- setActiveTab((prev) => {
- const currentIndex = tabs.indexOf(prev)
- const safeIndex = currentIndex === -1 ? 0 : currentIndex
- const nextIndex = (safeIndex + 1) % tabs.length
- return tabs[nextIndex]
- })
- }, 5000)
- return () => clearInterval(intervalId)
- }, [tabs, isPaused])
- const showProducts = useMemo(() => {
- if (!activeTab) return []
- const allTypes = (orderedProducts ?? []).flatMap((category) => category.productTypes ?? [])
- const matched = allTypes
- .filter((type) => type.productTypeName === activeTab)
- .flatMap((type) => type.productCenters ?? [])
- return matched.slice(0, 4)
- }, [orderedProducts, activeTab])
- return (
- <section className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
- <div className="w-full border border-gray-300 rounded-md overflow-hidden">
- <div className="flex overflow-x-auto">
- {tabs.map((tab) => (
- <div
- key={tab}
- onClick={() => setActiveTab(tab)}
- className={`flex-1 min-w-36 sm:min-w-44 py-3 sm:py-4 text-center shuheiti transition-colors cursor-pointer ${
- activeTab === tab
- ? "bg-blue-600 text-white font-semibold"
- : "bg-white text-gray-700 hover:bg-gray-100"
- }`}
- >
- {tab}
- </div>
- ))}
- </div>
- </div>
- <div
- className="mt-4 sm:mt-6 grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-6"
- onMouseEnter={() => setIsPaused(true)}
- onMouseLeave={() => setIsPaused(false)}
- >
- {showProducts.map((product) => (
- <Link
- key={product.productId}
- href={`/products/${product.productId}`}
- className="group rounded-xl border border-gray-200 bg-white p-4 sm:p-6 flex flex-col items-center text-center justify-between shadow-sm hover:shadow-md transition-shadow duration-300 cursor-pointer"
- >
- <h3 className="shuheiti text-sm sm:text-xl text-gray-900 line-clamp-1">
- {product.productName}
- </h3>
- <p className="mt-1 text-xs sm:text-sm text-gray-500 w-full">
- <span className="text-blue-800 font-bold line-clamp-2">{product.productIntroduction}</span>
- </p>
- <div className="mt-3 sm:mt-5 w-full overflow-hidden rounded-lg bg-gray-50">
- <Image
- src={product.productUrl ? BASE_URL + product.productUrl : "/assets/productions/2.png"}
- alt={product.productName}
- width={1000}
- height={1000}
- sizes="(max-width: 640px) 50vw, 25vw"
- className="w-full h-auto object-contain p-2 transition-transform duration-300 group-hover:scale-105"
- />
- </div>
- <div className="mt-3 sm:mt-5 w-full flex flex-col items-center gap-1">
- <span className="text-xs sm:text-sm text-gray-700 line-clamp-1">
- {product.productType}
- </span>
- <span className="text-xs text-gray-400 line-clamp-1">
- {product.productModel}
- </span>
- </div>
- </Link>
- ))}
- </div>
- </section>
- );
- };
|