fix: 修复素材库批量删除后白屏崩溃 #509

Merged
xiaoxia merged 2 commits from fix/asset-batch-delete-crash into develop 2026-07-18 15:21:04 +08:00
2 changed files with 31 additions and 6 deletions
Regular → Executable
+23 -4
View File
@@ -390,6 +390,25 @@ export interface BatchOperationResult {
failure_count: number;
}
/** 统一批量操作结果归一化,防御后端字段缺失或格式不一致 */
const normalizeBatchResult = (
raw: Record<string, unknown>,
): BatchOperationResult => {
const succeeded = Array.isArray(raw.succeeded)
? (raw.succeeded as string[])
: [];
const failed = Array.isArray(raw.failed) ? (raw.failed as string[]) : [];
const success_count =
typeof raw.success_count === "number"
? raw.success_count
: succeeded.length;
const failure_count =
typeof raw.failure_count === "number" ? raw.failure_count : failed.length;
const total =
typeof raw.total === "number" ? raw.total : success_count + failure_count;
return { succeeded, failed, total, success_count, failure_count };
};
/** 批量删除素材 */
export const batchDeleteAssets = async (
assetIds: string[],
@@ -397,7 +416,7 @@ export const batchDeleteAssets = async (
const response = await apiClient.post("/assets/batch-delete", {
asset_ids: assetIds,
});
return response.data;
return normalizeBatchResult((response.data || {}) as Record<string, unknown>);
};
/** 批量打标签 */
@@ -407,7 +426,7 @@ export const batchTagAssets = async (data: {
mode: "add" | "replace";
}): Promise<BatchOperationResult> => {
const response = await apiClient.post("/assets/batch-tag", data);
return response.data;
return normalizeBatchResult((response.data || {}) as Record<string, unknown>);
};
/** 批量改分类 */
@@ -416,7 +435,7 @@ export const batchClassifyAssets = async (data: {
category: string;
}): Promise<BatchOperationResult> => {
const response = await apiClient.post("/assets/batch-classify", data);
return response.data;
return normalizeBatchResult((response.data || {}) as Record<string, unknown>);
};
/** 批量智能标记 */
@@ -425,5 +444,5 @@ export const batchMarkAssets = async (data: {
smart_view: "recommended" | "caution" | "high_risk";
}): Promise<BatchOperationResult> => {
const response = await apiClient.post("/assets/batch-mark", data);
return response.data;
return normalizeBatchResult((response.data || {}) as Record<string, unknown>);
};
+8 -2
View File
@@ -355,7 +355,10 @@ const AssetLibrary: React.FC = () => {
staleTime: 60_000,
});
const libraries = useMemo(() => apiLibraries.map(mapLibrary), [apiLibraries]);
const libraries = useMemo(
() => (Array.isArray(apiLibraries) ? apiLibraries : []).map(mapLibrary),
[apiLibraries],
);
/* ── 当前选中的素材库 ── */
const [activeLibId, setActiveLibId] = useState<string>("");
@@ -377,7 +380,10 @@ const AssetLibrary: React.FC = () => {
staleTime: 30_000,
});
const assets = useMemo(() => apiAssets.map(mapAsset), [apiAssets]);
const assets = useMemo(
() => (Array.isArray(apiAssets) ? apiAssets : []).map(mapAsset),
[apiAssets],
);
/* ── Mutations ── */
const createLibMutation = useMutation({