Jelajahi Sumber

代码调整

zhangzf 4 hari lalu
induk
melakukan
50f8894d77

+ 77 - 77
src/app/(public)/customer/order/history/_components/OrderHistory.tsx

@@ -5,80 +5,80 @@ import Link from "next/link";
 import { clientFetch } from "@/lib/restApiClient";
 
 // 模拟订单数据
-const mockOrders = [
-  {
-    id: 600217097,
-    date: "3/4/2026",
-    status: "Processing",
-    items: [
-      {
-        name: "Highlight Wigs For Women Headband Wigs with Blonde Highlights",
-        specs: "10, #022, Straight, 5 Free Headbands",
-        price: "88 points + $154.05x1",
-        image: "",
-      },
-    ],
-    progress: "Preparing Order",
-    total: "88 Points + $158.67",
-  },
-  {
-    id: 100055662,
-    date: "3/3/2026",
-    status: "Processing",
-    items: [
-      {
-        name: "Alipearl Lace Front Wig 180% Density Body Wave Human Hair Wigs Pre...",
-        specs: "10+180%, Medium, No Adjustable Band",
-        price: "$128.82x1",
-        image: "",
-      },
-    ],
-    progress: "Preparing Order",
-    total: "$132.68",
-  },
-  {
-    id: 600217055,
-    date: "3/3/2026",
-    status: "Processing",
-    items: [
-      {
-        name: "3 Bundles Deep Wave Hair With 4*4 Lace Closure Alipearl Brazilian Hair",
-        specs: "8 8 8, Free Part, 8",
-        price: "$142.14x1",
-        image: "",
-      },
-      {
-        name: "Princess Braids Wig Blonde Barbie Pre-Styled Highlight Wig 13×4 Front Wig",
-        specs: "12",
-        price: "$279.32x1",
-        image:
-          "https://cdn.alipearlhair.com/media/catalog/product/cache/6/thumbnail/750x1000/9df78eab33525d08d6e5fb8d27136e95/b/o/body_wave_lace_front_wig_2.jpg", // 替换为实际图片路径
-      },
-      {
-        name: "Deep Wave Wig 100 Human Hair Swiss Lace Wig Lace Front Wig",
-        specs: "10, Medium, 100%",
-        price: "$252.00x1",
-        image: "",
-      },
-      {
-        name: "Braids Wig Blonde Barbie Pre-Styled Highlight Wig 13×4 Front Wig",
-        specs: "12",
-        price: "6000 points + $279.32x1",
-        image:
-          "https://cdn.alipearlhair.com/media/catalog/product/cache/6/thumbnail/750x1000/9df78eab33525d08d6e5fb8d27136e95/b/o/body_wave_lace_front_wig_2.jpg", // 替换为实际图片路径
-      },
-      {
-        name: "random free wigs-2",
-        specs: "",
-        price: "$0.00x1",
-        image: "",
-      },
-    ],
-    progress: "Preparing Order",
-    discount: "-$80.00",
-    total: "$872.78",
-  },
-];
+// const mockOrders = [
+//   {
+//     id: 600217097,
+//     date: "3/4/2026",
+//     status: "Processing",
+//     items: [
+//       {
+//         name: "Highlight Wigs For Women Headband Wigs with Blonde Highlights",
+//         specs: "10, #022, Straight, 5 Free Headbands",
+//         price: "88 points + $154.05x1",
+//         image: "",
+//       },
+//     ],
+//     progress: "Preparing Order",
+//     total: "88 Points + $158.67",
+//   },
+//   {
+//     id: 100055662,
+//     date: "3/3/2026",
+//     status: "Processing",
+//     items: [
+//       {
+//         name: "Alipearl Lace Front Wig 180% Density Body Wave Human Hair Wigs Pre...",
+//         specs: "10+180%, Medium, No Adjustable Band",
+//         price: "$128.82x1",
+//         image: "",
+//       },
+//     ],
+//     progress: "Preparing Order",
+//     total: "$132.68",
+//   },
+//   {
+//     id: 600217055,
+//     date: "3/3/2026",
+//     status: "Processing",
+//     items: [
+//       {
+//         name: "3 Bundles Deep Wave Hair With 4*4 Lace Closure Alipearl Brazilian Hair",
+//         specs: "8 8 8, Free Part, 8",
+//         price: "$142.14x1",
+//         image: "",
+//       },
+//       {
+//         name: "Princess Braids Wig Blonde Barbie Pre-Styled Highlight Wig 13×4 Front Wig",
+//         specs: "12",
+//         price: "$279.32x1",
+//         image:
+//           "https://cdn.alipearlhair.com/media/catalog/product/cache/6/thumbnail/750x1000/9df78eab33525d08d6e5fb8d27136e95/b/o/body_wave_lace_front_wig_2.jpg", // 替换为实际图片路径
+//       },
+//       {
+//         name: "Deep Wave Wig 100 Human Hair Swiss Lace Wig Lace Front Wig",
+//         specs: "10, Medium, 100%",
+//         price: "$252.00x1",
+//         image: "",
+//       },
+//       {
+//         name: "Braids Wig Blonde Barbie Pre-Styled Highlight Wig 13×4 Front Wig",
+//         specs: "12",
+//         price: "6000 points + $279.32x1",
+//         image:
+//           "https://cdn.alipearlhair.com/media/catalog/product/cache/6/thumbnail/750x1000/9df78eab33525d08d6e5fb8d27136e95/b/o/body_wave_lace_front_wig_2.jpg", // 替换为实际图片路径
+//       },
+//       {
+//         name: "random free wigs-2",
+//         specs: "",
+//         price: "$0.00x1",
+//         image: "",
+//       },
+//     ],
+//     progress: "Preparing Order",
+//     discount: "-$80.00",
+//     total: "$872.78",
+//   },
+// ];
 
 // 标签列表
 const tabs = [
@@ -112,11 +112,11 @@ export default function OrderHistory() {
       const resp = await clientFetch(
         `/api/customer/orders?page=${page}&limit=${PAGE_SIZE}&status=${tabKey}`,
       );
-      let records = resp.data.records ?? [];
+      const records = resp.data ?? [];
       setTotal(resp.data.total ?? 0);
       // 模拟数据后面换成真正的接口数据
-      setTotal(100);
-      records = mockOrders; //
+      // setTotal(100);
+      // records = mockOrders; //
       if (isLoadMore) {
         setFilteredOrders((prev) => [...prev, ...records]);
       } else {

+ 3 - 1
src/app/(public)/customer/order/view/order_id/[id]/_components/ProductList.tsx

@@ -106,7 +106,9 @@ export default function ProductList({ orderData }: Props) {
                   className="
                     text-[14px]
                     leading-[20px]
-                    text-black
+                  text-black
+                    line-clamp-2
+                    overflow-hidden
                   "
                 >
                   {item.name}

+ 2 - 2
src/app/(public)/customer/order/view/order_id/[id]/page.tsx

@@ -14,8 +14,8 @@ type Params = {
 export default async function OrderDetail({ params }: { params: Params }) {
   // 解包拿到真实订单ID
   const realParams = await params;
-  let orderId = realParams.id;
-  orderId = '881900125';
+  const orderId = realParams.id;
+  // orderId = '881900125';
   console.log("orderId:", orderId);
 
   // 2. 服务端 fetch 请求我们自己的 Next.js API

+ 1 - 1
src/app/(public)/product/[urlkey]/[id]/page.tsx

@@ -180,7 +180,7 @@ export default async function ProductPage({
 
          <ProductDescription   htmlString={product?.feature || ""} />
           <SwitchButton
-            productId={"3792"} //|| String(product._id)
+            productId={String(product._id)} //|| 
 
             questionTotal={questionTotal}
             questionList={["aaa"]}

+ 3 - 0
src/app/(public)/product/_components/ProductReviewSection.tsx

@@ -11,6 +11,7 @@ interface ProductReviewSectionProps {
   onOpenBaseModal: () => void;
   activeTab: string;
   onChangeTab: (tabKey: string) => void;
+  openGalleryModal: (clickReviewIndex: number, clickImgIndex: number) => void;
 }
 
 function ProductReviewSection({
@@ -21,6 +22,7 @@ function ProductReviewSection({
   activeTab,
   onOpenBaseModal,
   onChangeTab,
+  openGalleryModal
 }: ProductReviewSectionProps) {
 
   return (
@@ -37,6 +39,7 @@ function ProductReviewSection({
               onClose={closeModal}
               activeTab={activeTab}
               onChangeTab={onChangeTab} // 关键:把切换tab的函数传给弹窗
+              openGalleryModal={openGalleryModal}
             />
           </>
         ) : (

File diff ditekan karena terlalu besar
+ 155 - 4
src/app/(public)/product/_components/SwitchButton.tsx


+ 2 - 0
src/app/(public)/product/_components/review/ReviewAdd.tsx

@@ -19,6 +19,7 @@ export default function ReviewAdd({ productId }: { productId: string }) {
     <>
       <div className="flex items-center justify-start gap-3">
         <ReviewButton setShowForm={setShowForm} />
+        { false &&
         <div
           onClick={() => {
             setOpen(() => false);
@@ -28,6 +29,7 @@ export default function ReviewAdd({ productId }: { productId: string }) {
         >
           Ask a question
         </div>
+        }
       </div>
       {/* 页面内表单区块,非弹窗 */}
       {open && (

+ 42 - 4
src/app/(public)/product/_components/review/ReviewDetail.tsx

@@ -16,6 +16,9 @@ import ReviewModal from "./ReviewModal";
 import { useCustomToast } from "@utils/hooks/useToast";
 import { clientFetch } from "@/lib/restApiClient";
 import { getUuId } from "@/utils/helper";
+import { Select, SelectItem } from "@heroui/select";
+
+type ReviewTabType = "all" | "newest" | "photos";
 
 interface ReviewDetailProps {
   reviewDetails: ProductReviewNode[];
@@ -26,6 +29,7 @@ interface ReviewDetailProps {
   activeTab: string;
   onChangeTab: (tabKey: string) => void;
   onOpenBaseModal: () => void;
+  openGalleryModal: (clickReviewIndex: number, clickImgIndex: number) => void;
 }
 
 const ReviewDetail: FC<ReviewDetailProps> = ({
@@ -37,9 +41,10 @@ const ReviewDetail: FC<ReviewDetailProps> = ({
   activeTab,
   onChangeTab,
   onOpenBaseModal,
+  openGalleryModal
 }) => {
  
-
+  // const [currentActiveTab, setCurrentActiveTab] = useState<ReviewTabType>("newest");
   const { showToast } = useCustomToast();
   const [localLikeMap, setLocalLikeMap] = useState<
     Record<string, { liked: boolean; like_count: number }>
@@ -52,9 +57,18 @@ const ReviewDetail: FC<ReviewDetailProps> = ({
       like_count: item.like_count,
     };
   };
+  // 选项映射
+const tabOptions: { key: ReviewTabType; label: string }[] = [
+  { key: "all", label: "ALL" },
+  { key: "newest", label: "Newest" },
+  { key: "photos", label: "Photos" },
+];
 
-
-
+const handleTabClick = (tab: ReviewTabType) => {
+  // setCurrentActiveTab(tab);
+  onChangeTab(tab);
+  // 这里写:请求接口、重置页码等逻辑
+};
   const visibleReviews = reviewDetails.slice(0, 5);
   console.log("visibleReviews-------------------:", visibleReviews);
 
@@ -119,6 +133,29 @@ const ReviewDetail: FC<ReviewDetailProps> = ({
   return (
     <>
       <div className="flex flex-col flex-wrap gap-x-5 sm:gap-x-10">
+        <div className="flex items-center justify-between">
+          <h3 className="text-xl font-medium">Reviews</h3>
+          <Select
+            selectionMode="single"
+            classNames={{
+              trigger: "border-none shadow-none px-0   max-w-[100px] pl-3",
+              value: "text-sm",
+            }}
+            // selectedKeys={new Set([currentActiveTab])}
+            selectedKeys={new Set([activeTab])}
+           onSelectionChange={(keys) => {
+             const tab = Array.from(keys)[0] as ReviewTabType;
+             handleTabClick(tab);
+           }}
+            variant="flat"
+          >
+            {tabOptions.map((item) => (
+              <SelectItem key={item.key}>
+                {item.label}
+              </SelectItem>
+            ))}
+          </Select>
+        </div>
         <div className="my-2 flex w-full flex-col flex-wrap justify-between gap-4 sm:flex-row sm:items-center min-[1350px]:flex-nowrap">
           <div className="flex items-center gap-x-2">
             {/* <Rating
@@ -297,9 +334,10 @@ const ReviewDetail: FC<ReviewDetailProps> = ({
                     item.attachments &&
                     item.attachments.length > 0 && (
                       <div className="mt-4 pl-[56px] flex gap-3 flex-wrap">
-                        {item.attachments.map((img: any) => (
+                        {item.attachments.map((img: any,imgIdx:number) => (
                           <div
                             key={img.reviewId}
+                            onClick={() => openGalleryModal(index, imgIdx)}
                             className="w-[160px] h-[160px] rounded-lg overflow-hidden shrink-0 border border-[#E5E5E5FF]"
                           >
                             <GridTileImage

File diff ditekan karena terlalu besar
+ 12 - 6
src/app/(public)/product/_components/review/ReviewImageGalleryModal.tsx


+ 3 - 2
src/app/(public)/product/_components/review/ReviewModal.tsx

@@ -193,7 +193,7 @@ const ReviewModal: React.FC<ReviewModalProps> = React.memo(
       const targetReview: any = filterReviewList()[clickReviewIndex];
       const targetImg = targetReview.attachments[clickImgIndex];
       const targetSlide = galleryAll.findIndex(
-        (g) => g.reviewIndex === clickReviewIndex && g.imageUrl === targetImg,
+        (g) => g.imageUrl === targetImg.url,
       );
       setGalleryData({ galleryList: galleryAll, initialSlide: targetSlide });
       setGalleryOpen(true);
@@ -271,7 +271,7 @@ const ReviewModal: React.FC<ReviewModalProps> = React.memo(
     return (
       <>
         {/* 遮罩层 */}
-        <div className="fixed inset-0 bg-black/60 z-[90] flex items-center justify-center ">
+        <div className="fixed inset-0 bg-black/60 z-[1001] flex items-center justify-center ">
           <div className="w-full max-w-3xl h-full bg-white flex flex-col overflow-hidden">
             {/* 顶部固定头部:返回 + Reviews标题 */}
             <div className="flex items-center justify-between p-4 border-b border-gray-200 shrink-0">
@@ -485,6 +485,7 @@ const ReviewModal: React.FC<ReviewModalProps> = React.memo(
 
         {/* 图片预览弹窗 完全不变 */}
         <ReviewImageGalleryModal
+          key={galleryData.initialSlide}
           open={galleryOpen}
           onClose={() => setGalleryOpen(false)}
           galleryList={galleryData.galleryList}

+ 1 - 1
src/components/layout/navbar/NavbarSearchIcon.tsx

@@ -11,7 +11,7 @@ export default function NavbarSearchIcon() {
         setSearchOpen(false);
       });
     }
-  }, [pathname, searchOpen]);
+  }, [pathname]);
   return (
     <>
       <div