Files
xiaoxia-saas/apps/web/src/pages/assets/components/AssetGridSection.tsx
T
xiaoxia 5c45629495
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 4m37s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4m37s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 4m50s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 5m5s
AI Code Review / AI Code Review (pull_request) Successful in 7m56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m40s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 8m15s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 8m37s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m48s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m55s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 10m20s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m1s
CI/CD Pipeline / Retag skipped Staging API Image (push) Successful in 2m18s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1m49s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Successful in 2m16s
CI/CD Pipeline / Integration Tests (push) Successful in 4m27s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m0s
CI/CD Pipeline / Unit Tests (push) Successful in 15m57s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m25s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m10s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 4m44s
CI/CD Pipeline / Canary Release to Production (push) Failing after 405h11m24s
CI/CD Pipeline / Production Browser E2E (push) Failing after 405h13m22s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 405h18m50s
CI/CD Pipeline / Deploy Production (push) Failing after 405h13m23s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Failing after 405h18m56s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 405h13m23s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 405h19m0s
CI/CD Pipeline / Build Production Web Image (push) Failing after 405h13m24s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 405h19m0s
CI/CD Pipeline / CI Gate (push) Failing after 405h13m24s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 405h19m2s
CI/CD Pipeline / Build Production API Image (push) Failing after 405h13m24s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 405h19m4s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 405h18m52s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 405h18m54s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 405h20m35s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 405h20m57s
CI/CD Pipeline / Build Staging Worker Image (push) Failing after 405h21m0s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 405h21m3s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 405h21m5s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 405h20m37s
CI/CD Pipeline / Build Staging API Image (push) Failing after 405h21m5s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 405h24m44s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 405h24m48s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 405h20m59s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 405h25m53s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 405h25m57s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Failing after 405h28m47s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 405h28m51s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 405h28m53s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 405h29m18s
CI/CD Pipeline / PR Build API Image (push) Failing after 405h29m22s
CI/CD Pipeline / Frontend Lint (push) Failing after 405h29m23s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 405h29m25s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 405h29m26s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 405h53m11s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 405h55m10s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 405h58m55s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 406h0m4s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Failing after 406h2m58s
CI/CD Pipeline / PR Build Web Image (push) Failing after 406h3m29s
feat(assets): 上传即入库——批量上传队列化(并发3)+真实进度+刷新不丢 (#1557)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-08-30 17:56:02 +08:00

100 lines
2.6 KiB
TypeScript

/**
* AssetLibrary 素材网格区域(含加载/错误/空状态)
*/
import React from "react"
import { PictureOutlined, ExclamationCircleOutlined } from "@ant-design/icons"
import { Button } from "@/components/ui"
import type { AssetItem } from "../types"
import AssetCard from "./AssetCard"
import { SkeletonCard } from "./AssetSkeleton"
/** 上传中素材的实时进度(asset_id → 进度信息),由上传队列合并到卡片 */
export type UploadProgressMap = Map<string, { progress: number; uploading: boolean }>
export interface AssetGridSectionProps {
loading: boolean
error: boolean
errorMessage?: string
assets: AssetItem[]
selectedIds: Set<string>
diagnosingId: string | null
uploadProgressMap?: UploadProgressMap
onRetry?: () => void
onToggleSelect: (id: string) => void
onDiagnose: (asset: AssetItem) => void
onPlay: (asset: AssetItem) => void
onDelete: (id: string) => void
}
export const AssetGridSection: React.FC<AssetGridSectionProps> = ({
loading,
error,
errorMessage,
assets,
selectedIds,
diagnosingId,
uploadProgressMap,
onRetry,
onToggleSelect,
onDiagnose,
onPlay,
onDelete,
}) => {
if (loading) {
return (
<div className="xx-asset-grid">
{Array.from({ length: 8 }).map((_, i) => (
<SkeletonCard key={i} />
))}
</div>
)
}
if (error) {
return (
<div className="xx-assets-empty">
<div className="xx-assets-empty-icon">
<ExclamationCircleOutlined />
</div>
<p className="xx-assets-empty-title">{errorMessage || "加载失败"}</p>
{onRetry && (
<Button buttonType="primary" buttonSize="sm" onClick={onRetry}>
重新加载
</Button>
)}
</div>
)
}
if (assets.length > 0) {
return (
<div className="xx-asset-grid">
{assets.map((asset) => (
<AssetCard
key={asset.id}
asset={asset}
selected={selectedIds.has(asset.id)}
diagnosing={diagnosingId === asset.id}
uploadProgress={uploadProgressMap?.get(asset.id)}
onToggle={() => onToggleSelect(asset.id)}
onDiagnose={() => onDiagnose(asset)}
onPlay={() => onPlay(asset)}
onDelete={() => onDelete(asset.id)}
/>
))}
</div>
)
}
return (
<div className="xx-assets-empty">
<div className="xx-assets-empty-icon">
<PictureOutlined />
</div>
<p className="xx-assets-empty-title">暂无素材,请上传或切换视频库</p>
</div>
)
}
export default AssetGridSection