feat: 支持图库瀑布流切换并调整列表间距

This commit is contained in:
GouJ
2026-09-04 12:41:04 +08:00
parent de421f985e
commit 989f2c1834
7 changed files with 177 additions and 10 deletions
@@ -17,7 +17,17 @@ import {
} from 'naive-ui'
import { computed, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Search, RefreshCw, Download, ImagePlus, ArrowLeft, ArrowRight, LayoutGrid, AlertTriangle } from '@lucide/vue'
import {
Search,
RefreshCw,
Download,
ImagePlus,
ArrowLeft,
ArrowRight,
LayoutGrid,
Columns3,
AlertTriangle
} from '@lucide/vue'
import { AssetImage, EmptyState, StatusBadge } from '../../components/ui'
import { downloadText } from '../../lib/format'
import ConfirmAction from '../workflows/ConfirmAction.vue'
@@ -30,6 +40,7 @@ import FormPromptDialog from './components/FormPromptDialog.vue'
import FormPromptBatch from './components/FormPromptBatch.vue'
import { useKeyframeImpact } from './useKeyframeImpact'
import { queryText, referenceLocation, referenceTargets } from '../production/asset-links'
import { formCoverAspectRatio, type GalleryLayout } from './layout'
/** 形态图库以正式数据库为准;首次读取、手动刷新和自身操作完成后更新,不定时刷新。 */
const route = useRoute()
@@ -123,6 +134,8 @@ watch(
}
)
const search = ref('')
/** 切换排版复用同一份卡片和查询结果,不重新读取图库或清空筛选。 */
const layout = ref<GalleryLayout>('grid')
const module = ref('all')
const onlyMissing = ref(false)
const onlyStale = ref(false)
@@ -491,7 +504,33 @@ async function showStaleForms() {
<NCheckbox v-model:checked="onlyMissing">仅看缺少主图</NCheckbox>
<NCheckbox v-model:checked="onlyStale">仅看身份过期</NCheckbox>
</div>
<span class="filter-result-count">{{ filtered.length }} 个形态</span>
<div class="form-image-display-controls">
<span class="filter-result-count">{{ filtered.length }} 个形态</span>
<div class="gallery-layout-switch" role="group" aria-label="图库显示方式">
<NButton
class="icon-button"
size="small"
:type="layout === 'grid' ? 'primary' : 'default'"
:aria-pressed="layout === 'grid'"
aria-label="网格布局"
title="网格布局"
@click="layout = 'grid'"
>
<template #icon><LayoutGrid :size="16" /></template>
</NButton>
<NButton
class="icon-button"
size="small"
:type="layout === 'masonry' ? 'primary' : 'default'"
:aria-pressed="layout === 'masonry'"
aria-label="瀑布流布局"
title="瀑布流布局"
@click="layout = 'masonry'"
>
<template #icon><Columns3 :size="16" /></template>
</NButton>
</div>
</div>
</div>
</div>
</div>
@@ -559,7 +598,11 @@ async function showStaleForms() {
<p v-if="!query.data.value && query.loading.value" class="py-10 text-sm text-muted" role="status">
正在读取形态和已有图片
</p>
<div v-else-if="filtered.length" class="form-image-grid">
<div
v-else-if="filtered.length"
class="form-image-grid"
:class="{ 'form-image-masonry': layout === 'masonry' }"
>
<article
v-for="form in filtered"
:key="form.id"
@@ -569,11 +612,12 @@ async function showStaleForms() {
'form-image-card-focused': targetFormId === form.id
}"
:data-form-id="form.id"
:style="{ '--form-image-aspect': formCoverAspectRatio(form) }"
>
<AssetImage
:src="coverImage(form)?.imageUrl"
:alt="`${form.subject.name} · ${form.name}`"
object-fit="cover"
:object-fit="layout === 'masonry' ? 'contain' : 'cover'"
preview
:empty-text="hasRunningImages(form.images) ? '后台正在生成图片' : '尚未生成图片'"
/>