增加仓库管理功能

This commit is contained in:
2025-08-21 14:59:52 +08:00
parent f2e38f4355
commit 84b712246d
10 changed files with 2060 additions and 4 deletions
+1
View File
@@ -32,6 +32,7 @@ onMounted(async () => {
<RouterLink to="/search" class="nav-link" v-if="isLoggedIn">搜索</RouterLink>
<RouterLink to="/downloads" class="nav-link" v-if="isLoggedIn">下载管理</RouterLink>
<RouterLink to="/artists" class="nav-link" v-if="isLoggedIn">作者管理</RouterLink>
<RouterLink to="/repository" class="nav-link" v-if="isLoggedIn">仓库管理</RouterLink>
</div>
<div class="nav-auth">
+6
View File
@@ -44,6 +44,12 @@ const router = createRouter({
name: 'artists',
component: () => import('@/views/ArtistsView.vue'),
meta: { requiresAuth: true }
},
{
path: '/repository',
name: 'repository',
component: () => import('@/views/RepositoryView.vue'),
meta: { requiresAuth: true }
}
]
})
+187
View File
@@ -0,0 +1,187 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export interface RepositoryConfig {
downloadDir: string
fileStructure: 'artist/artwork' | 'artwork' | 'flat'
namingPattern: string
maxFileSize: number
allowedExtensions: string[]
autoMigration: boolean
migrationRules: any[]
}
export interface RepositoryStats {
totalArtworks: number
totalArtists: number
totalSize: number
diskUsage: {
total: number
used: number
free: number
usagePercent: number
}
lastScan: string
}
export interface Artist {
name: string
artworkCount: number
totalSize: number
lastUpdated: number | null
}
export interface ArtworkFile {
name: string
path: string
size: number
extension: string
modifiedAt: string
}
export interface Artwork {
id: string
title: string
artist: string
artistPath: string
path: string
files: ArtworkFile[]
size: number
createdAt: string
}
export interface MigrationResult {
success: boolean
message: string
log: Array<{
type: string
id: string
title: string
source?: string
target?: string
status: 'success' | 'skipped'
reason?: string
}>
totalMigrated: number
}
export const useRepositoryStore = defineStore('repository', () => {
const config = ref<RepositoryConfig | null>(null)
const stats = ref<RepositoryStats | null>(null)
// API基础URL
const API_BASE = '/api/repository'
// 通用API调用函数
const apiCall = async (endpoint: string, options: RequestInit = {}) => {
const response = await fetch(`${API_BASE}${endpoint}`, {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
})
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(errorData.message || `HTTP ${response.status}`)
}
const data = await response.json()
return data.data || data
}
// 初始化仓库
const initialize = async () => {
return await apiCall('/initialize', { method: 'POST' })
}
// 获取配置
const getConfig = async (): Promise<RepositoryConfig> => {
const result = await apiCall('/config')
config.value = result
return result
}
// 更新配置
const updateConfig = async (newConfig: Partial<RepositoryConfig>) => {
const result = await apiCall('/config', {
method: 'PUT',
body: JSON.stringify(newConfig),
})
if (config.value) {
config.value = { ...config.value, ...newConfig }
}
return result
}
// 获取统计信息
const getStats = async (): Promise<RepositoryStats> => {
const result = await apiCall('/stats')
stats.value = result
return result
}
// 获取作者列表
const getArtists = async (offset = 0, limit = 50) => {
return await apiCall(`/artists?offset=${offset}&limit=${limit}`)
}
// 获取作者作品
const getArtworksByArtist = async (artistName: string, offset = 0, limit = 20) => {
return await apiCall(`/artists/${encodeURIComponent(artistName)}/artworks?offset=${offset}&limit=${limit}`)
}
// 搜索作品
const searchArtworks = async (query: string, offset = 0, limit = 20) => {
return await apiCall(`/search?q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}`)
}
// 获取作品详情
const getArtwork = async (artworkId: string): Promise<Artwork> => {
return await apiCall(`/artworks/${artworkId}`)
}
// 删除作品
const deleteArtwork = async (artworkId: string) => {
return await apiCall(`/artworks/${artworkId}`, { method: 'DELETE' })
}
// 迁移旧项目
const migrateOldProjects = async (sourceDir: string): Promise<MigrationResult> => {
return await apiCall('/migrate', {
method: 'POST',
body: JSON.stringify({ sourceDir }),
})
}
// 获取文件信息
const getFileInfo = async (filePath: string) => {
return await apiCall(`/file-info?path=${encodeURIComponent(filePath)}`)
}
// 获取目录结构
const getDirectory = async (dirPath = '') => {
return await apiCall(`/directory?path=${encodeURIComponent(dirPath)}`)
}
return {
// 状态
config,
stats,
// 方法
initialize,
getConfig,
updateConfig,
getStats,
getArtists,
getArtworksByArtist,
searchArtworks,
getArtwork,
deleteArtwork,
migrateOldProjects,
getFileInfo,
getDirectory,
}
})
File diff suppressed because it is too large Load Diff