feat(admin): batch ops, transfer, watermark, usage and qr share pages

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-20 21:10:30 +08:00
parent 618d1d796c
commit f08d68bebf
31 changed files with 2717 additions and 34 deletions
+54 -3
View File
@@ -21,9 +21,19 @@
<span class="font-medium">{{ titleOf(album) }}</span>
<ElTag size="small" type="info">{{ album?.defaultLocale }}</ElTag>
</div>
<ElButton type="primary" plain data-test="album-detail-edit" @click="editVisible = true">
{{ $t('albumsManage.detail.edit') }}
</ElButton>
<div class="flex items-center gap-2">
<ElButton plain data-test="album-detail-transfer" @click="transferVisible = true">
{{ $t('albumsManage.transfer.entry') }}
</ElButton>
<ElButton
type="primary"
plain
data-test="album-detail-edit"
@click="editVisible = true"
>
{{ $t('albumsManage.detail.edit') }}
</ElButton>
</div>
</div>
</template>
@@ -82,6 +92,18 @@
<ElDescriptionsItem :label="$t('albumsManage.detail.fieldUpdatedAt')">
{{ formatDateTime(album.updatedAt) }}
</ElDescriptionsItem>
<ElDescriptionsItem :label="$t('albumsManage.detail.fieldStatsSyncedAt')">
<span data-test="album-detail-stats-synced-at">
{{
album.statsSyncedAt
? formatDateTime(album.statsSyncedAt)
: $t('albumsManage.detail.statsNotSynced')
}}
</span>
</ElDescriptionsItem>
<ElDescriptionsItem :label="$t('albumsManage.detail.fieldOwnerId')">
<span data-test="album-detail-owner-id">{{ album.ownerId }}</span>
</ElDescriptionsItem>
</ElDescriptions>
<div v-if="album" class="mt-5">
@@ -111,10 +133,30 @@
</template>
<AlbumCategories :album="album" @changed="load" />
</ElTabPane>
<ElTabPane name="watermark">
<template #label>
<span data-test="album-watermark-tab">
{{ $t('albumsManage.detail.tabWatermark') }}
</span>
</template>
<AlbumWatermark :album="album" />
</ElTabPane>
<ElTabPane name="share">
<template #label>
<span data-test="album-share-tab">{{ $t('albumsManage.detail.tabShare') }}</span>
</template>
<AlbumShareCard :album="album" />
</ElTabPane>
</ElTabs>
</ElCard>
<AlbumFormDialog v-if="album" v-model="editVisible" :album="album" @saved="onAlbumSaved" />
<AlbumTransferDialog
v-if="album"
v-model="transferVisible"
:album="album"
@saved="onTransferred"
/>
</div>
</template>
@@ -129,6 +171,9 @@
import AlbumMembers from './AlbumMembers.vue'
import AlbumCategories from './AlbumCategories.vue'
import AlbumPhotos from './AlbumPhotos.vue'
import AlbumWatermark from './AlbumWatermark.vue'
import AlbumShareCard from './AlbumShareCard.vue'
import AlbumTransferDialog from './AlbumTransferDialog.vue'
import { fetchAlbum } from '@/api/albums'
import { formatDateTime } from '@/utils/albums/format'
@@ -144,6 +189,7 @@
const loading = ref(false)
const error = ref<Error | null>(null)
const editVisible = ref(false)
const transferVisible = ref(false)
const activeTab = ref('photos')
async function load() {
@@ -163,6 +209,11 @@
album.value = saved
}
/** 交接成功:回包 ownerId 已变更,原位替换相册详情 */
function onTransferred(transferred: Api.Album.Detail) {
album.value = transferred
}
function titleOf(target: Api.Album.Detail | null): string {
if (!target) return ''
const preferred = target.translations.find((item) => item.locale === target.defaultLocale)