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