sa2kit 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{UniversalFileService-CEZRJ87g.d.mts → UniversalFileService-BuHN-jrR.d.ts} +47 -259
- package/dist/{UniversalFileService-CEZRJ87g.d.ts → UniversalFileService-CGGzYeeF.d.mts} +47 -259
- package/dist/{chunk-3XG5OHFD.mjs → chunk-CIVO4R6N.mjs} +2 -2
- package/dist/{chunk-3XG5OHFD.mjs.map → chunk-CIVO4R6N.mjs.map} +1 -1
- package/dist/chunk-EV6BCVOQ.mjs +204 -0
- package/dist/chunk-EV6BCVOQ.mjs.map +1 -0
- package/dist/chunk-W35VTQAW.js +211 -0
- package/dist/chunk-W35VTQAW.js.map +1 -0
- package/dist/{chunk-HWJ34NL6.js → chunk-ZRAW3HXA.js} +2 -2
- package/dist/{chunk-HWJ34NL6.js.map → chunk-ZRAW3HXA.js.map} +1 -1
- package/dist/drizzle-schema-BNhqj2AZ.d.mts +1114 -0
- package/dist/drizzle-schema-BNhqj2AZ.d.ts +1114 -0
- package/dist/mmd/admin/index.d.mts +487 -0
- package/dist/mmd/admin/index.d.ts +487 -0
- package/dist/mmd/admin/index.js +871 -0
- package/dist/mmd/admin/index.js.map +1 -0
- package/dist/mmd/admin/index.mjs +822 -0
- package/dist/mmd/admin/index.mjs.map +1 -0
- package/dist/mmd/index.d.mts +4 -193
- package/dist/mmd/index.d.ts +4 -193
- package/dist/mmd/server/index.d.mts +138 -0
- package/dist/mmd/server/index.d.ts +138 -0
- package/dist/mmd/server/index.js +245 -0
- package/dist/mmd/server/index.js.map +1 -0
- package/dist/mmd/server/index.mjs +207 -0
- package/dist/mmd/server/index.mjs.map +1 -0
- package/dist/testYourself/index.d.mts +145 -0
- package/dist/testYourself/index.d.ts +145 -0
- package/dist/testYourself/index.js +1004 -0
- package/dist/testYourself/index.js.map +1 -0
- package/dist/testYourself/index.mjs +993 -0
- package/dist/testYourself/index.mjs.map +1 -0
- package/dist/types-Bc_p-zAR.d.mts +194 -0
- package/dist/types-Bc_p-zAR.d.ts +194 -0
- package/dist/types-CK4We_aI.d.mts +270 -0
- package/dist/types-CK4We_aI.d.ts +270 -0
- package/dist/universalFile/index.d.mts +3 -2
- package/dist/universalFile/index.d.ts +3 -2
- package/dist/universalFile/index.js +48 -10
- package/dist/universalFile/index.js.map +1 -1
- package/dist/universalFile/index.mjs +43 -5
- package/dist/universalFile/index.mjs.map +1 -1
- package/dist/universalFile/server/index.d.mts +3 -2
- package/dist/universalFile/server/index.d.ts +3 -2
- package/dist/universalFile/server/index.js +239 -7
- package/dist/universalFile/server/index.js.map +1 -1
- package/dist/universalFile/server/index.mjs +234 -2
- package/dist/universalFile/server/index.mjs.map +1 -1
- package/package.json +19 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/mmd/admin/types.ts","../../../src/mmd/admin/components/MmdResourceSelector.tsx","../../../src/mmd/admin/components/MmdPlaylistEditor.tsx","../../../src/mmd/admin/components/MmdAdminPanel.tsx","../../../src/mmd/admin/utils.ts"],"names":["useState","React","Film","FileText","Music","useCallback","useEffect","JSZip","Upload","CheckCircle2","X","Loader2","AlertTriangle","Search","Save","Settings","ChevronUp","ChevronDown","Plus","GripVertical","Trash2","List","Database","BarChart3"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * MMD 后台管理类型定义\n * \n * 这个文件定义了MMD后台管理系统的所有TypeScript类型\n * 包括前端组件使用的类型和后端API的类型\n * \n * @package sa2kit/mmd/admin\n */\n\nimport type { FileMetadata } from '../../universalFile/types';\nimport type { \n MMDResources, \n MMDPlaylistNode, \n MMDPlaylistConfig,\n MMDResourceItem,\n ResourceOption \n} from '../types';\n\n// ============= 数据库映射类型 =============\n\n/**\n * 播放列表配置(数据库格式)\n */\nexport interface MmdPlaylistDB {\n id: string;\n name: string;\n description?: string;\n loop: boolean;\n preloadStrategy: 'none' | 'next' | 'all';\n autoPlay: boolean;\n thumbnailFileId?: string;\n status: 'draft' | 'published' | 'archived';\n sortOrder: number;\n config?: Record<string, any>;\n createdBy: string;\n createdAt: Date;\n updatedAt: Date;\n deletedAt?: Date;\n}\n\n/**\n * 播放节点配置(数据库格式)\n */\nexport interface MmdPlaylistNodeDB {\n id: string;\n playlistId: string;\n name: string;\n description?: string;\n loop: boolean;\n duration?: number;\n thumbnailFileId?: string;\n sortOrder: number;\n modelFileId: string;\n motionFileId?: string;\n cameraFileId?: string;\n audioFileId?: string;\n stageModelFileId?: string;\n additionalMotionFileIds?: string[];\n config?: Record<string, any>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * 资源选项配置(数据库格式)\n */\nexport interface MmdResourceOptionDB {\n id: string;\n name: string;\n description?: string;\n resourceType: 'model' | 'motion' | 'camera' | 'audio' | 'stage';\n fileId: string;\n thumbnailFileId?: string;\n tags?: string[];\n sortOrder: number;\n isActive: boolean;\n createdBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * 预设项配置(数据库格式)\n */\nexport interface MmdPresetItemDB {\n id: string;\n name: string;\n description?: string;\n thumbnailFileId?: string;\n modelFileId: string;\n motionFileId?: string;\n cameraFileId?: string;\n audioFileId?: string;\n stageModelFileId?: string;\n additionalMotionFileIds?: string[];\n sortOrder: number;\n isActive: boolean;\n tags?: string[];\n createdBy: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\n// ============= 前端展示类型 =============\n\n/**\n * 播放列表配置(包含文件URL映射)\n */\nexport interface MmdPlaylistWithFiles extends Omit<MmdPlaylistDB, 'thumbnailFileId'> {\n thumbnailUrl?: string;\n nodes: MmdPlaylistNodeWithFiles[];\n}\n\n/**\n * 播放节点配置(包含文件URL映射)\n */\nexport interface MmdPlaylistNodeWithFiles extends Omit<\n MmdPlaylistNodeDB,\n 'modelFileId' | 'motionFileId' | 'cameraFileId' | 'audioFileId' | 'stageModelFileId' | 'thumbnailFileId' | 'additionalMotionFileIds'\n> {\n thumbnailUrl?: string;\n modelUrl: string;\n motionUrl?: string;\n cameraUrl?: string;\n audioUrl?: string;\n stageModelUrl?: string;\n additionalMotionUrls?: string[];\n}\n\n/**\n * 资源选项配置(包含文件URL映射)\n */\nexport interface MmdResourceOptionWithFile extends Omit<MmdResourceOptionDB, 'fileId' | 'thumbnailFileId'> {\n fileUrl: string;\n thumbnailUrl?: string;\n fileMetadata?: Partial<FileMetadata>;\n}\n\n/**\n * 预设项配置(包含文件URL映射)\n */\nexport interface MmdPresetItemWithFiles extends Omit<\n MmdPresetItemDB,\n 'modelFileId' | 'motionFileId' | 'cameraFileId' | 'audioFileId' | 'stageModelFileId' | 'thumbnailFileId' | 'additionalMotionFileIds'\n> {\n thumbnailUrl?: string;\n modelUrl: string;\n motionUrl?: string;\n cameraUrl?: string;\n audioUrl?: string;\n stageModelUrl?: string;\n additionalMotionUrls?: string[];\n}\n\n// ============= API 请求/响应类型 =============\n\n/**\n * 创建播放列表请求\n */\nexport interface CreatePlaylistRequest {\n name: string;\n description?: string;\n loop?: boolean;\n preloadStrategy?: 'none' | 'next' | 'all';\n autoPlay?: boolean;\n thumbnailFileId?: string;\n config?: Record<string, any>;\n}\n\n/**\n * 更新播放列表请求\n */\nexport interface UpdatePlaylistRequest extends Partial<CreatePlaylistRequest> {\n status?: 'draft' | 'published' | 'archived';\n sortOrder?: number;\n}\n\n/**\n * 创建播放节点请求\n */\nexport interface CreatePlaylistNodeRequest {\n playlistId: string;\n name: string;\n description?: string;\n loop?: boolean;\n duration?: number;\n thumbnailFileId?: string;\n sortOrder?: number;\n modelFileId: string;\n motionFileId?: string;\n cameraFileId?: string;\n audioFileId?: string;\n stageModelFileId?: string;\n additionalMotionFileIds?: string[];\n config?: Record<string, any>;\n}\n\n/**\n * 更新播放节点请求\n */\nexport interface UpdatePlaylistNodeRequest extends Partial<Omit<CreatePlaylistNodeRequest, 'playlistId'>> {}\n\n/**\n * 创建资源选项请求\n */\nexport interface CreateResourceOptionRequest {\n name: string;\n description?: string;\n resourceType: 'model' | 'motion' | 'camera' | 'audio' | 'stage';\n fileId: string;\n thumbnailFileId?: string;\n tags?: string[];\n sortOrder?: number;\n}\n\n/**\n * 更新资源选项请求\n */\nexport interface UpdateResourceOptionRequest extends Partial<CreateResourceOptionRequest> {\n isActive?: boolean;\n}\n\n/**\n * 创建预设项请求\n */\nexport interface CreatePresetItemRequest {\n name: string;\n description?: string;\n thumbnailFileId?: string;\n modelFileId: string;\n motionFileId?: string;\n cameraFileId?: string;\n audioFileId?: string;\n stageModelFileId?: string;\n additionalMotionFileIds?: string[];\n tags?: string[];\n sortOrder?: number;\n}\n\n/**\n * 更新预设项请求\n */\nexport interface UpdatePresetItemRequest extends Partial<CreatePresetItemRequest> {\n isActive?: boolean;\n}\n\n/**\n * 分页查询参数\n */\nexport interface PaginationQuery {\n page?: number;\n pageSize?: number;\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n}\n\n/**\n * 播放列表查询参数\n */\nexport interface PlaylistQuery extends PaginationQuery {\n status?: 'draft' | 'published' | 'archived';\n createdBy?: string;\n search?: string;\n}\n\n/**\n * 资源选项查询参数\n */\nexport interface ResourceOptionQuery extends PaginationQuery {\n resourceType?: 'model' | 'motion' | 'camera' | 'audio' | 'stage';\n tags?: string[];\n isActive?: boolean;\n search?: string;\n}\n\n/**\n * 预设项查询参数\n */\nexport interface PresetItemQuery extends PaginationQuery {\n tags?: string[];\n isActive?: boolean;\n search?: string;\n}\n\n/**\n * 分页响应\n */\nexport interface PaginationResponse<T> {\n items: T[];\n total: number;\n page: number;\n pageSize: number;\n totalPages: number;\n}\n\n// ============= 转换辅助类型 =============\n\n/**\n * 文件ID到URL的映射\n */\nexport interface FileIdToUrlMap {\n [fileId: string]: string;\n}\n\n/**\n * 批量文件URL查询响应\n */\nexport interface BatchFileUrlsResponse {\n fileUrls: FileIdToUrlMap;\n missingFileIds: string[];\n}\n\n/**\n * MMD资源文件上传配置\n */\nexport interface MmdFileUploadConfig {\n /** 模块ID(用于文件分类) */\n moduleId: 'mmd-models' | 'mmd-motions' | 'mmd-cameras' | 'mmd-audios' | 'mmd-stages' | 'mmd-thumbnails';\n /** 允许的文件类型 */\n acceptedTypes: string[];\n /** 最大文件大小(MB) */\n maxFileSize: number;\n /** 文件描述 */\n description: string;\n /** 额外提示 */\n hint?: string;\n}\n\n/**\n * MMD资源类型配置映射\n */\nexport const MMD_RESOURCE_TYPE_CONFIGS: Record<string, MmdFileUploadConfig> = {\n model: {\n moduleId: 'mmd-models',\n acceptedTypes: ['.zip'],\n maxFileSize: 150,\n description: 'MMD模型压缩包 (ZIP)',\n hint: '请上传包含 PMX/贴图等完整目录的 ZIP 压缩包,保持原始文件结构',\n },\n motion: {\n moduleId: 'mmd-motions',\n acceptedTypes: ['.vmd'],\n maxFileSize: 20,\n description: 'MMD动作文件',\n },\n camera: {\n moduleId: 'mmd-cameras',\n acceptedTypes: ['.vmd'],\n maxFileSize: 10,\n description: 'MMD相机动画文件',\n },\n audio: {\n moduleId: 'mmd-audios',\n acceptedTypes: ['.mp3', '.wav', '.ogg', '.m4a'],\n maxFileSize: 20,\n description: '音频文件',\n },\n stage: {\n moduleId: 'mmd-stages',\n acceptedTypes: ['.zip'],\n maxFileSize: 200,\n description: '舞台/场景压缩包 (ZIP)',\n hint: '需将舞台模型与依赖贴图一起打包 ZIP,并保持目录结构',\n },\n thumbnail: {\n moduleId: 'mmd-thumbnails',\n acceptedTypes: ['.jpg', '.jpeg', '.png', '.webp'],\n maxFileSize: 5,\n description: '缩略图',\n },\n};\n\n// ============= 组件属性类型 =============\n\n/**\n * MMD后台管理器组件属性\n */\nexport interface MmdAdminPanelProps {\n /** UniversalFile服务实例(用于文件上传) */\n fileService: any; // UniversalFileService\n /** 当前用户ID */\n userId: string;\n /** API基础路径 */\n apiBaseUrl?: string;\n /** 是否显示高级选项 */\n showAdvancedOptions?: boolean;\n /** 自定义样式类名 */\n className?: string;\n}\n\n/**\n * 播放列表编辑器组件属性\n */\nexport interface PlaylistEditorProps {\n /** 播放列表ID(编辑模式)或 undefined(创建模式) */\n playlistId?: string;\n /** UniversalFile服务实例 */\n fileService: any;\n /** 当前用户ID */\n userId: string;\n /** 保存回调 */\n onSave?: (playlist: MmdPlaylistWithFiles) => void;\n /** 取消回调 */\n onCancel?: () => void;\n}\n\n/**\n * 资源选择器组件属性\n */\nexport interface ResourceSelectorProps {\n /** 资源类型 */\n resourceType: 'model' | 'motion' | 'camera' | 'audio' | 'stage';\n /** UniversalFile服务实例 */\n fileService: any;\n /** 当前用户ID */\n userId: string;\n /** 当前选中的文件ID */\n value?: string;\n /** 选择回调 */\n onChange: (fileId: string, fileUrl: string) => void;\n /** 是否必填 */\n required?: boolean;\n}\n\n// ============= 数据转换函数类型 =============\n\n/**\n * 播放列表转换为前端格式\n */\nexport type PlaylistToFrontendConverter = (\n playlist: MmdPlaylistDB,\n nodes: MmdPlaylistNodeDB[],\n fileUrls: FileIdToUrlMap\n) => MmdPlaylistWithFiles;\n\n/**\n * 播放列表转换为MMD组件格式\n */\nexport type PlaylistToMmdConfigConverter = (\n playlist: MmdPlaylistWithFiles\n) => MMDPlaylistConfig;\n\n/**\n * 资源选项转换为前端格式\n */\nexport type ResourceOptionToFrontendConverter = (\n option: MmdResourceOptionDB,\n fileUrls: FileIdToUrlMap\n) => MmdResourceOptionWithFile;\n\n/**\n * 预设项转换为前端格式\n */\nexport type PresetItemToFrontendConverter = (\n item: MmdPresetItemDB,\n fileUrls: FileIdToUrlMap\n) => MmdPresetItemWithFiles;\n\n/**\n * 预设项转换为MMD资源格式\n */\nexport type PresetItemToMmdResourceConverter = (\n item: MmdPresetItemWithFiles\n) => MMDResourceItem;\n\n","/**\n * MMD 资源选择器组件\n * \n * 集成 UniversalFile 文件上传组件,支持:\n * - 文件上传到OSS\n * - 文件列表浏览\n * - 文件选择\n * - 文件预览\n * \n * @package sa2kit/mmd/admin\n */\n\n'use client';\n\nimport React, { useState, useEffect, useCallback } from 'react';\nimport JSZip from 'jszip';\nimport {\n Upload,\n FileText,\n Image as ImageIcon,\n Film,\n Music,\n CheckCircle2,\n Search,\n Loader2,\n X,\n AlertTriangle,\n} from 'lucide-react';\n\nimport { MMD_RESOURCE_TYPE_CONFIGS } from '../types';\nimport type { ResourceSelectorProps, MmdResourceOptionDB } from '../types';\nimport type { FileMetadata } from '../../../universalFile/types';\n\n/**\n * MMD资源选择器\n */\nexport const MmdResourceSelector: React.FC<ResourceSelectorProps> = ({\n resourceType,\n fileService,\n userId,\n value,\n onChange,\n required = false,\n}) => {\n const [selectedFileId, setSelectedFileId] = useState<string | undefined>(value);\n const [selectedFile, setSelectedFile] = useState<FileMetadata | null>(null);\n const [files, setFiles] = useState<FileMetadata[]>([]);\n const [loading, setLoading] = useState(false);\n const [uploading, setUploading] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [showUploader, setShowUploader] = useState(false);\n const [zipValidationError, setZipValidationError] = useState<string | null>(null);\n\n // 从配置获取资源类型信息\n const config = MMD_RESOURCE_TYPE_CONFIGS[resourceType];\n\n // 防御性检查(理论上不会发生,因为 resourceType 为受控枚举)\n if (!config) {\n return (\n <div className=\"p-4 bg-red-50 text-red-600 rounded-lg\">\n 未找到资源类型配置:{resourceType}\n </div>\n );\n }\n\n // 获取文件图标\n const getFileIcon = () => {\n switch (resourceType) {\n case 'model':\n case 'stage':\n return <Film className=\"w-5 h-5\" />;\n case 'motion':\n case 'camera':\n return <FileText className=\"w-5 h-5\" />;\n case 'audio':\n return <Music className=\"w-5 h-5\" />;\n default:\n return <FileText className=\"w-5 h-5\" />;\n }\n };\n\n // 加载文件列表\n const loadFiles = useCallback(async () => {\n if (!fileService || !config) return;\n\n setLoading(true);\n try {\n const result = await fileService.queryFiles({\n moduleId: config.moduleId,\n pageSize: 50,\n page: 1,\n sortBy: 'uploadTime',\n sortOrder: 'desc',\n });\n\n setFiles(result.items || []);\n } catch (error) {\n console.error('加载文件列表失败:', error);\n } finally {\n setLoading(false);\n }\n }, [fileService, config]);\n\n // 初始加载\n useEffect(() => {\n loadFiles();\n }, [loadFiles]);\n\n // 加载选中的文件信息\n useEffect(() => {\n if (selectedFileId && fileService) {\n fileService\n .getFileMetadata(selectedFileId)\n .then((file: FileMetadata) => setSelectedFile(file))\n .catch((error: any) => console.error('加载文件信息失败:', error));\n } else {\n setSelectedFile(null);\n }\n }, [selectedFileId, fileService]);\n\n // 处理文件选择\n const handleFileSelect = (file: FileMetadata) => {\n setSelectedFileId(file.id);\n setSelectedFile(file);\n \n // 获取文件URL并回调\n fileService\n .getFileUrl(file.id)\n .then((url: string) => onChange(file.id, url))\n .catch((error: any) => console.error('获取文件URL失败:', error));\n };\n\n const validateZipContents = async (buffer: ArrayBuffer, type: 'model' | 'stage') => {\n const zip = await JSZip.loadAsync(buffer);\n const entries = Object.keys(zip.files);\n\n if (!entries.length) {\n throw new Error('压缩包为空,请检查文件内容');\n }\n\n const hasModel =\n entries.some((name) => /\\.[pP][mM][xX]$/.test(name)) ||\n (type === 'stage' && entries.some((name) => /\\.[pP][mM][dD]$/.test(name)));\n\n const hasAssets = entries.some((name) =>\n /\\.(png|jpg|jpeg|bmp|tga|dds|spa|sph)$/i.test(name),\n );\n\n if (!hasModel) {\n throw new Error(type === 'stage' ? '压缩包中未找到 PMX/PMD 舞台模型文件' : '压缩包中未找到 PMX 模型文件');\n }\n\n if (!hasAssets) {\n throw new Error('压缩包中未发现贴图文件,请确认是否包含 texture 目录');\n }\n };\n\n // 处理文件上传\n const handleFileUpload = async (file: File) => {\n if (!fileService) return;\n\n setUploading(true);\n setZipValidationError(null);\n try {\n if (resourceType === 'model' || resourceType === 'stage') {\n const arrayBuffer = await file.arrayBuffer();\n await validateZipContents(arrayBuffer, resourceType);\n }\n\n const fileMetadata = await fileService.uploadFile({\n file,\n moduleId: config.moduleId,\n businessId: userId,\n permission: 'public',\n });\n\n // 刷新文件列表\n await loadFiles();\n\n // 自动选择刚上传的文件\n handleFileSelect(fileMetadata);\n setShowUploader(false);\n } catch (error) {\n console.error('文件上传失败:', error);\n const message = error instanceof Error ? error.message : '未知错误';\n setZipValidationError(message);\n alert(`上传失败: ${message}`);\n } finally {\n setUploading(false);\n }\n };\n\n // 过滤文件列表\n const filteredFiles = files.filter((file) =>\n file.originalName.toLowerCase().includes(searchTerm.toLowerCase())\n );\n\n return (\n <div className=\"space-y-4\">\n {/* 标题和上传按钮 */}\n <div className=\"flex items-center justify-between\">\n <label className=\"flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300\">\n {getFileIcon()}\n {config.description}\n {required && <span className=\"text-red-500\">*</span>}\n </label>\n <button\n onClick={() => setShowUploader(!showUploader)}\n className=\"px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2\"\n >\n <Upload className=\"w-4 h-4\" />\n 上传新文件\n </button>\n </div>\n\n {/* 当前选中的文件 */}\n {selectedFile && (\n <div className=\"p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <CheckCircle2 className=\"w-5 h-5 text-green-600 dark:text-green-400\" />\n <div>\n <div className=\"text-sm font-medium text-gray-900 dark:text-white\">\n {selectedFile.originalName}\n </div>\n <div className=\"text-xs text-gray-500 dark:text-gray-400\">\n {(selectedFile.size / 1024 / 1024).toFixed(2)} MB\n </div>\n </div>\n </div>\n <button\n onClick={() => {\n setSelectedFileId(undefined);\n setSelectedFile(null);\n onChange('', '');\n }}\n className=\"p-1 hover:bg-white/50 dark:hover:bg-black/20 rounded transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n )}\n\n {/* 文件上传区域 */}\n {showUploader && (\n <div className=\"p-4 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg\">\n <div className=\"text-sm text-gray-600 dark:text-gray-400 mb-3 space-y-1\">\n <p>支持的文件类型: {config.acceptedTypes.join(', ')}</p>\n <p>最大文件大小: {config.maxFileSize}MB</p>\n {config.hint && (\n <p className=\"text-xs text-amber-600 dark:text-amber-400\">{config.hint}</p>\n )}\n </div>\n \n <input\n type=\"file\"\n accept={config.acceptedTypes.join(',')}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) {\n // 验证文件大小\n if (file.size > config.maxFileSize * 1024 * 1024) {\n alert(`文件大小超过限制(最大 ${config.maxFileSize}MB)`);\n return;\n }\n handleFileUpload(file);\n }\n }}\n disabled={uploading}\n className=\"w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100 disabled:opacity-50\"\n />\n\n {uploading && (\n <div className=\"mt-3 flex items-center gap-2 text-sm text-blue-600\">\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n 上传中...\n </div>\n )}\n {zipValidationError && (\n <div className=\"mt-3 flex items-center gap-2 text-sm text-amber-600 dark:text-amber-400\">\n <AlertTriangle className=\"w-4 h-4\" />\n {zipValidationError}\n </div>\n )}\n </div>\n )}\n\n {/* 搜索框 */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400\" />\n <input\n type=\"text\"\n placeholder=\"搜索文件...\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n className=\"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n\n {/* 文件列表 */}\n <div className=\"max-h-96 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg divide-y divide-gray-200 dark:divide-gray-700\">\n {loading ? (\n <div className=\"p-8 text-center text-gray-500\">\n <Loader2 className=\"w-6 h-6 animate-spin mx-auto mb-2\" />\n 加载中...\n </div>\n ) : filteredFiles.length === 0 ? (\n <div className=\"p-8 text-center text-gray-500\">\n {searchTerm ? '没有找到匹配的文件' : '暂无文件,请上传'}\n </div>\n ) : (\n filteredFiles.map((file) => (\n <button\n key={file.id}\n onClick={() => handleFileSelect(file)}\n className={`w-full p-3 text-left hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors ${\n selectedFileId === file.id ? 'bg-blue-50 dark:bg-blue-900/20' : ''\n }`}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium text-gray-900 dark:text-white truncate\">\n {file.originalName}\n </div>\n <div className=\"text-xs text-gray-500 dark:text-gray-400 mt-0.5\">\n {(file.size / 1024 / 1024).toFixed(2)} MB •{' '}\n {new Date(file.uploadTime).toLocaleDateString()}\n </div>\n </div>\n {selectedFileId === file.id && (\n <CheckCircle2 className=\"w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0 ml-2\" />\n )}\n </div>\n </button>\n ))\n )}\n </div>\n\n {/* 提示信息 */}\n {required && !selectedFileId && (\n <div className=\"text-sm text-red-600 dark:text-red-400\">\n 请选择一个{config.description}\n </div>\n )}\n </div>\n );\n};\n\n","/**\n * MMD 播放列表编辑器组件\n * \n * 功能:\n * - 创建/编辑播放列表\n * - 添加/删除/排序播放节点\n * - 为每个节点配置资源(模型、动作、音频等)\n * - 预览配置\n * \n * @package sa2kit/mmd/admin\n */\n\n'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport {\n Plus,\n Trash2,\n Save,\n X,\n GripVertical,\n Settings,\n Eye,\n ChevronDown,\n ChevronUp,\n} from 'lucide-react';\n\nimport { MmdResourceSelector } from './MmdResourceSelector';\nimport type { PlaylistEditorProps, MmdPlaylistNodeDB } from '../types';\n\ninterface NodeFormData {\n id?: string;\n name: string;\n description?: string;\n loop: boolean;\n duration?: number;\n sortOrder: number;\n thumbnailFileId?: string;\n modelFileId: string;\n motionFileId?: string;\n cameraFileId?: string;\n audioFileId?: string;\n stageModelFileId?: string;\n additionalMotionFileIds?: string[];\n}\n\n/**\n * 播放列表编辑器\n */\nexport const MmdPlaylistEditor: React.FC<PlaylistEditorProps> = ({\n playlistId,\n fileService,\n userId,\n onSave,\n onCancel,\n}) => {\n // 播放列表基本信息\n const [playlistName, setPlaylistName] = useState('');\n const [playlistDescription, setPlaylistDescription] = useState('');\n const [loop, setLoop] = useState(false);\n const [autoPlay, setAutoPlay] = useState(false);\n const [preloadStrategy, setPreloadStrategy] = useState<'none' | 'next' | 'all'>('none');\n \n // 节点列表\n const [nodes, setNodes] = useState<NodeFormData[]>([]);\n const [expandedNodes, setExpandedNodes] = useState<Set<number>>(new Set([0]));\n \n // UI 状态\n const [saving, setSaving] = useState(false);\n const [showAdvanced, setShowAdvanced] = useState(false);\n\n // 添加新节点\n const addNode = () => {\n const newNode: NodeFormData = {\n name: `节点 ${nodes.length + 1}`,\n description: '',\n loop: false,\n sortOrder: nodes.length,\n modelFileId: '',\n };\n \n setNodes([...nodes, newNode]);\n setExpandedNodes(new Set([...expandedNodes, nodes.length]));\n };\n\n // 删除节点\n const removeNode = (index: number) => {\n const newNodes = nodes.filter((_, i) => i !== index);\n // 重新排序\n newNodes.forEach((node, i) => {\n node.sortOrder = i;\n });\n setNodes(newNodes);\n \n // 更新展开状态\n const newExpanded = new Set<number>();\n expandedNodes.forEach((i) => {\n if (i < index) newExpanded.add(i);\n else if (i > index) newExpanded.add(i - 1);\n });\n setExpandedNodes(newExpanded);\n };\n\n // 移动节点\n const moveNode = (index: number, direction: 'up' | 'down') => {\n const newNodes = [...nodes];\n const targetIndex = direction === 'up' ? index - 1 : index + 1;\n \n if (targetIndex < 0 || targetIndex >= newNodes.length) return;\n if (!newNodes[index] || !newNodes[targetIndex]) return;\n \n // 交换位置\n [newNodes[index], newNodes[targetIndex]] = [newNodes[targetIndex]!, newNodes[index]!];\n \n // 更新 sortOrder\n newNodes.forEach((node, i) => {\n node.sortOrder = i;\n });\n \n setNodes(newNodes);\n \n // 更新展开状态\n const newExpanded = new Set<number>();\n expandedNodes.forEach((i) => {\n if (i === index) newExpanded.add(targetIndex);\n else if (i === targetIndex) newExpanded.add(index);\n else newExpanded.add(i);\n });\n setExpandedNodes(newExpanded);\n };\n\n // 切换节点展开/折叠\n const toggleNode = (index: number) => {\n const newExpanded = new Set(expandedNodes);\n if (newExpanded.has(index)) {\n newExpanded.delete(index);\n } else {\n newExpanded.add(index);\n }\n setExpandedNodes(newExpanded);\n };\n\n // 更新节点\n const updateNode = (index: number, updates: Partial<NodeFormData>) => {\n const newNodes = [...nodes];\n if (!newNodes[index]) return;\n newNodes[index] = { ...newNodes[index]!, ...updates };\n setNodes(newNodes);\n };\n\n // 验证表单\n const validateForm = (): boolean => {\n if (!playlistName.trim()) {\n alert('请输入播放列表名称');\n return false;\n }\n \n if (nodes.length === 0) {\n alert('请至少添加一个播放节点');\n return false;\n }\n \n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || !node.name?.trim()) {\n alert(`节点 ${i + 1}: 请输入节点名称`);\n return false;\n }\n if (!node.modelFileId) {\n alert(`节点 ${i + 1}: 请选择模型文件`);\n return false;\n }\n }\n \n return true;\n };\n\n // 保存\n const handleSave = async () => {\n if (!validateForm()) return;\n \n setSaving(true);\n try {\n // 这里应该调用API保存数据\n // TODO: 实现API调用\n console.log('保存播放列表:', {\n name: playlistName,\n description: playlistDescription,\n loop,\n autoPlay,\n preloadStrategy,\n nodes,\n });\n \n alert('保存成功!');\n onSave?.(null as any); // 实际应该返回保存后的数据\n } catch (error) {\n console.error('保存失败:', error);\n alert(`保存失败: ${error instanceof Error ? error.message : '未知错误'}`);\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <div className=\"max-w-6xl mx-auto p-6 bg-white dark:bg-gray-900 rounded-lg shadow-lg\">\n {/* 标题栏 */}\n <div className=\"flex items-center justify-between mb-6\">\n <h2 className=\"text-2xl font-bold text-gray-900 dark:text-white\">\n {playlistId ? '编辑播放列表' : '创建播放列表'}\n </h2>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handleSave}\n disabled={saving}\n className=\"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50 flex items-center gap-2\"\n >\n <Save className=\"w-4 h-4\" />\n {saving ? '保存中...' : '保存'}\n </button>\n <button\n onClick={onCancel}\n className=\"px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors flex items-center gap-2\"\n >\n <X className=\"w-4 h-4\" />\n 取消\n </button>\n </div>\n </div>\n\n {/* 基本信息 */}\n <div className=\"space-y-4 mb-8 p-6 bg-gray-50 dark:bg-gray-800 rounded-lg\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white mb-4\">\n 基本信息\n </h3>\n \n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 播放列表名称 <span className=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={playlistName}\n onChange={(e) => setPlaylistName(e.target.value)}\n placeholder=\"输入播放列表名称...\"\n className=\"w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 描述\n </label>\n <textarea\n value={playlistDescription}\n onChange={(e) => setPlaylistDescription(e.target.value)}\n placeholder=\"输入描述信息...\"\n rows={3}\n className=\"w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n\n <div className=\"flex items-center gap-6\">\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={loop}\n onChange={(e) => setLoop(e.target.checked)}\n className=\"w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <span className=\"text-sm text-gray-700 dark:text-gray-300\">列表循环</span>\n </label>\n\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={autoPlay}\n onChange={(e) => setAutoPlay(e.target.checked)}\n className=\"w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <span className=\"text-sm text-gray-700 dark:text-gray-300\">自动播放</span>\n </label>\n </div>\n\n {/* 高级选项 */}\n <button\n onClick={() => setShowAdvanced(!showAdvanced)}\n className=\"flex items-center gap-2 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300\"\n >\n <Settings className=\"w-4 h-4\" />\n 高级选项\n {showAdvanced ? <ChevronUp className=\"w-4 h-4\" /> : <ChevronDown className=\"w-4 h-4\" />}\n </button>\n\n {showAdvanced && (\n <div className=\"space-y-4 pt-4 border-t border-gray-200 dark:border-gray-700\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 预加载策略\n </label>\n <select\n value={preloadStrategy}\n onChange={(e) => setPreloadStrategy(e.target.value as any)}\n className=\"w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n >\n <option value=\"none\">不预加载</option>\n <option value=\"next\">预加载下一个</option>\n <option value=\"all\">预加载全部</option>\n </select>\n </div>\n </div>\n )}\n </div>\n\n {/* 播放节点列表 */}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n 播放节点 ({nodes.length})\n </h3>\n <button\n onClick={addNode}\n className=\"px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors flex items-center gap-2\"\n >\n <Plus className=\"w-4 h-4\" />\n 添加节点\n </button>\n </div>\n\n {nodes.length === 0 ? (\n <div className=\"p-8 text-center text-gray-500 border-2 border-dashed border-gray-300 dark:border-gray-700 rounded-lg\">\n 暂无节点,请点击\"添加节点\"按钮开始\n </div>\n ) : (\n nodes.map((node, index) => (\n <div\n key={index}\n className=\"border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden\"\n >\n {/* 节点头部 */}\n <div className=\"flex items-center gap-3 p-4 bg-gray-50 dark:bg-gray-800\">\n <button\n className=\"cursor-move text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n title=\"拖拽排序\"\n >\n <GripVertical className=\"w-5 h-5\" />\n </button>\n\n <button\n onClick={() => toggleNode(index)}\n className=\"flex-1 flex items-center justify-between text-left\"\n >\n <span className=\"font-medium text-gray-900 dark:text-white\">\n {index + 1}. {node.name || '未命名节点'}\n </span>\n {expandedNodes.has(index) ? (\n <ChevronUp className=\"w-5 h-5 text-gray-400\" />\n ) : (\n <ChevronDown className=\"w-5 h-5 text-gray-400\" />\n )}\n </button>\n\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => moveNode(index, 'up')}\n disabled={index === 0}\n className=\"p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-30\"\n title=\"上移\"\n >\n <ChevronUp className=\"w-5 h-5\" />\n </button>\n <button\n onClick={() => moveNode(index, 'down')}\n disabled={index === nodes.length - 1}\n className=\"p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 disabled:opacity-30\"\n title=\"下移\"\n >\n <ChevronDown className=\"w-5 h-5\" />\n </button>\n <button\n onClick={() => removeNode(index)}\n className=\"p-1 text-red-400 hover:text-red-600 dark:hover:text-red-300\"\n title=\"删除\"\n >\n <Trash2 className=\"w-5 h-5\" />\n </button>\n </div>\n </div>\n\n {/* 节点内容 */}\n {expandedNodes.has(index) && (\n <div className=\"p-6 space-y-6 bg-white dark:bg-gray-900\">\n {/* 基本信息 */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 节点名称 <span className=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={node.name}\n onChange={(e) => updateNode(index, { name: e.target.value })}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 时长(秒)\n </label>\n <input\n type=\"number\"\n value={node.duration || ''}\n onChange={(e) => updateNode(index, { duration: parseInt(e.target.value) || undefined })}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\n 描述\n </label>\n <textarea\n value={node.description || ''}\n onChange={(e) => updateNode(index, { description: e.target.value })}\n rows={2}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={node.loop}\n onChange={(e) => updateNode(index, { loop: e.target.checked })}\n className=\"w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <span className=\"text-sm text-gray-700 dark:text-gray-300\">单曲循环</span>\n </label>\n\n {/* 资源选择器 */}\n <div className=\"grid grid-cols-1 gap-6 pt-4 border-t border-gray-200 dark:border-gray-700\">\n <MmdResourceSelector\n resourceType=\"model\"\n fileService={fileService}\n userId={userId}\n value={node.modelFileId}\n onChange={(fileId) => updateNode(index, { modelFileId: fileId })}\n required\n />\n\n <MmdResourceSelector\n resourceType=\"motion\"\n fileService={fileService}\n userId={userId}\n value={node.motionFileId}\n onChange={(fileId) => updateNode(index, { motionFileId: fileId })}\n />\n\n <MmdResourceSelector\n resourceType=\"audio\"\n fileService={fileService}\n userId={userId}\n value={node.audioFileId}\n onChange={(fileId) => updateNode(index, { audioFileId: fileId })}\n />\n </div>\n </div>\n )}\n </div>\n ))\n )}\n </div>\n </div>\n );\n};\n\n","/**\n * MMD 后台管理面板 - 主入口组件\n * \n * 功能:\n * - 播放列表管理(列表、创建、编辑、删除)\n * - 预设项管理\n * - 资源选项管理\n * - 统计信息展示\n * \n * @package sa2kit/mmd/admin\n */\n\n'use client';\n\nimport React, { useState } from 'react';\nimport {\n List,\n Plus,\n Settings,\n Database,\n BarChart3,\n} from 'lucide-react';\n\nimport { MmdPlaylistEditor } from './MmdPlaylistEditor';\nimport type { MmdAdminPanelProps } from '../types';\n\ntype TabType = 'playlists' | 'presets' | 'resources' | 'stats';\n\n/**\n * MMD后台管理面板\n */\nexport const MmdAdminPanel: React.FC<MmdAdminPanelProps> = ({\n fileService,\n userId,\n apiBaseUrl = '/api/mmd',\n showAdvancedOptions = true,\n className = '',\n}) => {\n const [activeTab, setActiveTab] = useState<TabType>('playlists');\n const [showEditor, setShowEditor] = useState(false);\n const [editingPlaylistId, setEditingPlaylistId] = useState<string | undefined>();\n\n // 标签页配置\n const tabs = [\n { id: 'playlists' as const, label: '播放列表', icon: List },\n { id: 'presets' as const, label: '预设项', icon: Database },\n { id: 'resources' as const, label: '资源管理', icon: Settings },\n ...(showAdvancedOptions ? [{ id: 'stats' as const, label: '统计', icon: BarChart3 }] : []),\n ];\n\n // 创建新播放列表\n const handleCreatePlaylist = () => {\n setEditingPlaylistId(undefined);\n setShowEditor(true);\n };\n\n // 编辑播放列表\n const handleEditPlaylist = (playlistId: string) => {\n setEditingPlaylistId(playlistId);\n setShowEditor(true);\n };\n\n // 关闭编辑器\n const handleCloseEditor = () => {\n setShowEditor(false);\n setEditingPlaylistId(undefined);\n };\n\n // 保存成功\n const handleSaveSuccess = (playlist: any) => {\n console.log('保存成功:', playlist);\n handleCloseEditor();\n // 刷新列表...\n };\n\n if (showEditor) {\n return (\n <MmdPlaylistEditor\n playlistId={editingPlaylistId}\n fileService={fileService}\n userId={userId}\n onSave={handleSaveSuccess}\n onCancel={handleCloseEditor}\n />\n );\n }\n\n return (\n <div className={`min-h-screen bg-gray-50 dark:bg-gray-900 ${className}`}>\n {/* 头部 */}\n <div className=\"bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"flex items-center justify-between h-16\">\n <h1 className=\"text-2xl font-bold text-gray-900 dark:text-white\">\n MMD 后台管理\n </h1>\n \n {activeTab === 'playlists' && (\n <button\n onClick={handleCreatePlaylist}\n className=\"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2\"\n >\n <Plus className=\"w-4 h-4\" />\n 创建播放列表\n </button>\n )}\n </div>\n\n {/* 标签导航 */}\n <div className=\"flex space-x-8\">\n {tabs.map((tab) => {\n const Icon = tab.icon;\n return (\n <button\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex items-center gap-2 px-1 py-4 border-b-2 font-medium text-sm transition-colors ${\n activeTab === tab.id\n ? 'border-blue-600 text-blue-600 dark:text-blue-400'\n : 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'\n }`}\n >\n <Icon className=\"w-4 h-4\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* 主内容区 */}\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8\">\n {activeTab === 'playlists' && (\n <div className=\"space-y-4\">\n <div className=\"text-center py-12 text-gray-500\">\n <List className=\"w-12 h-12 mx-auto mb-4 opacity-50\" />\n <p>播放列表管理功能开发中...</p>\n <p className=\"text-sm mt-2\">点击右上角\"创建播放列表\"按钮开始</p>\n </div>\n </div>\n )}\n\n {activeTab === 'presets' && (\n <div className=\"text-center py-12 text-gray-500\">\n <Database className=\"w-12 h-12 mx-auto mb-4 opacity-50\" />\n <p>预设项管理功能开发中...</p>\n </div>\n )}\n\n {activeTab === 'resources' && (\n <div className=\"text-center py-12 text-gray-500\">\n <Settings className=\"w-12 h-12 mx-auto mb-4 opacity-50\" />\n <p>资源管理功能开发中...</p>\n </div>\n )}\n\n {activeTab === 'stats' && (\n <div className=\"text-center py-12 text-gray-500\">\n <BarChart3 className=\"w-12 h-12 mx-auto mb-4 opacity-50\" />\n <p>统计功能开发中...</p>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n","/**\n * MMD 后台管理数据转换工具\n * \n * 提供数据库格式和前端格式之间的转换函数\n * 以及文件ID到URL的映射功能\n * \n * @package sa2kit/mmd/admin\n */\n\nimport type {\n MmdPlaylistDB,\n MmdPlaylistNodeDB,\n MmdResourceOptionDB,\n MmdPresetItemDB,\n MmdPlaylistWithFiles,\n MmdPlaylistNodeWithFiles,\n MmdResourceOptionWithFile,\n MmdPresetItemWithFiles,\n FileIdToUrlMap,\n} from './types';\n\nimport type {\n MMDResources,\n MMDPlaylistConfig,\n MMDPlaylistNode,\n MMDResourceItem,\n ResourceOption,\n MMDResourceOptions,\n} from '../types';\n\n// ============= 文件URL映射 =============\n\n/**\n * 从数据库记录中提取所有文件ID\n */\nexport function extractFileIdsFromPlaylist(\n playlist: MmdPlaylistDB,\n nodes: MmdPlaylistNodeDB[]\n): string[] {\n const fileIds = new Set<string>();\n\n // 播放列表缩略图\n if (playlist.thumbnailFileId) {\n fileIds.add(playlist.thumbnailFileId);\n }\n\n // 节点文件\n for (const node of nodes) {\n if (node.thumbnailFileId) fileIds.add(node.thumbnailFileId);\n if (node.modelFileId) fileIds.add(node.modelFileId);\n if (node.motionFileId) fileIds.add(node.motionFileId);\n if (node.cameraFileId) fileIds.add(node.cameraFileId);\n if (node.audioFileId) fileIds.add(node.audioFileId);\n if (node.stageModelFileId) fileIds.add(node.stageModelFileId);\n if (node.additionalMotionFileIds) {\n node.additionalMotionFileIds.forEach((id) => fileIds.add(id));\n }\n }\n\n return Array.from(fileIds);\n}\n\n/**\n * 从资源选项中提取文件ID\n */\nexport function extractFileIdsFromResourceOptions(\n options: MmdResourceOptionDB[]\n): string[] {\n const fileIds = new Set<string>();\n\n for (const option of options) {\n fileIds.add(option.fileId);\n if (option.thumbnailFileId) {\n fileIds.add(option.thumbnailFileId);\n }\n }\n\n return Array.from(fileIds);\n}\n\n/**\n * 从预设项中提取文件ID\n */\nexport function extractFileIdsFromPresetItem(item: MmdPresetItemDB): string[] {\n const fileIds = new Set<string>();\n\n if (item.thumbnailFileId) fileIds.add(item.thumbnailFileId);\n if (item.modelFileId) fileIds.add(item.modelFileId);\n if (item.motionFileId) fileIds.add(item.motionFileId);\n if (item.cameraFileId) fileIds.add(item.cameraFileId);\n if (item.audioFileId) fileIds.add(item.audioFileId);\n if (item.stageModelFileId) fileIds.add(item.stageModelFileId);\n if (item.additionalMotionFileIds) {\n item.additionalMotionFileIds.forEach((id) => fileIds.add(id));\n }\n\n return Array.from(fileIds);\n}\n\n// ============= 数据库 -> 前端格式转换 =============\n\n/**\n * 转换播放节点(数据库 -> 前端格式)\n */\nexport function convertPlaylistNodeToFrontend(\n node: MmdPlaylistNodeDB,\n fileUrls: FileIdToUrlMap\n): MmdPlaylistNodeWithFiles {\n return {\n id: node.id,\n playlistId: node.playlistId,\n name: node.name,\n description: node.description,\n loop: node.loop,\n duration: node.duration,\n sortOrder: node.sortOrder,\n config: node.config,\n createdAt: node.createdAt,\n updatedAt: node.updatedAt,\n // URL 映射\n thumbnailUrl: node.thumbnailFileId ? fileUrls[node.thumbnailFileId] : undefined,\n modelUrl: fileUrls[node.modelFileId] || '',\n motionUrl: node.motionFileId ? fileUrls[node.motionFileId] : undefined,\n cameraUrl: node.cameraFileId ? fileUrls[node.cameraFileId] : undefined,\n audioUrl: node.audioFileId ? fileUrls[node.audioFileId] : undefined,\n stageModelUrl: node.stageModelFileId ? fileUrls[node.stageModelFileId] : undefined,\n additionalMotionUrls: node.additionalMotionFileIds\n ?.map((id) => fileUrls[id])\n .filter((url): url is string => Boolean(url)),\n };\n}\n\n/**\n * 转换播放列表(数据库 -> 前端格式)\n */\nexport function convertPlaylistToFrontend(\n playlist: MmdPlaylistDB,\n nodes: MmdPlaylistNodeDB[],\n fileUrls: FileIdToUrlMap\n): MmdPlaylistWithFiles {\n return {\n id: playlist.id,\n name: playlist.name,\n description: playlist.description,\n loop: playlist.loop,\n preloadStrategy: playlist.preloadStrategy,\n autoPlay: playlist.autoPlay,\n status: playlist.status,\n sortOrder: playlist.sortOrder,\n config: playlist.config,\n createdBy: playlist.createdBy,\n createdAt: playlist.createdAt,\n updatedAt: playlist.updatedAt,\n deletedAt: playlist.deletedAt,\n // URL 映射\n thumbnailUrl: playlist.thumbnailFileId ? fileUrls[playlist.thumbnailFileId] : undefined,\n // 转换节点\n nodes: nodes\n .sort((a, b) => a.sortOrder - b.sortOrder)\n .map((node) => convertPlaylistNodeToFrontend(node, fileUrls)),\n };\n}\n\n/**\n * 转换资源选项(数据库 -> 前端格式)\n */\nexport function convertResourceOptionToFrontend(\n option: MmdResourceOptionDB,\n fileUrls: FileIdToUrlMap\n): MmdResourceOptionWithFile {\n return {\n id: option.id,\n name: option.name,\n description: option.description,\n resourceType: option.resourceType,\n tags: option.tags,\n sortOrder: option.sortOrder,\n isActive: option.isActive,\n createdBy: option.createdBy,\n createdAt: option.createdAt,\n updatedAt: option.updatedAt,\n // URL 映射\n fileUrl: fileUrls[option.fileId] || '',\n thumbnailUrl: option.thumbnailFileId ? fileUrls[option.thumbnailFileId] : undefined,\n };\n}\n\n/**\n * 转换预设项(数据库 -> 前端格式)\n */\nexport function convertPresetItemToFrontend(\n item: MmdPresetItemDB,\n fileUrls: FileIdToUrlMap\n): MmdPresetItemWithFiles {\n return {\n id: item.id,\n name: item.name,\n description: item.description,\n sortOrder: item.sortOrder,\n isActive: item.isActive,\n tags: item.tags,\n createdBy: item.createdBy,\n createdAt: item.createdAt,\n updatedAt: item.updatedAt,\n // URL 映射\n thumbnailUrl: item.thumbnailFileId ? fileUrls[item.thumbnailFileId] : undefined,\n modelUrl: fileUrls[item.modelFileId] || '',\n motionUrl: item.motionFileId ? fileUrls[item.motionFileId] : undefined,\n cameraUrl: item.cameraFileId ? fileUrls[item.cameraFileId] : undefined,\n audioUrl: item.audioFileId ? fileUrls[item.audioFileId] : undefined,\n stageModelUrl: item.stageModelFileId ? fileUrls[item.stageModelFileId] : undefined,\n additionalMotionUrls: item.additionalMotionFileIds\n ?.map((id) => fileUrls[id])\n .filter((url): url is string => Boolean(url)),\n };\n}\n\n// ============= 前端格式 -> MMD组件格式转换 =============\n\n/**\n * 转换播放节点(前端格式 -> MMD组件格式)\n */\nexport function convertNodeToMmdFormat(node: MmdPlaylistNodeWithFiles): MMDPlaylistNode {\n return {\n id: node.id,\n name: node.name,\n loop: node.loop,\n duration: node.duration,\n thumbnail: node.thumbnailUrl,\n resources: {\n modelPath: node.modelUrl,\n motionPath: node.motionUrl,\n cameraPath: node.cameraUrl,\n audioPath: node.audioUrl,\n stageModelPath: node.stageModelUrl,\n additionalMotions: node.additionalMotionUrls,\n },\n };\n}\n\n/**\n * 转换播放列表(前端格式 -> MMD组件格式)\n */\nexport function convertPlaylistToMmdConfig(\n playlist: MmdPlaylistWithFiles\n): MMDPlaylistConfig {\n return {\n id: playlist.id,\n name: playlist.name,\n nodes: playlist.nodes.map(convertNodeToMmdFormat),\n loop: playlist.loop,\n preload: playlist.preloadStrategy,\n autoPlay: playlist.autoPlay,\n };\n}\n\n/**\n * 转换预设项(前端格式 -> MMD资源项格式)\n */\nexport function convertPresetItemToMmdResource(\n item: MmdPresetItemWithFiles\n): MMDResourceItem {\n return {\n id: item.id,\n name: item.name,\n thumbnail: item.thumbnailUrl,\n description: item.description,\n resources: {\n modelPath: item.modelUrl,\n motionPath: item.motionUrl,\n cameraPath: item.cameraUrl,\n audioPath: item.audioUrl,\n stageModelPath: item.stageModelUrl,\n additionalMotions: item.additionalMotionUrls,\n },\n };\n}\n\n/**\n * 转换资源选项列表(前端格式 -> MMD资源选项格式)\n */\nexport function convertResourceOptionsToMmdFormat(\n options: MmdResourceOptionWithFile[]\n): MMDResourceOptions {\n const grouped = {\n models: [] as ResourceOption[],\n motions: [] as ResourceOption[],\n cameras: [] as ResourceOption[],\n audios: [] as ResourceOption[],\n stages: [] as ResourceOption[],\n };\n\n for (const option of options) {\n const resourceOption: ResourceOption = {\n id: option.id,\n name: option.name,\n path: option.fileUrl,\n thumbnail: option.thumbnailUrl,\n };\n\n switch (option.resourceType) {\n case 'model':\n grouped.models.push(resourceOption);\n break;\n case 'motion':\n grouped.motions.push(resourceOption);\n break;\n case 'camera':\n grouped.cameras!.push(resourceOption);\n break;\n case 'audio':\n grouped.audios!.push(resourceOption);\n break;\n case 'stage':\n grouped.stages!.push(resourceOption);\n break;\n }\n }\n\n return grouped;\n}\n\n// ============= 辅助函数 =============\n\n/**\n * 验证文件URL映射是否完整\n */\nexport function validateFileUrls(\n requiredFileIds: string[],\n fileUrls: FileIdToUrlMap\n): { valid: boolean; missingIds: string[] } {\n const missingIds = requiredFileIds.filter((id) => !fileUrls[id]);\n \n return {\n valid: missingIds.length === 0,\n missingIds,\n };\n}\n\n/**\n * 生成默认文件URL映射(用于开发/测试)\n */\nexport function generateMockFileUrls(fileIds: string[]): FileIdToUrlMap {\n const urls: FileIdToUrlMap = {};\n \n for (const id of fileIds) {\n urls[id] = `/mock/files/${id}`;\n }\n \n return urls;\n}\n\n/**\n * 合并多个文件URL映射\n */\nexport function mergeFileUrlMaps(...maps: FileIdToUrlMap[]): FileIdToUrlMap {\n return Object.assign({}, ...maps);\n}\n\n/**\n * 从MMDResources提取文件路径(用于编辑时反向映射)\n */\nexport function extractPathsFromMmdResources(resources: MMDResources): string[] {\n const paths: string[] = [resources.modelPath];\n \n if (resources.motionPath) paths.push(resources.motionPath);\n if (resources.cameraPath) paths.push(resources.cameraPath);\n if (resources.audioPath) paths.push(resources.audioPath);\n if (resources.stageModelPath) paths.push(resources.stageModelPath);\n if (resources.additionalMotions) paths.push(...resources.additionalMotions);\n \n return paths;\n}\n\n"]}
|