|
|
@@ -5,11 +5,12 @@ import Image from "next/image";
|
|
|
import ReviewAdd from "@/app/(public)/product/_components/review/ReviewAdd";
|
|
|
import FaqList, { FaqItem } from "./question/FaqList";
|
|
|
import HairPhotoGallery from "./review/HairPhotoGallery";
|
|
|
+import { clientFetch } from "@/lib/restApiClient";
|
|
|
interface ReviewQuestionTabProps {
|
|
|
productId: string;
|
|
|
questionList: any[];
|
|
|
- reviewList: any[]; // 替换为你的 ProductReviewList 类型
|
|
|
- reviewTotal: number; // 评论总数 (allReviews.length)
|
|
|
+ // reviewList: any[]; // 替换为你的 ProductReviewList 类型
|
|
|
+ // reviewTotal: number; // 评论总数 (allReviews.length)
|
|
|
questionTotal: number; // 问答总数,后端接口获取
|
|
|
}
|
|
|
// 模拟截图内FAQ数据
|
|
|
@@ -45,14 +46,66 @@ const mockFaqData: FaqItem[] = [
|
|
|
];
|
|
|
export default function SwitchButton({
|
|
|
productId,
|
|
|
- reviewList,
|
|
|
questionList,
|
|
|
- reviewTotal,
|
|
|
questionTotal,
|
|
|
}: ReviewQuestionTabProps) {
|
|
|
+ // const [uuid, setUuidId] = useState<string>('');
|
|
|
+ // 自己通过接口拿到,不再由父组件传入
|
|
|
+ const [reviewList, setReviewList] = useState<any[]>([]);
|
|
|
+ const [reviewTotal, setReviewTotal] = useState<number>(0);
|
|
|
+ // 获取/生成访客UUID
|
|
|
+ const getUuId = () => {
|
|
|
+ const key = "GUEST_UUID";
|
|
|
+ let id = localStorage.getItem(key);
|
|
|
+ if (!id) {
|
|
|
+ id = crypto.randomUUID();
|
|
|
+ localStorage.setItem(key, id);
|
|
|
+ }
|
|
|
+ return id;
|
|
|
+ };
|
|
|
+ // 组件顶层,只生成一次uuid
|
|
|
+const [clientUuid] = useState(() => getUuId());
|
|
|
+ useEffect(() => {
|
|
|
+ if (!productId) return;
|
|
|
+ // 1. 请求中断控制器,组件卸载时取消网络请求,防止卸载后执行setState
|
|
|
+ const abortCtrl = new AbortController();
|
|
|
+ const signal = abortCtrl.signal;
|
|
|
+
|
|
|
+ // uuid 只初始化生成一次,存ref,不需要触发渲染
|
|
|
+
|
|
|
+
|
|
|
+ const fetchReviews = async () => {
|
|
|
+ try {
|
|
|
+ const res = await clientFetch(
|
|
|
+ `/api/shop/products/${productId}/reviews?page=1&per_page=10&has_images=0&sort=all&client_id=${clientUuid}`,
|
|
|
+ { signal } // 绑定中断信号
|
|
|
+ );
|
|
|
+ console.log('res------------------------------ccc:',res);
|
|
|
+
|
|
|
+ if (res.data.success) {
|
|
|
+ setReviewList(res?.data?.data ?? []);
|
|
|
+ setReviewTotal(res?.pagination?.total ?? 0);
|
|
|
+ }
|
|
|
+ } catch (err: any) {
|
|
|
+ // 手动取消的请求不需要打印报错
|
|
|
+ if (err.name !== "AbortError") {
|
|
|
+ console.error("获取评论失败", err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ fetchReviews();
|
|
|
+
|
|
|
+ // useEffect清理函数:组件卸载,终止请求
|
|
|
+ return () => {
|
|
|
+ abortCtrl.abort();
|
|
|
+ };
|
|
|
+}, [productId]);
|
|
|
+
|
|
|
+
|
|
|
// 切换状态:默认激活评论
|
|
|
const [activeTab, setActiveTab] = useState<"review" | "question">("review");
|
|
|
- // 提前计算空状态,减少模板内嵌套
|
|
|
+ // 提前计算空状态,减少模板内嵌套
|
|
|
const isEmptyReview = useMemo(() => reviewList.length === 0, [reviewList]);
|
|
|
const isEmptyQuestion = useMemo(
|
|
|
() => questionList.length === 0,
|
|
|
@@ -147,6 +200,7 @@ export default function SwitchButton({
|
|
|
onOpenBaseModal={openAllReviewModal}
|
|
|
activeTab={activeModalTab}
|
|
|
onChangeTab={onTabChange}
|
|
|
+ uuid={clientUuid}
|
|
|
/>
|
|
|
)
|
|
|
) : isEmptyQuestion ? (
|