Files
O96u 737235acff release: v1.4.0 — 标签系统、操作日志扩展与文档截图更新
- 每用户标签与彩色打标,图库 OR/AND 筛选与批量打标
- 操作日志记录登录、删除、设置与标签操作
- API 标签/打标接口;README 与文档站截图同步
2026-09-09 14:46:52 +08:00

95 lines
2.4 KiB
Vue

<script setup lang="ts">
import type { ImageItem } from '~/types/image'
const props = withDefaults(defineProps<{
items: ImageItem[]
selectedKeys: Set<string>
selectable?: boolean
showKey?: boolean
showStorage?: boolean
emptyText?: string
dense?: boolean
compact?: boolean
/** 图库:5 列 × 2 行,缩略图略扁 */
gallery?: boolean
allowDelete?: boolean
showTags?: boolean
showTagAction?: boolean
}>(), {
selectable: true,
showKey: true,
showStorage: false,
dense: false,
compact: false,
gallery: false,
allowDelete: true,
showTags: false,
showTagAction: false
})
const gridClass = computed(() => {
if (props.gallery) {
return 'grid items-start grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5'
}
if (props.dense) {
return 'grid items-start grid-cols-2 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'
}
return 'grid items-start grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'
})
const emit = defineEmits<{
'update:selectedKeys': [value: Set<string>]
'preview': [image: ImageItem]
'delete': [image: ImageItem]
'tag-click': [tagId: number]
'untagged-click': []
'edit-tags': [image: ImageItem]
}>()
const { t } = useI18n()
const displayEmptyText = computed(() => props.emptyText ?? t('image.empty'))
function updateSelection(key: string, selected: boolean) {
const next = new Set(props.selectedKeys)
if (selected) next.add(key)
else next.delete(key)
emit('update:selectedKeys', next)
}
</script>
<template>
<div
v-if="items.length"
class="items-start"
:class="gridClass"
>
<ImageCard
v-for="image in items"
:key="image.key"
:image="image"
:selected="selectedKeys.has(image.key)"
:selectable="selectable"
:show-key="showKey"
:show-storage="showStorage"
:compact="compact"
:gallery="gallery"
:allow-delete="allowDelete"
:show-tags="showTags"
:show-tag-action="showTagAction"
@update:selected="updateSelection(image.key, $event)"
@preview="emit('preview', image)"
@delete="emit('delete', image)"
@tag-click="emit('tag-click', $event)"
@untagged-click="emit('untagged-click')"
@edit-tags="emit('edit-tags', image)"
/>
</div>
<div
v-else
class="rounded-xl border border-dashed border-default py-16 text-center text-sm text-muted"
>
{{ displayEmptyText }}
</div>
</template>