Files
xiaoxia-saas/apps/web/src/components/asset-selector/AssetListItem.tsx
T
xiaoxia 4578b65965
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 2m30s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 2m37s
CI/CD Pipeline / Frontend Lint (push) Successful in 3m3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m18s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m18s
CI/CD Pipeline / Frontend Unit Tests (push) Failing after 3m17s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 3m33s
CI/CD Pipeline / Integration Tests (push) Successful in 2m22s
CI/CD Pipeline / Build Staging API Image (push) Successful in 6m19s
CI/CD Pipeline / Unit Tests (push) Failing after 6m57s
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m31s
CI/CD Pipeline / ACR Image Cleanup (push) Failing after 16s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m46s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m59s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
refactor(asset-selector): 三阶段重构 AssetSelector(504→168行, -67%) (#937)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-07-28 01:02:50 +08:00

100 lines
2.6 KiB
TypeScript

import React from "react"
import type { MediaAsset } from "@/api/template-editor"
import { MATERIAL_TYPE_LABELS, MATERIAL_TYPE_ICONS } from "@/api/template-editor"
import { formatSize, formatDuration, getQualityColor } from "./utils"
interface AssetListItemProps {
asset: MediaAsset
isSelected: boolean
isDragging: boolean
isDragOver: boolean
showCheckbox: boolean
onToggleSelect: (asset: MediaAsset, shiftKey: boolean) => void
onCardClick: (asset: MediaAsset, e: React.MouseEvent) => void
onDragStart: (e: React.DragEvent) => void
onDragOver: (e: React.DragEvent) => void
onDrop: (e: React.DragEvent) => void
onDragEnd: () => void
onMouseEnter: (e: React.MouseEvent) => void
onMouseLeave: () => void
}
const AssetListItem: React.FC<AssetListItemProps> = ({
asset,
isSelected,
isDragging,
isDragOver,
showCheckbox,
onToggleSelect,
onCardClick,
onDragStart,
onDragOver,
onDrop,
onDragEnd,
onMouseEnter,
onMouseLeave,
}) => {
return (
<div
className={[
"as-list-item",
isSelected ? "selected" : "",
isDragging ? "dragging" : "",
isDragOver ? "drag-over" : "",
]
.filter(Boolean)
.join(" ")}
draggable
onDragStart={onDragStart}
onDragOver={onDragOver}
onDrop={onDrop}
onDragEnd={onDragEnd}
onClick={(e) => onCardClick(asset, e)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{/* 拖拽手柄 */}
<span className="as-list-item-drag" title="拖拽排序">
</span>
{/* Checkbox */}
{showCheckbox && (
<span
data-checkbox
className={`as-list-item-checkbox${isSelected ? " checked" : ""}`}
onClick={(e) => {
e.stopPropagation()
onToggleSelect(asset, e.shiftKey)
}}
/>
)}
{/* 图标 */}
<span className="as-list-item-icon">{MATERIAL_TYPE_ICONS[asset.type]}</span>
{/* 信息 */}
<div className="as-list-item-info">
<div className="as-list-item-name">{asset.name}</div>
<div className="as-list-item-meta">
{MATERIAL_TYPE_LABELS[asset.type]}
{asset.duration != null && ` · ${formatDuration(asset.duration)}`}
{asset.size != null && ` · ${formatSize(asset.size)}`}
</div>
</div>
{/* 质量分 */}
{asset.quality_score != null && (
<span
className="as-list-item-quality"
style={{ color: getQualityColor(asset.quality_score) }}
>
{asset.quality_score}
</span>
)}
</div>
)
}
export default AssetListItem