ffebaa7249
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (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 / Validate - Migration (alembic) (push) Successful in 57s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m9s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m37s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m44s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m44s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 6m35s
CI/CD Pipeline / Build Staging API Image (push) Successful in 6m46s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 38s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m24s
CI/CD Pipeline / Integration Tests (push) Successful in 4m8s
CI/CD Pipeline / Unit Tests (push) Successful in 11m20s
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 / CI Gate (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 / Staging API Integration Tests (push) Successful in 3m26s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com> Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
529 lines
10 KiB
CSS
529 lines
10 KiB
CSS
/**
|
|
* 素材选择器 - V21 设计系统样式
|
|
* 支持批量选择、拖拽排序、预览缩略图、质量分筛选
|
|
* 前缀: as- (AssetSelector)
|
|
*/
|
|
@import "../../styles/global.css";
|
|
|
|
/* ============================================================
|
|
容器
|
|
============================================================ */
|
|
.as-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ── 工具栏 ─────────────────────────────────────────────────── */
|
|
.as-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
padding: var(--space-sm) var(--space-md);
|
|
border-bottom: 1px solid var(--border-color);
|
|
flex-shrink: 0;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.as-toolbar-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.as-toolbar-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
/* 搜索框 */
|
|
.as-search {
|
|
flex: 1;
|
|
min-width: 120px;
|
|
max-width: 200px;
|
|
}
|
|
|
|
/* 视图切换按钮 */
|
|
.as-view-btn {
|
|
width: 28px;
|
|
height: 28px;
|
|
padding: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: var(--radius-sm);
|
|
border: 1px solid var(--border-color);
|
|
background: var(--bg-primary);
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
transition: var(--transition-all);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.as-view-btn:hover {
|
|
color: var(--primary-color);
|
|
border-color: var(--primary-color);
|
|
}
|
|
|
|
.as-view-btn.active {
|
|
background: var(--primary-soft);
|
|
color: var(--primary-color);
|
|
border-color: var(--primary-color);
|
|
}
|
|
|
|
/* ── 批量操作栏 ─────────────────────────────────────────────── */
|
|
.as-batch-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
padding: 6px var(--space-md);
|
|
background: var(--primary-soft);
|
|
border-bottom: 1px solid var(--color-primary-200);
|
|
font-size: var(--font-size-sm);
|
|
color: var(--primary-color);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.as-batch-bar-count {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.as-batch-bar-actions {
|
|
display: flex;
|
|
gap: var(--space-xs);
|
|
margin-left: auto;
|
|
}
|
|
|
|
/* ── 素材列表区域 ───────────────────────────────────────────── */
|
|
.as-body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: var(--space-sm);
|
|
}
|
|
|
|
.as-empty {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: var(--space-2xl) var(--space-md);
|
|
text-align: center;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.as-empty-icon {
|
|
font-size: 36px;
|
|
margin-bottom: var(--space-sm);
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.as-empty p {
|
|
margin: 0;
|
|
font-size: var(--font-size-sm);
|
|
}
|
|
|
|
/* ── 网格视图 ───────────────────────────────────────────────── */
|
|
.as-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
|
gap: var(--space-sm);
|
|
}
|
|
|
|
.as-grid.compact {
|
|
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
|
gap: 6px;
|
|
}
|
|
|
|
/* ── 列表视图 ───────────────────────────────────────────────── */
|
|
.as-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
/* ============================================================
|
|
素材卡片 — 网格模式
|
|
============================================================ */
|
|
.as-card {
|
|
position: relative;
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-md);
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
transition: var(--transition-all);
|
|
background: var(--bg-primary);
|
|
user-select: none;
|
|
}
|
|
|
|
.as-card:hover {
|
|
border-color: var(--primary-color);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.as-card.selected {
|
|
border-color: var(--primary-color);
|
|
box-shadow: 0 0 0 2px var(--primary-soft);
|
|
}
|
|
|
|
.as-card.dragging {
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.as-card.drag-over {
|
|
border-color: var(--primary-color);
|
|
box-shadow: 0 0 0 2px var(--primary-color);
|
|
}
|
|
|
|
/* 缩略图区域 */
|
|
.as-card-thumb {
|
|
position: relative;
|
|
aspect-ratio: 9 / 16;
|
|
background: var(--bg-secondary);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.as-card-thumb-icon {
|
|
font-size: 28px;
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.as-card-thumb img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
/* 类型角标 */
|
|
.as-card-type-badge {
|
|
position: absolute;
|
|
top: 4px;
|
|
left: 4px;
|
|
padding: 1px 5px;
|
|
border-radius: var(--radius-sm);
|
|
background: rgba(0, 0, 0, 0.55);
|
|
color: #fff;
|
|
font-size: 10px;
|
|
line-height: 1.4;
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
/* 时长角标 */
|
|
.as-card-duration {
|
|
position: absolute;
|
|
bottom: 4px;
|
|
right: 4px;
|
|
padding: 1px 5px;
|
|
border-radius: var(--radius-sm);
|
|
background: rgba(0, 0, 0, 0.6);
|
|
color: #fff;
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* 质量分角标 */
|
|
.as-card-quality {
|
|
position: absolute;
|
|
top: 4px;
|
|
right: 4px;
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 9px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
}
|
|
|
|
.as-card-quality.excellent {
|
|
background: var(--success-color, #10b981);
|
|
}
|
|
|
|
.as-card-quality.good {
|
|
background: var(--primary-color, #6366f1);
|
|
}
|
|
|
|
.as-card-quality.fair {
|
|
background: var(--warning-color, #f59e0b);
|
|
}
|
|
|
|
.as-card-quality.poor {
|
|
background: var(--error-color, #ef4444);
|
|
}
|
|
|
|
/* 选择 checkbox */
|
|
.as-card-checkbox {
|
|
position: absolute;
|
|
top: 4px;
|
|
left: 4px;
|
|
z-index: 2;
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: var(--radius-sm);
|
|
border: 2px solid rgba(255, 255, 255, 0.7);
|
|
background: rgba(0, 0, 0, 0.2);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: var(--transition-all);
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.as-card-checkbox.checked {
|
|
background: var(--primary-color);
|
|
border-color: var(--primary-color);
|
|
}
|
|
|
|
.as-card-checkbox.checked::after {
|
|
content: "✓";
|
|
color: #fff;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* 有 checkbox 时,类型角标右移 */
|
|
.as-card.has-checkbox .as-card-type-badge {
|
|
left: 26px;
|
|
}
|
|
|
|
/* 卡片信息 */
|
|
.as-card-info {
|
|
padding: 6px 8px;
|
|
}
|
|
|
|
.as-card-name {
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
margin: 0;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.as-card-meta {
|
|
font-size: 10px;
|
|
color: var(--text-secondary);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* ============================================================
|
|
素材卡片 — 列表模式
|
|
============================================================ */
|
|
.as-list-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-sm);
|
|
padding: 6px 8px;
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius-sm);
|
|
cursor: pointer;
|
|
transition: var(--transition-all);
|
|
user-select: none;
|
|
}
|
|
|
|
.as-list-item:hover {
|
|
background: var(--bg-secondary);
|
|
border-color: var(--border-color);
|
|
}
|
|
|
|
.as-list-item.selected {
|
|
background: var(--primary-soft);
|
|
border-color: var(--primary-color);
|
|
}
|
|
|
|
.as-list-item.dragging {
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.as-list-item.drag-over {
|
|
border-top: 2px solid var(--primary-color);
|
|
}
|
|
|
|
.as-list-item-checkbox {
|
|
width: 16px;
|
|
height: 16px;
|
|
border-radius: 3px;
|
|
border: 2px solid var(--border-color);
|
|
flex-shrink: 0;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: var(--transition-all);
|
|
}
|
|
|
|
.as-list-item-checkbox.checked {
|
|
background: var(--primary-color);
|
|
border-color: var(--primary-color);
|
|
}
|
|
|
|
.as-list-item-checkbox.checked::after {
|
|
content: "✓";
|
|
color: #fff;
|
|
font-size: 10px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.as-list-item-drag {
|
|
cursor: grab;
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
opacity: 0.4;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.as-list-item-drag:hover {
|
|
opacity: 1;
|
|
}
|
|
|
|
.as-list-item-drag:active {
|
|
cursor: grabbing;
|
|
}
|
|
|
|
.as-list-item-icon {
|
|
font-size: 20px;
|
|
flex-shrink: 0;
|
|
width: 28px;
|
|
text-align: center;
|
|
}
|
|
|
|
.as-list-item-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.as-list-item-name {
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.as-list-item-meta {
|
|
font-size: 11px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.as-list-item-quality {
|
|
width: 32px;
|
|
text-align: center;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ============================================================
|
|
悬浮预览
|
|
============================================================ */
|
|
.as-preview-overlay {
|
|
position: fixed;
|
|
z-index: 1000;
|
|
pointer-events: none;
|
|
background: var(--bg-primary);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-lg);
|
|
padding: 8px;
|
|
min-width: 180px;
|
|
max-width: 260px;
|
|
animation: as-preview-in 0.15s ease;
|
|
}
|
|
|
|
.as-preview-overlay-thumb {
|
|
width: 100%;
|
|
aspect-ratio: 9 / 16;
|
|
max-height: 200px;
|
|
background: var(--bg-secondary);
|
|
border-radius: var(--radius-md);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.as-preview-overlay-thumb img,
|
|
.as-preview-overlay-thumb video {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.as-preview-overlay-thumb-icon {
|
|
font-size: 48px;
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.as-preview-overlay-name {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
margin: 0 0 4px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.as-preview-overlay-meta {
|
|
font-size: 11px;
|
|
color: var(--text-secondary);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
|
|
@keyframes as-preview-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: scale(0.95);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
|
|
/* ============================================================
|
|
响应式
|
|
============================================================ */
|
|
@media (max-width: 768px) {
|
|
.as-grid {
|
|
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
|
}
|
|
|
|
.as-toolbar {
|
|
padding: var(--space-xs) var(--space-sm);
|
|
}
|
|
|
|
.as-search {
|
|
max-width: 140px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.as-grid {
|
|
grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
|
|
gap: 4px;
|
|
}
|
|
|
|
.as-card-info {
|
|
padding: 4px 6px;
|
|
}
|
|
|
|
.as-card-name {
|
|
font-size: 10px;
|
|
}
|
|
}
|