fix: 修复商品批量删除与恢复

This commit is contained in:
hh
2026-07-13 14:31:26 +08:00
parent f803948143
commit bd3b484fde
4 changed files with 258 additions and 12 deletions
+36 -9
View File
@@ -22,6 +22,11 @@ type TrashSection = {
rows: TrashRow[];
};
type ProductBatchResult = {
succeededIds: string[];
failedIds: string[];
};
const mediaStyle = (url: string): CSSProperties => ({ ["--mock-media-url"]: `url(${url})` } as CSSProperties);
const dateOf = (iso?: string | null): string => {
@@ -94,10 +99,12 @@ const rowsFromProjects = (items: Project[]): TrashRow[] =>
cover: p.cover_preview_url || ""
}));
export function TrashPage({ onRestore, onPurge, onChanged }: {
export function TrashPage({ onRestore, onPurge, onRestoreProducts, onPurgeProducts, onChanged }: {
navigate: NavigateFn;
onRestore: (id: string) => Promise<unknown> | void;
onPurge: (id: string) => Promise<unknown> | void;
onRestoreProducts: (ids: string[]) => Promise<ProductBatchResult>;
onPurgeProducts: (ids: string[]) => Promise<ProductBatchResult>;
onChanged?: () => void;
}) {
const [sections, setSections] = useState<TrashSection[]>([]);
@@ -224,16 +231,26 @@ export function TrashPage({ onRestore, onPurge, onChanged }: {
setBulkBusy("restore");
setErrText("");
const rows = [...allRows];
const results = await Promise.allSettled(rows.map((row) => restoreRow(row)));
const failed = new Set(rows.filter((_, i) => results[i].status === "rejected").map(rowKey));
const productRows = rows.filter((row) => row.kind === "product");
const otherRows = rows.filter((row) => row.kind !== "product");
const [productResult, otherResults] = await Promise.all([
productRows.length
? onRestoreProducts(productRows.map((row) => row.id))
: Promise.resolve<ProductBatchResult>({ succeededIds: productRows.map((row) => row.id), failedIds: [] }),
Promise.allSettled(otherRows.map((row) => restoreRow(row)))
]);
const failed = new Set([
...productResult.failedIds.map((id) => `product:${id}`),
...otherRows.filter((_, index) => otherResults[index].status === "rejected").map(rowKey)
]);
setSections((list) =>
list
.map((section) => ({ ...section, rows: section.rows.filter((row) => failed.has(rowKey(row))) }))
.filter((section) => section.rows.length > 0)
);
const firstFail = results.find((r): r is PromiseRejectedResult => r.status === "rejected");
const firstFail = otherResults.find((r): r is PromiseRejectedResult => r.status === "rejected");
if (firstFail) setErrText(firstFail.reason instanceof Error ? firstFail.reason.message : "部分恢复失败");
if (results.some((r) => r.status === "fulfilled")) onChanged?.();
if (productResult.succeededIds.length || otherResults.some((r) => r.status === "fulfilled")) onChanged?.();
setBulkBusy(null);
}
@@ -242,16 +259,26 @@ export function TrashPage({ onRestore, onPurge, onChanged }: {
setBulkBusy("purge");
setErrText("");
const rows = [...allRows];
const results = await Promise.allSettled(rows.map((row) => purgeRow(row)));
const failed = new Set(rows.filter((_, i) => results[i].status === "rejected").map(rowKey));
const productRows = rows.filter((row) => row.kind === "product");
const otherRows = rows.filter((row) => row.kind !== "product");
const [productResult, otherResults] = await Promise.all([
productRows.length
? onPurgeProducts(productRows.map((row) => row.id))
: Promise.resolve<ProductBatchResult>({ succeededIds: productRows.map((row) => row.id), failedIds: [] }),
Promise.allSettled(otherRows.map((row) => purgeRow(row)))
]);
const failed = new Set([
...productResult.failedIds.map((id) => `product:${id}`),
...otherRows.filter((_, index) => otherResults[index].status === "rejected").map(rowKey)
]);
setSections((list) =>
list
.map((section) => ({ ...section, rows: section.rows.filter((row) => failed.has(rowKey(row))) }))
.filter((section) => section.rows.length > 0)
);
const firstFail = results.find((r): r is PromiseRejectedResult => r.status === "rejected");
const firstFail = otherResults.find((r): r is PromiseRejectedResult => r.status === "rejected");
if (firstFail) setErrText(firstFail.reason instanceof Error ? firstFail.reason.message : "部分删除失败");
if (results.some((r) => r.status === "fulfilled")) onChanged?.();
if (productResult.succeededIds.length || otherResults.some((r) => r.status === "fulfilled")) onChanged?.();
setBulkBusy(null);
}