fix(P0): 全面修复删除后白屏崩溃 - 4个页面加防御性检查 (#525)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Successful in 1m19s
CI Build & Deploy Pipeline / Build Staging Web Image (push) Successful in 1m59s
CI Build & Deploy Pipeline / Build Production API Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Worker Image (push) Has been skipped
CI Build & Deploy Pipeline / Build Production Web Image (push) Has been skipped
CI Build & Deploy Pipeline / Deploy Production (push) Has been skipped
CI Build & Deploy Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Unit Tests (push) Successful in 3m28s
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 4m8s
CI/CD Pipeline / Integration Tests (push) Successful in 1m21s
CI Build & Deploy Pipeline / Build Staging API Image (push) Successful in 6m4s
CI Build & Deploy Pipeline / Build Staging Worker Image (push) Successful in 8m2s
CI Build & Deploy Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 48s
CI Build & Deploy Pipeline / Staging E2E Tests (push) Failing after 1m21s
CI Build & Deploy Pipeline / Staging API Integration Tests (push) Successful in 3m20s

Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
This commit was merged in pull request #525.
This commit is contained in:
2026-07-18 17:22:04 +08:00
committed by auto-approve-bot
parent ce8f6b7398
commit 1ee779a566
4 changed files with 17 additions and 9 deletions
Regular → Executable
+6 -1
View File
@@ -89,7 +89,12 @@ export const getProducts = async (
params?: ProductListParams,
): Promise<ProductItem[]> => {
const response = await apiClient.get("/generation/tasks", { params });
const tasks = response.data.items || response.data || [];
const data = response.data;
const tasks = Array.isArray(data?.items)
? data.items
: Array.isArray(data)
? data
: [];
return tasks.map(mapTaskToProductItem);
};
+4 -4
View File
@@ -1277,13 +1277,13 @@ const AssetLibrary: React.FC = () => {
)}
</div>
{operationResult.succeeded.length > 0 && (
{(operationResult?.succeeded?.length ?? 0) > 0 && (
<div className="xx-batch-result-section">
<h4 className="xx-batch-result-section-title success">
<CheckCircleOutlined />
</h4>
<div className="xx-batch-result-ids">
{operationResult.succeeded.map((id) => (
{operationResult?.succeeded?.map((id) => (
<div key={id} className="xx-batch-result-id">
{id}
</div>
@@ -1292,13 +1292,13 @@ const AssetLibrary: React.FC = () => {
</div>
)}
{operationResult.failed.length > 0 && (
{(operationResult?.failed?.length ?? 0) > 0 && (
<div className="xx-batch-result-section">
<h4 className="xx-batch-result-section-title fail">
<CloseCircleOutlined />
</h4>
<div className="xx-batch-result-ids">
{operationResult.failed.map((id) => (
{operationResult?.failed?.map((id) => (
<div key={id} className="xx-batch-result-id fail">
{id}
</div>
@@ -48,7 +48,7 @@ const GenerationHistoryModal: React.FC<GenerationHistoryModalProps> = ({
<div className="ep-skeleton-item" />
</div>
</div>
) : history.length === 0 ? (
) : (history?.length ?? 0) === 0 ? (
<div className="ep-gh-empty">
<InboxOutlined style={{ fontSize: 32, opacity: 0.4 }} />
<span></span>
@@ -65,7 +65,7 @@ const GenerationHistoryModal: React.FC<GenerationHistoryModalProps> = ({
</tr>
</thead>
<tbody>
{history.map((gen) => {
{(history ?? []).map((gen) => {
const statusClass = `ep-gh-status-tag--${gen.status}`;
const canCancel =
gen.status === "rendering" || gen.status === "editing";
+5 -2
View File
@@ -587,8 +587,11 @@ const ProductLibrary: React.FC = () => {
staleTime: 30_000,
});
// 映射为前端类型
const products = useMemo(() => apiProducts.map(mapApiProduct), [apiProducts]);
// 映射为前端类型,防御非数组返回
const products = useMemo(
() => (Array.isArray(apiProducts) ? apiProducts : []).map(mapApiProduct),
[apiProducts],
);
/* ── 删除 mutation ── */
const deleteMutation = useMutation({