/** * 素材-模特绑定服务 * 遵循前端开发规范的服务层设计 */ import { invoke } from '@tauri-apps/api/core'; import { Material } from '../types/material'; import { Model } from '../types/model'; export interface MaterialModelBindingStats { total_materials: number; bound_materials: number; unbound_materials: number; binding_rate: number; } export interface ModelMaterialStatistics { total_materials: number; video_count: number; audio_count: number; image_count: number; total_size: number; } export interface MaterialUpdateRequest { model_id?: string; name?: string; } export class MaterialModelBindingService { /** * 绑定素材到模特 */ static async bindMaterialToModel(materialId: string, modelId: string): Promise { await invoke('associate_material_to_model', { materialId, modelId, }); } /** * 解除素材与模特的绑定 */ static async unbindMaterialFromModel(materialId: string): Promise { await invoke('disassociate_material_from_model', { materialId, }); } /** * 批量绑定素材到模特 */ static async batchBindMaterialsToModel(materialIds: string[], modelId: string): Promise { await invoke('batch_bind_materials_to_model', { materialIds, modelId, }); } /** * 批量解除素材与模特的绑定 */ static async batchUnbindMaterialsFromModel(materialIds: string[]): Promise { await invoke('batch_unbind_materials_from_model', { materialIds, }); } /** * 切换素材的模特绑定 */ static async switchMaterialModel(materialId: string, newModelId: string): Promise { await invoke('switch_material_model', { materialId, newModelId, }); } /** * 获取模特的所有素材 */ static async getMaterialsByModel(modelId: string): Promise { return await invoke('get_materials_by_model_id', { modelId, }); } /** * 获取未绑定模特的素材 */ static async getUnboundMaterials(projectId?: string): Promise { return await invoke('get_unassociated_materials', { projectId: projectId || null, }); } /** * 获取模特的素材统计信息 */ static async getModelMaterialStatistics(modelId: string): Promise { return await invoke('get_model_material_statistics', { modelId, }); } /** * 获取项目中模特绑定统计信息 */ static async getProjectModelBindingStats(projectId: string): Promise { return await invoke('get_project_model_binding_stats', { projectId, }); } /** * 获取全局模特绑定统计信息 */ static async getGlobalModelBindingStats(): Promise { return await invoke('get_global_model_binding_stats'); } /** * 更新素材信息 */ static async updateMaterial(id: string, updates: MaterialUpdateRequest): Promise { await invoke('update_material', { id, updates, }); } /** * 获取所有模特 */ static async getAllModels(): Promise { return await invoke('get_all_models'); } /** * 搜索模特 */ static async searchModels(query: string): Promise { return await invoke('search_models', { query, }); } /** * 获取项目的所有素材 */ static async getProjectMaterials(projectId: string): Promise { return await invoke('get_project_materials', { projectId, }); } /** * 获取所有素材 */ static async getAllMaterials(): Promise { return await invoke('get_all_materials'); } /** * 根据过滤条件获取素材 */ static async getMaterialsByFilter(filter: { projectId?: string; modelId?: string; bound?: boolean; search?: string; }): Promise { let materials: Material[] = []; // 首先根据主要过滤条件获取素材 if (filter.modelId) { materials = await this.getMaterialsByModel(filter.modelId); } else if (filter.bound === false) { materials = await this.getUnboundMaterials(filter.projectId); } else if (filter.projectId) { materials = await this.getProjectMaterials(filter.projectId); // 如果指定了绑定状态过滤 if (filter.bound === true) { materials = materials.filter(m => m.model_id); } } else { // 如果没有指定项目,获取所有素材 materials = await this.getAllMaterials(); // 如果指定了绑定状态过滤 if (filter.bound === true) { materials = materials.filter(m => m.model_id); } else if (filter.bound === false) { materials = materials.filter(m => !m.model_id); } } // 应用搜索过滤 if (filter.search && filter.search.trim()) { const searchLower = filter.search.toLowerCase(); materials = materials.filter(m => m.name.toLowerCase().includes(searchLower) ); } return materials; } /** * 验证模特是否存在 */ static async validateModelExists(modelId: string): Promise { try { const model = await invoke('get_model_by_id', { id: modelId }); return model !== null; } catch { return false; } } /** * 验证素材是否存在 */ static async validateMaterialExists(materialId: string): Promise { try { const material = await invoke('get_material_by_id', { id: materialId }); return material !== null; } catch { return false; } } /** * 获取绑定操作的建议 */ static async getBindingSuggestions(_materialId: string): Promise { try { // 这里可以实现基于素材内容的模特推荐逻辑 // 暂时返回所有活跃的模特 const allModels = await this.getAllModels(); return allModels.filter(model => model.is_active); } catch { return []; } } /** * 批量操作验证 */ static async validateBatchOperation(materialIds: string[], modelId?: string): Promise<{ validMaterials: string[]; invalidMaterials: string[]; modelValid: boolean; }> { const validMaterials: string[] = []; const invalidMaterials: string[] = []; let modelValid = true; // 验证素材 for (const materialId of materialIds) { const exists = await this.validateMaterialExists(materialId); if (exists) { validMaterials.push(materialId); } else { invalidMaterials.push(materialId); } } // 验证模特 if (modelId) { modelValid = await this.validateModelExists(modelId); } return { validMaterials, invalidMaterials, modelValid, }; } /** * 获取绑定历史统计 */ static async getBindingHistory(_days: number = 30): Promise<{ daily_bindings: Array<{ date: string; count: number }>; total_operations: number; most_active_model: string | null; }> { // 这里需要后端支持绑定历史统计 // 暂时返回模拟数据 return { daily_bindings: [], total_operations: 0, most_active_model: null, }; } /** * 导出绑定关系 */ static async exportBindingRelations(format: 'json' | 'csv' = 'json'): Promise { try { // 获取所有绑定关系 const allModels = await this.getAllModels(); const bindingData = []; for (const model of allModels) { const materials = await this.getMaterialsByModel(model.id); for (const material of materials) { bindingData.push({ model_id: model.id, model_name: model.name, model_stage_name: model.stage_name, material_id: material.id, material_name: material.name, material_type: material.material_type, created_at: material.created_at, }); } } if (format === 'json') { return JSON.stringify(bindingData, null, 2); } else { // CSV 格式 const headers = Object.keys(bindingData[0] || {}); const csvContent = [ headers.join(','), ...bindingData.map(row => headers.map(header => `"${row[header as keyof typeof row] || ''}"`).join(',') ) ].join('\n'); return csvContent; } } catch (error) { throw new Error(`导出绑定关系失败: ${error}`); } } }