style(cover-avatar): 列表改为 avatar-card 卡片样式(hover 操作按钮 + 图片缩放 + 4 列网格)
This commit is contained in:
@@ -1089,6 +1089,17 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 封面形象网格 — 复用 avatar-card 风格 */
|
||||
.cover-avatar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: var(--spacing-xl);
|
||||
padding: var(--spacing-sm) var(--spacing-xs);
|
||||
flex: 1;
|
||||
align-content: start;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* Content Page Compact variant */
|
||||
.content-page-compact {
|
||||
gap: var(--spacing-md);
|
||||
|
||||
@@ -285,62 +285,57 @@ export default function CoverAvatarLibrary() {
|
||||
<p className="empty-state-desc">上传一张人物照片,<br />AI 将自动抠图生成透明背景形象</p>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 16, flex: 1, overflow: 'auto' }}>
|
||||
<div className="voice-list" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, alignContent: 'start', alignItems: 'start' }}>
|
||||
{coverAvatars.map(a => (
|
||||
<div key={a.id} className="voice-row" style={{ cursor: 'default', padding: 12 }}>
|
||||
{/* 图片预览 */}
|
||||
<div style={{ marginBottom: 10, borderRadius: 'var(--radius-md)', overflow: 'hidden', background: '#f5f5f5', aspectRatio: '1', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<img
|
||||
src={a.imageUrl}
|
||||
alt={a.name}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'contain' }}
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="voice-row-main" style={{ padding: 0 }}>
|
||||
<div className="voice-row-info" style={{ flex: 1, minWidth: 0 }}>
|
||||
{editingId === a.id ? (
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
value={editingName}
|
||||
onChange={e => setEditingName(e.target.value)}
|
||||
onKeyDown={e => {
|
||||
if (e.key === 'Enter') {confirmRename();}
|
||||
if (e.key === 'Escape') {cancelRename();}
|
||||
}}
|
||||
onBlur={confirmRename}
|
||||
autoFocus
|
||||
style={{ width: '100%', height: 28, padding: '2px 8px', fontSize: 'var(--font-sm)' }}
|
||||
/>
|
||||
) : (
|
||||
<div className="voice-row-name" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{a.name}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="voice-row-actions">
|
||||
<button
|
||||
className="action-icon"
|
||||
onClick={() => startRename(a.id, a.name)}
|
||||
title="重命名"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" /></svg>
|
||||
</button>
|
||||
<button
|
||||
className="action-icon"
|
||||
onClick={() => openDeleteModal(a.id, a.name)}
|
||||
title="删除"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div className="cover-avatar-grid">
|
||||
{coverAvatars.map(a => (
|
||||
<div key={a.id} className="avatar-card">
|
||||
{/* 图片预览 */}
|
||||
<div className="avatar-card-thumb-container">
|
||||
<img
|
||||
src={a.imageUrl}
|
||||
alt={a.name}
|
||||
className="avatar-card-video"
|
||||
style={{ objectFit: 'contain', background: 'var(--bg-input)' }}
|
||||
loading="lazy"
|
||||
/>
|
||||
{/* 悬停操作按钮 */}
|
||||
<div className="avatar-card-actions">
|
||||
<button
|
||||
className="avatar-card-action-btn"
|
||||
onClick={() => startRename(a.id, a.name)}
|
||||
title="重命名"
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" /></svg>
|
||||
</button>
|
||||
<button
|
||||
className="avatar-card-action-btn delete"
|
||||
onClick={() => openDeleteModal(a.id, a.name)}
|
||||
title="删除"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* 名称 */}
|
||||
<div className="avatar-card-info">
|
||||
{editingId === a.id ? (
|
||||
<input
|
||||
type="text"
|
||||
className="avatar-card-name-input"
|
||||
value={editingName}
|
||||
onChange={e => setEditingName(e.target.value)}
|
||||
onKeyDown={e => {
|
||||
if (e.key === 'Enter') {confirmRename();}
|
||||
if (e.key === 'Escape') {cancelRename();}
|
||||
}}
|
||||
onBlur={confirmRename}
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
<div className="avatar-card-name">{a.name}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user