perf: 流转树排他展开(手风琴模式)-同时只展开一个产品
This commit is contained in:
@ -47,8 +47,8 @@ export default function AdminTasksPage() {
|
||||
// 手风琴展开状态
|
||||
const [expandedOrders, setExpandedOrders] = useState<Set<string>>(new Set());
|
||||
|
||||
// 任务树展开
|
||||
const [expandedProducts, setExpandedProducts] = useState<Set<string>>(new Set());
|
||||
// 🔧 排他展开:同时只展开一个产品的流转树
|
||||
const [activeTreeProductId, setActiveTreeProductId] = useState<string | null>(null);
|
||||
const [taskTrees, setTaskTrees] = useState<Record<string, ProductScanResponse | null>>({});
|
||||
const [treeLoading, setTreeLoading] = useState<Record<string, boolean>>({});
|
||||
|
||||
@ -121,38 +121,22 @@ export default function AdminTasksPage() {
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 任务树展开/收起 ----
|
||||
// ---- 排他展开(手风琴模式) ----
|
||||
async function toggleProductTree(serialNumber: string) {
|
||||
setExpandedProducts((prev) => {
|
||||
const next = new Set(prev);
|
||||
if (next.has(serialNumber)) {
|
||||
next.delete(serialNumber);
|
||||
return next;
|
||||
}
|
||||
// 加载任务树
|
||||
next.add(serialNumber);
|
||||
if (!taskTrees[serialNumber]) {
|
||||
setTreeLoading((s) => ({ ...s, [serialNumber]: true }));
|
||||
scanProduct(serialNumber)
|
||||
.then((result) => {
|
||||
setTaskTrees((s) => ({ ...s, [serialNumber]: result }));
|
||||
})
|
||||
.catch((err: any) => {
|
||||
const msg =
|
||||
err?.response?.data?.detail ?? err?.message ?? "加载任务树失败";
|
||||
toast(msg, "error");
|
||||
setExpandedProducts((prev2) => {
|
||||
const n2 = new Set(prev2);
|
||||
n2.delete(serialNumber);
|
||||
return n2;
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setTreeLoading((s) => ({ ...s, [serialNumber]: false }));
|
||||
});
|
||||
}
|
||||
return next;
|
||||
});
|
||||
// 点击已展开的树 → 收起
|
||||
if (activeTreeProductId === serialNumber) {
|
||||
setActiveTreeProductId(null);
|
||||
return;
|
||||
}
|
||||
// 展开新的 → 自动收起旧的
|
||||
setActiveTreeProductId(serialNumber);
|
||||
if (!taskTrees[serialNumber]) {
|
||||
setTreeLoading((s) => ({ ...s, [serialNumber]: true }));
|
||||
scanProduct(serialNumber)
|
||||
.then((result) => setTaskTrees((s) => ({ ...s, [serialNumber]: result })))
|
||||
.catch((err: any) => toast(err?.response?.data?.detail ?? err?.message ?? "加载任务树失败", "error"))
|
||||
.finally(() => setTreeLoading((s) => ({ ...s, [serialNumber]: false })));
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 任务操作 ----
|
||||
@ -378,7 +362,7 @@ export default function AdminTasksPage() {
|
||||
|
||||
{/* 产品行 */}
|
||||
{group.products.map((p) => {
|
||||
const productExpanded = expandedProducts.has(p.serial_number);
|
||||
const productExpanded = activeTreeProductId === p.serial_number;
|
||||
const isTreeLoading = treeLoading[p.serial_number];
|
||||
const tree = taskTrees[p.serial_number];
|
||||
// 综合状态:优先流转树状态,兜底产品状态
|
||||
|
||||
Reference in New Issue
Block a user