diff --git a/app/components/MediaSessionCard.vue b/app/components/MediaSessionCard.vue
index 62054e4..63cdf2d 100644
--- a/app/components/MediaSessionCard.vue
+++ b/app/components/MediaSessionCard.vue
@@ -180,6 +180,11 @@ const presetLabel = computed(() => {
+
+
{
void Promise.all([
loadActiveTranscodes(),
- loadUploadPolicy().catch(() => {})
+ loadUploadPolicy().catch(() => {}),
+ fetchTags()
])
})
@@ -89,6 +93,27 @@ async function removeItem(item: FileItem) {
toast.add({ title: t('files.deleteFailed'), color: 'error' })
}
}
+
+async function confirmBatchTags(tagIds: number[]) {
+ const keys = sessionItems.value.map(item => item.key)
+ if (!keys.length || !tagIds.length) return
+
+ try {
+ await batchUpdateTags(keys, tagIds, 'add')
+ batchTagOpen.value = false
+ recordRecent(tagIds)
+ await fetchTags(true)
+ const addedTags = tagItems.value.filter(tag => tagIds.includes(tag.id))
+ sessionItems.value = sessionItems.value.map((item) => {
+ const merged = new Map((item.tags ?? []).map(tag => [tag.id, tag]))
+ for (const tag of addedTags) merged.set(tag.id, tag)
+ return { ...item, tags: [...merged.values()] }
+ })
+ toast.add({ title: t('tags.batchSuccess'), color: 'success' })
+ } catch {
+ toast.add({ title: t('tags.batchFailed'), color: 'error' })
+ }
+}
@@ -112,10 +137,20 @@ async function removeItem(item: FileItem) {
v-if="sessionItems.length"
class="space-y-4"
>
-
- {{ t('upload.sessionTitle') }}
- ({{ sessionItems.length }})
-
+
+
+ {{ t('upload.sessionTitle') }}
+ ({{ sessionItems.length }})
+
+ { batchTagOpen = true }"
+ />
+
+
+
diff --git a/server/api/images/batch-tags.post.ts b/server/api/images/batch-tags.post.ts
index b99748c..bd412a8 100644
--- a/server/api/images/batch-tags.post.ts
+++ b/server/api/images/batch-tags.post.ts
@@ -46,7 +46,7 @@ export default defineEventHandler(async (event) => {
const action = body?.action === 'remove' ? 'remove' : 'add'
if (!keys.length) {
- createApiError(event, 'INVALID_REQUEST', '请提供图片列表', 400)
+ createApiError(event, 'INVALID_REQUEST', '请提供媒体列表', 400)
}
if (!tagIds.length) {
createApiError(event, 'INVALID_REQUEST', '请提供标签列表', 400)
@@ -55,7 +55,7 @@ export default defineEventHandler(async (event) => {
createApiError(
event,
'INVALID_REQUEST',
- `每次最多处理 ${MAX_DELETE_BATCH} 张图片`,
+ `每次最多处理 ${MAX_DELETE_BATCH} 个媒体`,
400
)
}
@@ -64,7 +64,7 @@ export default defineEventHandler(async (event) => {
validateKeys(keys)
} catch (error) {
if (error instanceof Error && error.message.startsWith('INVALID_KEY:')) {
- createApiError(event, 'INVALID_IMAGE_KEY', `无效的图片路径: ${error.message.slice(12)}`, 400)
+ createApiError(event, 'INVALID_IMAGE_KEY', `无效的媒体路径: ${error.message.slice(12)}`, 400)
}
throw error
}
@@ -87,10 +87,10 @@ export default defineEventHandler(async (event) => {
logActivity(event, {
action: 'tags',
- key: 'images/batch-tags',
+ key: 'media/batch-tags',
originalName: action === 'add'
- ? `批量打标(${keys.length} 张)`
- : `批量移除标签(${keys.length} 张)`,
+ ? `批量打标(${keys.length} 个媒体)`
+ : `批量移除标签(${keys.length} 个媒体)`,
userId: user.id
})