| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- import React, { useState, useRef, useEffect } from "react";
- import { Swiper, SwiperSlide } from "swiper/react";
- import { Scrollbar, Navigation } from "swiper/modules";
- import "swiper/css";
- import "swiper/css/scrollbar";
- import "swiper/css/navigation";
- import Image from "next/image";
- import { OpenAddToCartModalButton } from "@/components/common/AddToCartModal/OpenAddToCartModalButton";
- import {HomeProduct} from "@/types/home/type"
- interface trendingProps {
- trending: HomeProduct[];
- }
- // // 商品数据,每个卡片携带videoUrl视频地址
- // type ProductItem = {
- // id: number;
- // img: string;
- // title: string;
- // price: number;
- // videoUrl: string;
- // };
- // const productList: ProductItem[] = [
- // {
- // id: 1,
- // img: "/img/hair-video-1.jpg",
- // title: "14-36 In Water Wave Human Hair HD Inv...",
- // price: 146.1,
- // videoUrl: "/video/hair-demo-1.mp4",
- // },
- // {
- // id: 2,
- // img: "/img/hair-video-2.jpg",
- // title: "14-36 In Water Wave Human Hair HD Inv...",
- // price: 146.1,
- // videoUrl: "/video/hair-demo-2.mp4",
- // },
- // {
- // id: 3,
- // img: "/img/hair-video-3.jpg",
- // title: "14-36 In Water Wave Human Hair HD Inv...",
- // price: 146.1,
- // videoUrl: "/video/hair-demo-3.mp4",
- // },
- // {
- // id: 4,
- // img: "/img/hair-video-4.jpg",
- // title: "14-36 In Water Wave Human Hair HD Inv...",
- // price: 146.1,
- // videoUrl: "/video/hair-demo-4.mp4",
- // },
- // ];
- const Trending = ({ trending }: trendingProps) => {
- // 视频弹窗状态
- const [openVideoModal, setOpenVideoModal] = useState(false);
- const [currentVideoSrc, setCurrentVideoSrc] = useState("");
- const videoRef = useRef<HTMLVideoElement>(null);
- // 弹窗打开自动播放
- useEffect(() => {
- if (openVideoModal && videoRef.current) {
- videoRef.current.play().catch((err) => console.log("播放拦截", err));
- }
- }, [openVideoModal]);
-
- if (!trending || trending.length === 0) return null;
- const productList = trending
-
-
- // 打开弹窗并赋值视频地址
- const handlePlayClick = (videoUrl: string) => {
- setCurrentVideoSrc(videoUrl);
- setOpenVideoModal(true);
- };
- // 关闭弹窗,暂停视频
- const closeModal = () => {
- setOpenVideoModal(false);
- if (videoRef.current) {
- videoRef.current.pause();
- videoRef.current.currentTime = 0;
- }
- };
-
- return (
- <div className="w-full max-w-[960px] mx-auto">
- <div className="w-full max-w-[960px] mx-auto px-4 py-6">
- {/* 顶部标题 */}
- <h2 className="text-[clamp(1.5rem,4vw,2.2rem)] font-bold mb-6 text-black">
- Real looks,Trending Now
- </h2>
- {/* Swiper外层容器:进度条深层Tailwind样式 */}
- <div
- className="
- [&_.custom-scrollbar]:h-[3px]
- [&_.custom-scrollbar]:bg-gray-200
- [&_.custom-scrollbar]:rounded-full
- [&_.swiper-scrollbar-drag]:h-full
- [&_.swiper-scrollbar-drag]:bg-black
- [&_.swiper-scrollbar-drag]:rounded-full
- [&_.swiper-scrollbar-drag]:shadow-none
- [&_.swiper-scrollbar]:bg-transparent
- /* 自定义左右箭头样式 匹配截图灰色圆形按钮 */
- [&_.swiper-button-next]:w-11
- [&_.swiper-button-next]:h-11
- [&_.swiper-button-next]:rounded-full
- [&_.swiper-button-next]:bg-black/40
- [&_.swiper-button-next]:text-white
- [&_.swiper-button-next]:after:text-base
- [&_.swiper-button-next]:after:font-bold
- [&_.swiper-button-prev]:w-11
- [&_.swiper-button-prev]:h-11
- [&_.swiper-button-prev]:rounded-full
- [&_.swiper-button-prev]:bg-black/40
- [&_.swiper-button-prev]:text-white
- [&_.swiper-button-prev]:after:text-base
- [&_.swiper-button-prev]:after:font-bold
- [&_.swiper-button-next]:right-3
- [&_.swiper-button-prev]:left-3
- "
- >
- <Swiper
- modules={[Scrollbar, Navigation]}
- spaceBetween={16}
- slidesPerView={1.2} // 露出右侧下一张,和截图一致
- navigation={{
- prevEl: ".btn-prev", // 左箭头class
- nextEl: ".btn-next", // 右箭头class
- disabledClass: "opacity-20", // 滑到首尾自动加这个类,Tailwind直接用
- }}
- breakpoints={{
- 640: { slidesPerView: 2.2 },
- 1024: { slidesPerView: 2.5 },
- }}
- >
- {productList.map((item) => (
- <SwiperSlide key={item.id} className="!h-auto">
- {/* 单个商品卡片 */}
- <div className=" overflow-hidden flex flex-col">
- {/* 图片区域 + 中间播放按钮 */}
- <div className="relative rounded-xl w-full aspect-[4/5] overflow-hidden rounded-xl">
- <img
- src={item.image_url}
- alt={item.name}
- className="w-full h-full object-cover"
- />
- {/* 居中圆形播放按钮 */}
- <button
- onClick={() => handlePlayClick(item.videoUrl||"/video/hair-demo-1.mp4" )}
- className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
- w-24 h-24 rounded-full bg-white/60 backdrop-blur-sm
- flex items-center justify-center transition hover:bg-white/80"
- >
- <svg
- width="36"
- height="36"
- viewBox="0 0 24 24"
- fill="none"
- stroke="#222"
- strokeWidth="2"
- >
- <polygon points="5 3 19 12 5 21 5 3" />
- </svg>
- </button>
- </div>
- {/* 底部文字价格区域 */}
- <div className="p-3 flex flex-col rounded-xl mt-3 bg-[#f0f8f5] gap-3">
- <p className="text-base text-gray-900 truncate">
- {item.name}
- </p>
- {/* 价格 + 购物车图标 */}
- <div className="flex items-center justify-between">
- <div className="flex items-center gap-1">
- <span className="font-semibold">${item.min_price}</span>
- <span className="text-xs text-gray-500 line-through">
- ${item.price}
- </span>
- </div>
- {/* 购物车图标 */}
- <OpenAddToCartModalButton
- productId={item.id}
- icon={
- <svg
- xmlns="http://www.w3.org/2000/svg"
- width="32"
- height="32"
- viewBox="0 0 32 32"
- fill="none"
- >
- <rect
- x="0"
- y="0"
- width="32"
- height="32"
- rx="8"
- fill="#036141"
- ></rect>
- <path
- stroke="rgba(255, 255, 255, 1)"
- stroke-width="1.3333333333333333"
- stroke-linejoin="round"
- stroke-linecap="round"
- d="M6.40039 7.79993L8.03372 7.79993L8.73372 10.5999M8.73372 10.5999L11.0671 19.9333L23.2004 19.9333L25.5337 10.5999L8.73372 10.5999Z"
- ></path>
- <ellipse
- cx="11.066040515899658"
- cy="23.199928283691406"
- rx="1.4000248908996582"
- ry="1.4000015258789062"
- stroke="rgba(255, 255, 255, 1)"
- stroke-width="1.3333333333333333"
- stroke-linejoin="round"
- stroke-linecap="round"
- ></ellipse>
- <ellipse
- cx="23.1998291015625"
- cy="23.199928283691406"
- rx="1.4000244140625"
- ry="1.4000015258789062"
- stroke="rgba(255, 255, 255, 1)"
- stroke-width="1.3333333333333333"
- stroke-linejoin="round"
- stroke-linecap="round"
- ></ellipse>
- <path
- stroke="rgba(255, 255, 255, 1)"
- stroke-width="1.3333333333333333"
- stroke-linejoin="round"
- stroke-linecap="round"
- d="M15.2656 15.2665L18.999 15.2665"
- ></path>
- <path
- stroke="rgba(255, 255, 255, 1)"
- stroke-width="1.3333333333333333"
- stroke-linejoin="round"
- stroke-linecap="round"
- d="M17.1348 17.1332L17.1348 13.3999"
- ></path>
- </svg>
- }
- />
- </div>
- </div>
- </div>
- </SwiperSlide>
- ))}
- {/* 自定义左右按钮,放在Swiper内部,同级slide */}
- <button className="btn-prev absolute left-2 top-1/2 -translate-y-1/2 z-10 w-9 h-9 rounded-full bg-black/50 shadow flex items-center justify-center">
- {/* 自定义左箭头SVG */}
- <svg
- width="16"
- height="16"
- viewBox="0 0 24 24"
- fill="none"
- stroke="#fff"
- stroke-width="2"
- >
- <path d="M15 18l-6-6 6-6" />
- </svg>
- </button>
- <button className="btn-next absolute right-2 top-1/2 -translate-y-1/2 z-10 w-9 h-9 rounded-full bg-black/50 shadow flex items-center justify-center">
- {/* 自定义右箭头SVG */}
- <svg
- width="16"
- height="16"
- viewBox="0 0 24 24"
- fill="none"
- stroke="#fff"
- stroke-width="2"
- >
- <path d="M9 18l6-6-6-6" />
- </svg>
- </button>
- </Swiper>
- </div>
- {/* ====================== 全屏视频遮罩弹窗 ====================== */}
- {openVideoModal && (
- <div
- className="fixed inset-0 z-[9999] bg-black/95 flex items-center justify-center p-4"
- onClick={closeModal} // 点击遮罩空白关闭
- >
- {/* 弹窗内层,阻止冒泡 */}
- <div
- className="relative w-full max-w-4xl"
- onClick={(e) => e.stopPropagation()}
- >
- {/* 右上角关闭按钮 */}
- <button
- onClick={closeModal}
- className="absolute -top-12 right-0 text-white text-3xl hover:text-gray-300"
- >
- ✕
- </button>
- {/* 视频播放器 */}
- <video
- ref={videoRef}
- src={currentVideoSrc}
- controls
- className="w-full rounded-lg"
- />
- </div>
- </div>
- )}
- </div>
- <div className="relative w-full aspect-[3/4] mt-8">
- <Image
- src={
- "https://cdn.asteriahair.com/uploads/202607/01/20260701165110_3fff435adf276b89.jpg"
- }
- alt={"cscscs"}
- fill
- className="object-cover rounded-md"
- />
- </div>
- </div>
- );
- };
- export default Trending;
|