|
@@ -1,7 +1,8 @@
|
|
|
"use client";
|
|
"use client";
|
|
|
-import { useEffect, useState } from "react";
|
|
|
|
|
|
|
+import { useEffect, useState, useRef, useCallback } from "react";
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useRouter } from "next/navigation";
|
|
|
import Link from "next/link";
|
|
import Link from "next/link";
|
|
|
|
|
+import { useSearchParams } from "next/navigation";
|
|
|
|
|
|
|
|
// 模拟订单数据
|
|
// 模拟订单数据
|
|
|
const mockOrders = [
|
|
const mockOrders = [
|
|
@@ -86,29 +87,9 @@ export default function OrderHistory() {
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const [activeTab, setActiveTab] = useState("all");
|
|
const [activeTab, setActiveTab] = useState("all");
|
|
|
const [filteredOrders, setFilteredOrders] = useState(mockOrders);
|
|
const [filteredOrders, setFilteredOrders] = useState(mockOrders);
|
|
|
-
|
|
|
|
|
- // 监听URL哈希值,初始化选中标签
|
|
|
|
|
- useEffect(() => {
|
|
|
|
|
- const hash = window.location.hash.slice(1) || "all"; // 解析 #all -> all
|
|
|
|
|
- const validTab = tabs.find((t) => t.key === hash.toLowerCase());
|
|
|
|
|
- setActiveTab(validTab ? validTab.key : "all");
|
|
|
|
|
-
|
|
|
|
|
- // 模拟接口请求:根据标签传不同参数(实际项目替换为真实接口)
|
|
|
|
|
- fetchOrders(validTab ? validTab.key : "all");
|
|
|
|
|
-
|
|
|
|
|
- // 监听哈希变化
|
|
|
|
|
- const handleHashChange = () => {
|
|
|
|
|
- const newHash = window.location.hash.slice(1) || "all";
|
|
|
|
|
- const validNewTab = tabs.find((t) => t.key === newHash.toLowerCase());
|
|
|
|
|
- if (validNewTab) {
|
|
|
|
|
- setActiveTab(validNewTab.key);
|
|
|
|
|
- fetchOrders(validNewTab.key);
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- window.addEventListener("hashchange", handleHashChange);
|
|
|
|
|
- return () => window.removeEventListener("hashchange", handleHashChange);
|
|
|
|
|
- }, []);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ // 组件内新增
|
|
|
|
|
+ const searchParams = useSearchParams();
|
|
|
|
|
+ const lastHashRef = useRef<string>("");
|
|
|
// 模拟接口请求:不同标签传不同参数
|
|
// 模拟接口请求:不同标签传不同参数
|
|
|
const fetchOrders = (tabKey: string) => {
|
|
const fetchOrders = (tabKey: string) => {
|
|
|
console.log("请求接口参数:", tabKey); // 实际项目替换为真实接口调用
|
|
console.log("请求接口参数:", tabKey); // 实际项目替换为真实接口调用
|
|
@@ -121,22 +102,44 @@ export default function OrderHistory() {
|
|
|
setFilteredOrders(mockOrders);
|
|
setFilteredOrders(mockOrders);
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
+ // 把更新状态+请求的逻辑抽离,Effect 只调用这个函数,不直接写setState
|
|
|
|
|
+ const updateTabByHash = useCallback(
|
|
|
|
|
+ (hashKey: string) => {
|
|
|
|
|
+ const validTab = tabs.find((t) => t.key === hashKey.toLowerCase());
|
|
|
|
|
+ const targetKey = validTab ? validTab.key : "all";
|
|
|
|
|
+ // setState 全部放在回调函数里,不在 useEffect 顶层同步执行
|
|
|
|
|
+ setActiveTab(targetKey);
|
|
|
|
|
+ fetchOrders(targetKey);
|
|
|
|
|
+ },
|
|
|
|
|
+ [tabs, fetchOrders],
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 监听哈希变化,Effect 内部无任何直接setState
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const currentHash = searchParams.get("") || "all";
|
|
|
|
|
+ // 对比上一次缓存的hash,避免重复执行
|
|
|
|
|
+ if (lastHashRef.current !== currentHash) {
|
|
|
|
|
+ lastHashRef.current = currentHash;
|
|
|
|
|
+ // 仅调用抽离好的函数,Effect内部没有setActiveTab
|
|
|
|
|
+ updateTabByHash(currentHash);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [searchParams, updateTabByHash]);
|
|
|
|
|
|
|
|
// 点击标签切换
|
|
// 点击标签切换
|
|
|
const handleTabClick = (tabKey: string) => {
|
|
const handleTabClick = (tabKey: string) => {
|
|
|
- window.location.hash = tabKey; // 更新URL哈希
|
|
|
|
|
|
|
+ // window.location.hash = tabKey; // 更新URL哈希
|
|
|
|
|
+ router.push(`#${tabKey}`, { scroll: false });
|
|
|
setActiveTab(tabKey);
|
|
setActiveTab(tabKey);
|
|
|
fetchOrders(tabKey);
|
|
fetchOrders(tabKey);
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
<div className="min-h-screen bg-gray-50">
|
|
<div className="min-h-screen bg-gray-50">
|
|
|
{/* 顶部返回栏 + 标题 */}
|
|
{/* 顶部返回栏 + 标题 */}
|
|
|
- <div className="sticky top-0 z-20 bg-white px-4 py-3 border-b flex justify-between items-center w-full">
|
|
|
|
|
|
|
+ <Link href={"/customer/account"} className="sticky top-0 z-20 bg-white px-4 py-3 border-b flex justify-between items-center w-full">
|
|
|
<button className="text-black text-xl mr-4">
|
|
<button className="text-black text-xl mr-4">
|
|
|
<svg
|
|
<svg
|
|
|
-
|
|
|
|
|
className="w-6 h-6"
|
|
className="w-6 h-6"
|
|
|
viewBox="0 0 1024 1024"
|
|
viewBox="0 0 1024 1024"
|
|
|
version="1.1"
|
|
version="1.1"
|
|
@@ -153,7 +156,7 @@ export default function OrderHistory() {
|
|
|
</button>
|
|
</button>
|
|
|
<h1 className="text-xl font-bold mx-auto">Orders</h1>
|
|
<h1 className="text-xl font-bold mx-auto">Orders</h1>
|
|
|
<div className="w-6"></div>
|
|
<div className="w-6"></div>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </Link>
|
|
|
|
|
|
|
|
{/* 标签栏(固定顶部 + 横向滚动) */}
|
|
{/* 标签栏(固定顶部 + 横向滚动) */}
|
|
|
<div className="sticky top-14 z-10 bg-white px-4 py-2 border-b">
|
|
<div className="sticky top-14 z-10 bg-white px-4 py-2 border-b">
|
|
@@ -183,7 +186,6 @@ export default function OrderHistory() {
|
|
|
</div>
|
|
</div>
|
|
|
) : (
|
|
) : (
|
|
|
filteredOrders.map((order) => (
|
|
filteredOrders.map((order) => (
|
|
|
-
|
|
|
|
|
<div
|
|
<div
|
|
|
key={order.id}
|
|
key={order.id}
|
|
|
className="bg-white rounded-lg p-4 mb-4 border"
|
|
className="bg-white rounded-lg p-4 mb-4 border"
|
|
@@ -230,7 +232,10 @@ export default function OrderHistory() {
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
{/* 订单进度条 */}
|
|
{/* 订单进度条 */}
|
|
|
- <Link href={`/customer/order/track/order_id/${order.id}`} className="mb-4 h-8 bg-gray-100 rounded-full h-2 flex items-center px-2">
|
|
|
|
|
|
|
+ <Link
|
|
|
|
|
+ href={`/customer/order/track/order_id/${order.id}`}
|
|
|
|
|
+ className="mb-4 h-8 bg-gray-100 rounded-full h-2 flex items-center px-2"
|
|
|
|
|
+ >
|
|
|
<span className="ml-2 text-xs text-gray-700 flex-1 flex justify-between">
|
|
<span className="ml-2 text-xs text-gray-700 flex-1 flex justify-between">
|
|
|
{order.progress}
|
|
{order.progress}
|
|
|
<span>
|
|
<span>
|
|
@@ -258,7 +263,7 @@ export default function OrderHistory() {
|
|
|
<p className="text-red-500 flex items-center justify-between">
|
|
<p className="text-red-500 flex items-center justify-between">
|
|
|
<span>Discount</span> <span>{order.discount}</span>
|
|
<span>Discount</span> <span>{order.discount}</span>
|
|
|
</p>
|
|
</p>
|
|
|
- )}
|
|
|
|
|
|
|
+ )}
|
|
|
<p className="font-bold mt-1 flex items-center justify-between">
|
|
<p className="font-bold mt-1 flex items-center justify-between">
|
|
|
<span>
|
|
<span>
|
|
|
Order Total ({order.items.length} item
|
|
Order Total ({order.items.length} item
|
|
@@ -268,10 +273,21 @@ export default function OrderHistory() {
|
|
|
</p>
|
|
</p>
|
|
|
|
|
|
|
|
<div className="flex justify-between mt-3">
|
|
<div className="flex justify-between mt-3">
|
|
|
- <Link href={`/customer/order/view/order_id/${order.id}`} className="text-black-600 text-sm underline">
|
|
|
|
|
|
|
+ <Link
|
|
|
|
|
+ href={`/customer/order/view/order_id/${order.id}`}
|
|
|
|
|
+ className="text-black-600 text-sm underline"
|
|
|
|
|
+ >
|
|
|
View Order
|
|
View Order
|
|
|
</Link>
|
|
</Link>
|
|
|
- <Link href={`/customer/order/track/order_id/${order.id}`} state={{ addressData: { /* 你的地址对象 */ } }} className="border border-gray-300 rounded-full px-4 py-1 text-sm text-gray-800 hover:bg-gray-50">
|
|
|
|
|
|
|
+ <Link
|
|
|
|
|
+ href={`/customer/order/track/order_id/${order.id}`}
|
|
|
|
|
+ state={{
|
|
|
|
|
+ addressData: {
|
|
|
|
|
+ /* 你的地址对象 */
|
|
|
|
|
+ },
|
|
|
|
|
+ }}
|
|
|
|
|
+ className="border border-gray-300 rounded-full px-4 py-1 text-sm text-gray-800 hover:bg-gray-50"
|
|
|
|
|
+ >
|
|
|
Track Order
|
|
Track Order
|
|
|
</Link>
|
|
</Link>
|
|
|
</div>
|
|
</div>
|