101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
|
|
import { useEffect, useState } from 'react'
|
||
|
|
import { getRecentAssets } from '../api/generate'
|
||
|
|
import type { RecentAssetItem } from '../api/types'
|
||
|
|
|
||
|
|
const ASSET_TYPE_LABELS: Record<string, string> = {
|
||
|
|
sprite: '精灵',
|
||
|
|
background: '背景',
|
||
|
|
ui: 'UI',
|
||
|
|
animation: '动画',
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function AssetGallery() {
|
||
|
|
const [assets, setAssets] = useState<RecentAssetItem[]>([])
|
||
|
|
const [loading, setLoading] = useState(true)
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
getRecentAssets()
|
||
|
|
.then(setAssets)
|
||
|
|
.catch(() => {})
|
||
|
|
.finally(() => setLoading(false))
|
||
|
|
}, [])
|
||
|
|
|
||
|
|
if (loading) return null
|
||
|
|
|
||
|
|
if (assets.length === 0) return null
|
||
|
|
|
||
|
|
return (
|
||
|
|
<section style={{ marginBottom: 32 }}>
|
||
|
|
<h2 style={{ fontSize: 18, marginBottom: 16 }}>最近生成</h2>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: 'grid',
|
||
|
|
gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))',
|
||
|
|
gap: 12,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{assets.map((item, i) => (
|
||
|
|
<div
|
||
|
|
key={`${item.taskId}-${i}`}
|
||
|
|
className="card"
|
||
|
|
style={{ padding: 8, cursor: 'pointer' }}
|
||
|
|
onClick={() => {
|
||
|
|
// navigate to result page — need projectId for URL
|
||
|
|
// For now just open the image
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
width: '100%',
|
||
|
|
aspectRatio: '1',
|
||
|
|
overflow: 'hidden',
|
||
|
|
borderRadius: 'var(--radius)',
|
||
|
|
background: 'var(--bg-input)',
|
||
|
|
display: 'flex',
|
||
|
|
alignItems: 'center',
|
||
|
|
justifyContent: 'center',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<img
|
||
|
|
src={item.url}
|
||
|
|
alt={item.prompt}
|
||
|
|
loading="lazy"
|
||
|
|
style={{
|
||
|
|
maxWidth: '100%',
|
||
|
|
maxHeight: '100%',
|
||
|
|
objectFit: 'contain',
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div style={{ marginTop: 6 }}>
|
||
|
|
<span
|
||
|
|
style={{
|
||
|
|
fontSize: 11,
|
||
|
|
padding: '1px 6px',
|
||
|
|
borderRadius: 999,
|
||
|
|
background: 'var(--accent-dim)',
|
||
|
|
color: 'var(--accent)',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{ASSET_TYPE_LABELS[item.assetType] || item.assetType}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
<p
|
||
|
|
style={{
|
||
|
|
fontSize: 12,
|
||
|
|
color: 'var(--text-secondary)',
|
||
|
|
marginTop: 4,
|
||
|
|
overflow: 'hidden',
|
||
|
|
textOverflow: 'ellipsis',
|
||
|
|
whiteSpace: 'nowrap',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{item.prompt}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
)
|
||
|
|
}
|