refactor: 重构设置、API、图库与存储页面前端结构。

将操作日志并入设置侧栏,补齐检查更新提示与版本接口刷新;拆分各模块组件并修复图库搜索分页变量。
This commit is contained in:
O96u committed 2026-09-01 17:15:02 +08:00
1 parent 270af4e707
commit ac65c1eb9d
51 files changed
+5119 -2059

No files matched your search

+17 -2
View File
@@ -9,7 +9,7 @@ import { createApiError } from '../../utils/api-error'
import { getUploadSourcesForKeys, listUserIdUsernameMap } from '../../utils/db'
import { mapStoredImageToItem } from '../../utils/image-response'
import { listStorageBackendNameMap } from '../../utils/storage-backends'
import { readBackendIdQuery } from '../../utils/image-query'
import { readBackendIdQuery, readContentTypeQuery, readUploadSourceQuery } from '../../utils/image-query'
import { listImages } from '../../utils/storage'
export default defineEventHandler(async (event) => {
@@ -31,9 +31,24 @@ export default defineEventHandler(async (event) => {
if (backendId === null) {
createApiError(event, 'INVALID_REQUEST', '无效的存储后端', 400)
}
const contentType = readContentTypeQuery(query)
if (contentType === null) {
createApiError(event, 'INVALID_REQUEST', '无效的图片类型', 400)
}
const uploadSource = readUploadSourceQuery(query)
if (uploadSource === null) {
createApiError(event, 'INVALID_REQUEST', '无效的上传来源', 400)
}
const userFilter = await getImageUserFilter(event)
const listing = await listImages({ limit, page, userFilter, backendId })
const listing = await listImages({
limit,
page,
userFilter,
backendId,
contentType,
uploadSource
})
const user = await getCurrentUser(event)
const ownerMap = user?.role === 'admin' ? listUserIdUsernameMap() : undefined
+18 -2
View File
@@ -9,7 +9,7 @@ import { createApiError } from '../../utils/api-error'
import { getUploadSourcesForKeys, listUserIdUsernameMap } from '../../utils/db'
import { mapStoredImageToItem } from '../../utils/image-response'
import { listStorageBackendNameMap } from '../../utils/storage-backends'
import { readBackendIdQuery } from '../../utils/image-query'
import { readBackendIdQuery, readContentTypeQuery, readUploadSourceQuery } from '../../utils/image-query'
import { searchImages } from '../../utils/storage'
export default defineEventHandler(async (event) => {
@@ -40,9 +40,25 @@ export default defineEventHandler(async (event) => {
if (backendId === null) {
createApiError(event, 'INVALID_REQUEST', '无效的存储后端', 400)
}
const contentType = readContentTypeQuery(query)
if (contentType === null) {
createApiError(event, 'INVALID_REQUEST', '无效的图片类型', 400)
}
const uploadSource = readUploadSourceQuery(query)
if (uploadSource === null) {
createApiError(event, 'INVALID_REQUEST', '无效的上传来源', 400)
}
const userFilter = await getImageUserFilter(event)
const result = await searchImages({ query: q, limit, page, userFilter, backendId })
const result = await searchImages({
query: q,
limit,
page,
userFilter,
backendId,
contentType,
uploadSource
})
const user = await getCurrentUser(event)
const ownerMap = user?.role === 'admin' ? listUserIdUsernameMap() : undefined
+39 -5
View File
@@ -7,6 +7,34 @@ import {
getFolderStorageStats,
getUserScopedStorageStats
} from '../utils/storage'
import { buildBackendCapacity } from '../utils/storage-capacity'
import { getActiveBackendRow } from '../utils/storage/resolver'
interface StorageUsageStat {
usedBytes: number
totalBytes: number | null
percent: number | null
}
async function resolveStorageUsage(usedBytes: number): Promise<StorageUsageStat> {
const backend = getActiveBackendRow()
if (!backend) {
return { usedBytes, totalBytes: null, percent: null }
}
const capacity = await buildBackendCapacity(
backend.id,
backend.type,
usedBytes,
backend.quota_bytes
)
return {
usedBytes,
totalBytes: capacity.totalBytes,
percent: capacity.percent
}
}
export default defineEventHandler(async (event) => {
const user = await requireUserAuth(event)
@@ -14,25 +42,30 @@ export default defineEventHandler(async (event) => {
try {
if (user.role === 'admin' && userFilter === 'admin') {
const [activity, storedCount, byFolder] = await Promise.all([
Promise.resolve(getActivityStats()),
const activity = getActivityStats()
const [storedCount, byFolder, storageUsage] = await Promise.all([
countImages(),
getFolderStorageStats()
getFolderStorageStats(),
resolveStorageUsage(activity.uploadBytesTotal)
])
return {
...activity,
storedCount,
byFolder,
userCount: countUsers()
userCount: countUsers(),
storageUsage
}
}
const scoped = await getUserScopedStorageStats(user.id)
const storageUsage = await resolveStorageUsage(scoped.uploadBytesTotal)
return {
uploadToday: scoped.uploadToday,
uploadYesterday: scoped.uploadYesterday,
uploadMonth: scoped.uploadMonth,
uploadLastMonth: scoped.uploadLastMonth,
deleteToday: 0,
deleteMonth: 0,
uploadTotal: scoped.storedCount,
@@ -44,7 +77,8 @@ export default defineEventHandler(async (event) => {
count: item.count
})),
storedCount: scoped.storedCount,
byFolder: scoped.byFolder
byFolder: scoped.byFolder,
storageUsage
}
} catch (error) {
logException('stats failed', error)
+3 -1
View File
@@ -9,7 +9,9 @@ export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
const currentVersion = String(config.appVersion ?? '')
const latest = await fetchLatestGitHubRelease()
const query = getQuery(event)
const force = query.refresh === '1' || query.refresh === 'true'
const latest = await fetchLatestGitHubRelease(force)
if (!latest) {
return {