release: v1.2.5 — 图库页、图片详情弹层与列表体验优化

This commit is contained in:
O96u committed 2026-08-31 16:05:53 +08:00
1 parent 81dcc2c15e
commit 270af4e707
22 files changed
+587 -52

No files matched your search

+3 -2
View File
@@ -6,7 +6,7 @@ import {
MAX_LIST_LIMIT
} from '../../utils/constants'
import { createApiError } from '../../utils/api-error'
import { listUserIdUsernameMap } from '../../utils/db'
import { getUploadSourcesForKeys, listUserIdUsernameMap } from '../../utils/db'
import { mapStoredImageToItem } from '../../utils/image-response'
import { listStorageBackendNameMap } from '../../utils/storage-backends'
import { readBackendIdQuery } from '../../utils/image-query'
@@ -38,8 +38,9 @@ export default defineEventHandler(async (event) => {
const user = await getCurrentUser(event)
const ownerMap = user?.role === 'admin' ? listUserIdUsernameMap() : undefined
const backendMap = listStorageBackendNameMap()
const sourceMap = getUploadSourcesForKeys(listing.items.map(item => item.key))
const items = listing.items.map(stored =>
mapStoredImageToItem(event, stored, { ownerMap, backendMap })
mapStoredImageToItem(event, stored, { ownerMap, backendMap, sourceMap })
)
items.sort((a, b) => b.uploadedAt.localeCompare(a.uploadedAt))
+3 -2
View File
@@ -6,7 +6,7 @@ import {
MAX_LIST_LIMIT
} from '../../utils/constants'
import { createApiError } from '../../utils/api-error'
import { listUserIdUsernameMap } from '../../utils/db'
import { getUploadSourcesForKeys, listUserIdUsernameMap } from '../../utils/db'
import { mapStoredImageToItem } from '../../utils/image-response'
import { listStorageBackendNameMap } from '../../utils/storage-backends'
import { readBackendIdQuery } from '../../utils/image-query'
@@ -47,8 +47,9 @@ export default defineEventHandler(async (event) => {
const user = await getCurrentUser(event)
const ownerMap = user?.role === 'admin' ? listUserIdUsernameMap() : undefined
const backendMap = listStorageBackendNameMap()
const sourceMap = getUploadSourcesForKeys(result.items.map(item => item.key))
const items = result.items.map(stored =>
mapStoredImageToItem(event, stored, { ownerMap, backendMap })
mapStoredImageToItem(event, stored, { ownerMap, backendMap, sourceMap })
)
items.sort((a, b) => b.uploadedAt.localeCompare(a.uploadedAt))
+28
View File
@@ -445,6 +445,34 @@ export function insertActivityLog(input: ActivityLogInput): void {
}
}
/** 按图片 key 查最近一次上传记录的来源(网页 / API) */
export function getUploadSourcesForKeys(keys: string[]): Map<string, LogSource> {
const result = new Map<string, LogSource>()
if (!keys.length) return result
const placeholders = keys.map(() => '?').join(', ')
const rows = getDb().prepare(`
SELECT al.key, al.source
FROM activity_logs al
INNER JOIN (
SELECT key, MAX(id) AS max_id
FROM activity_logs
WHERE action = 'upload' AND key IN (${placeholders})
GROUP BY key
) latest ON al.id = latest.max_id
`).all(...keys) as Array<{ key: string, source: string }>
for (const row of rows) {
const raw = row.source
const source = raw === 'twikoo' ? 'api' : raw
if (source === 'web' || source === 'api') {
result.set(row.key, source)
}
}
return result
}
export function listActivityLogs(options: {
limit: number
page?: number
+8 -8
View File
@@ -1,5 +1,6 @@
import type { H3Event } from 'h3'
import type { ImageItem } from '~/types/image'
import type { LogSource } from './db'
import type { AllowedMimeType } from './constants'
import type { StoredImage } from './storage'
import { getImageBaseUrl, isHideFolderInUrl } from './env'
@@ -50,6 +51,7 @@ export function mapStoredImageToItem(
options?: {
ownerMap?: Map<number, string>
backendMap?: Map<string, { name: string, type: StorageBackendType }>
sourceMap?: Map<string, LogSource>
}
): ImageItem {
const item = buildImageItem({
@@ -64,16 +66,14 @@ export function mapStoredImageToItem(
const owner = resolveImageOwner(stored.userId, options?.ownerMap)
const storage = resolveImageStorage(stored.backendId, options?.backendMap)
const uploadSource = options?.sourceMap?.get(stored.key)
if (owner || storage) {
return {
...item,
...(owner ? { owner } : {}),
...(storage ? { storage } : {})
}
return {
...item,
...(owner ? { owner } : {}),
...(storage ? { storage } : {}),
...(uploadSource ? { uploadSource } : {})
}
return item
}
export function buildImageUrl(
+11 -8
View File
@@ -169,14 +169,17 @@ export async function processSingleImageUpload(
})
return {
item: buildImageItem({
key,
event,
originalName,
contentType: compressed.mime,
size: compressed.bytes.byteLength,
uploadedAt
})
item: {
...buildImageItem({
key,
event,
originalName,
contentType: compressed.mime,
size: compressed.bytes.byteLength,
uploadedAt
}),
uploadSource: input.source ?? 'web'
}
}
}