441 lines
11 KiB
TypeScript
441 lines
11 KiB
TypeScript
import { invoke } from '@tauri-apps/api/core'
|
||
import { useAuthStore } from '../stores/useAuthStore'
|
||
|
||
// 统一的响应格式
|
||
export interface TemplateResponse {
|
||
success: boolean
|
||
message: string
|
||
data?: any
|
||
output?: string
|
||
error?: string
|
||
}
|
||
|
||
// 模板信息接口
|
||
export interface TemplateInfo {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
thumbnail_path: string
|
||
draft_content_path: string
|
||
resources_path: string
|
||
created_at: string
|
||
updated_at: string
|
||
canvas_config: any
|
||
duration: number
|
||
material_count: number
|
||
track_count: number
|
||
tags: string[]
|
||
is_cloud: boolean
|
||
user_id: string
|
||
}
|
||
|
||
// 请求接口
|
||
export interface BatchImportRequest {
|
||
source_folder: string
|
||
user_id?: string
|
||
verbose?: boolean
|
||
json_output?: boolean
|
||
}
|
||
|
||
export interface TemplateListRequest {
|
||
user_id?: string
|
||
include_cloud?: boolean
|
||
limit?: number
|
||
verbose?: boolean
|
||
json_output?: boolean
|
||
}
|
||
|
||
export interface TemplateGetRequest {
|
||
template_id: string
|
||
user_id?: string
|
||
verbose?: boolean
|
||
json_output?: boolean
|
||
}
|
||
|
||
export interface TemplateDeleteRequest {
|
||
template_id: string
|
||
user_id?: string
|
||
verbose?: boolean
|
||
json_output?: boolean
|
||
}
|
||
|
||
export interface TemplateSearchRequest {
|
||
query: string
|
||
user_id?: string
|
||
include_cloud?: boolean
|
||
limit?: number
|
||
verbose?: boolean
|
||
json_output?: boolean
|
||
}
|
||
|
||
// 批量导入结果
|
||
export interface BatchImportResult {
|
||
imported_count: number
|
||
failed_count: number
|
||
imported_templates: Array<{
|
||
id: string
|
||
name: string
|
||
path: string
|
||
}>
|
||
failed_templates: Array<{
|
||
name: string
|
||
path: string
|
||
error: string
|
||
}>
|
||
message: string
|
||
}
|
||
|
||
// 统计信息
|
||
export interface TemplateStats {
|
||
total_templates: number
|
||
user_templates: number
|
||
cloud_templates: number
|
||
total_materials: number
|
||
total_tracks: number
|
||
total_duration: number
|
||
average_duration: number
|
||
}
|
||
|
||
// 标签信息
|
||
export interface TagInfo {
|
||
tag: string
|
||
count: number
|
||
}
|
||
|
||
// 轨道片段信息
|
||
export interface TrackSegment {
|
||
id: string
|
||
type: 'video' | 'audio' | 'image' | 'text' | 'effect'
|
||
name: string
|
||
start_time: number
|
||
end_time: number
|
||
duration: number
|
||
resource_path?: string
|
||
properties?: any
|
||
effects?: any[]
|
||
}
|
||
|
||
// 轨道信息
|
||
export interface Track {
|
||
id: string
|
||
name: string
|
||
type: 'video' | 'audio' | 'effect' | 'text' | 'sticker' | 'image'
|
||
index: number
|
||
segments: TrackSegment[]
|
||
properties?: any
|
||
}
|
||
|
||
// 模板详细信息
|
||
export interface TemplateDetail {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
canvas_config: any
|
||
tracks: Track[]
|
||
duration: number
|
||
fps: number
|
||
sample_rate?: number
|
||
}
|
||
|
||
export class TemplateServiceV2 {
|
||
/**
|
||
* 获取当前用户ID
|
||
*/
|
||
private static getCurrentUserId(): string {
|
||
const authState = useAuthStore.getState()
|
||
|
||
if (!authState.isAuthenticated || !authState.user?.id) {
|
||
throw new Error('用户未登录,请先登录后再进行操作')
|
||
}
|
||
|
||
return authState.user.id
|
||
}
|
||
|
||
/**
|
||
* 批量导入模板 (新版本)
|
||
*/
|
||
static async batchImportTemplates(sourceFolder: string, userId?: string): Promise<BatchImportResult> {
|
||
try {
|
||
const request: BatchImportRequest = {
|
||
source_folder: sourceFolder,
|
||
user_id: userId || this.getCurrentUserId(),
|
||
verbose: false,
|
||
json_output: true
|
||
}
|
||
|
||
const response = await invoke<TemplateResponse>('batch_import_templates_cli', { request })
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Import failed')
|
||
}
|
||
|
||
return response.data as BatchImportResult
|
||
} catch (error) {
|
||
console.error('Batch import templates failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取模板列表 (新版本)
|
||
*/
|
||
static async getTemplates(includeCloud: boolean = true, limit: number = 100, userId?: string): Promise<TemplateInfo[]> {
|
||
try {
|
||
const request: TemplateListRequest = {
|
||
user_id: userId || this.getCurrentUserId(),
|
||
include_cloud: includeCloud,
|
||
limit: limit,
|
||
verbose: false,
|
||
json_output: true
|
||
}
|
||
|
||
const response = await invoke<TemplateResponse>('get_templates_cli', { request })
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to get templates')
|
||
}
|
||
|
||
return response.data?.templates || []
|
||
} catch (error) {
|
||
console.error('Get templates failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取单个模板 (新版本)
|
||
*/
|
||
static async getTemplate(templateId: string, userId?: string): Promise<TemplateInfo> {
|
||
try {
|
||
const request: TemplateGetRequest = {
|
||
template_id: templateId,
|
||
user_id: userId || this.getCurrentUserId(),
|
||
verbose: false,
|
||
json_output: true
|
||
}
|
||
|
||
const response = await invoke<TemplateResponse>('get_template_cli', { request })
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to get template')
|
||
}
|
||
|
||
return response.data as TemplateInfo
|
||
} catch (error) {
|
||
console.error('Get template failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取模板详细信息 (新版本)
|
||
* 注意:目前使用原版本的get_template_detail命令,因为CLI版本还未实现详细信息功能
|
||
*/
|
||
static async getTemplateDetail(templateId: string): Promise<TemplateDetail | null> {
|
||
try {
|
||
// 暂时使用原版本的命令,直到CLI版本实现详细信息功能
|
||
const response = await invoke<string>('get_template_detail', { template_id: templateId })
|
||
const detail = JSON.parse(response)
|
||
|
||
if (!detail) {
|
||
return null
|
||
}
|
||
|
||
return detail as TemplateDetail
|
||
} catch (error) {
|
||
console.error('Get template detail failed:', error)
|
||
return null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 删除模板 (新版本)
|
||
*/
|
||
static async deleteTemplate(templateId: string, userId?: string): Promise<boolean> {
|
||
try {
|
||
const request: TemplateDeleteRequest = {
|
||
template_id: templateId,
|
||
user_id: userId || this.getCurrentUserId(),
|
||
verbose: false,
|
||
json_output: true
|
||
}
|
||
|
||
const response = await invoke<TemplateResponse>('delete_template_cli', { request })
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to delete template')
|
||
}
|
||
|
||
return response.data?.deleted || false
|
||
} catch (error) {
|
||
console.error('Delete template failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 搜索模板 (新功能)
|
||
*/
|
||
static async searchTemplates(
|
||
query: string,
|
||
includeCloud: boolean = true,
|
||
limit: number = 50,
|
||
userId?: string
|
||
): Promise<TemplateInfo[]> {
|
||
try {
|
||
const request: TemplateSearchRequest = {
|
||
query: query,
|
||
user_id: userId || this.getCurrentUserId(),
|
||
include_cloud: includeCloud,
|
||
limit: limit,
|
||
verbose: false,
|
||
json_output: true
|
||
}
|
||
|
||
const response = await invoke<TemplateResponse>('search_templates_cli', { request })
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to search templates')
|
||
}
|
||
|
||
return response.data?.templates || []
|
||
} catch (error) {
|
||
console.error('Search templates failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取模板统计信息 (新功能)
|
||
*/
|
||
static async getTemplateStats(userId?: string): Promise<TemplateStats> {
|
||
try {
|
||
const response = await invoke<TemplateResponse>('get_template_stats_cli', {
|
||
user_id: userId || this.getCurrentUserId(),
|
||
verbose: false
|
||
})
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to get template stats')
|
||
}
|
||
|
||
return response.data as TemplateStats
|
||
} catch (error) {
|
||
console.error('Get template stats failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取热门标签 (新功能)
|
||
*/
|
||
static async getPopularTags(limit: number = 20, userId?: string): Promise<TagInfo[]> {
|
||
try {
|
||
const response = await invoke<TemplateResponse>('get_popular_tags_cli', {
|
||
user_id: userId || this.getCurrentUserId(),
|
||
limit: limit,
|
||
verbose: false
|
||
})
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to get popular tags')
|
||
}
|
||
|
||
return response.data?.tags || []
|
||
} catch (error) {
|
||
console.error('Get popular tags failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据标签获取模板 (新功能)
|
||
*/
|
||
static async getTemplatesByTag(
|
||
tag: string,
|
||
includeCloud: boolean = true,
|
||
limit: number = 50,
|
||
userId?: string
|
||
): Promise<TemplateInfo[]> {
|
||
try {
|
||
const response = await invoke<TemplateResponse>('get_templates_by_tag_cli', {
|
||
tag: tag,
|
||
user_id: userId || this.getCurrentUserId(),
|
||
include_cloud: includeCloud,
|
||
limit: limit,
|
||
verbose: false
|
||
})
|
||
|
||
if (!response.success) {
|
||
throw new Error(response.error || response.message || 'Failed to get templates by tag')
|
||
}
|
||
|
||
return response.data?.templates || []
|
||
} catch (error) {
|
||
console.error('Get templates by tag failed:', error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证模板文件夹结构
|
||
*/
|
||
static validateTemplateFolder(folderPath: string): boolean {
|
||
// 这个方法保持不变,依赖后端验证
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 格式化持续时间
|
||
*/
|
||
static formatDuration(seconds: number): string {
|
||
const minutes = Math.floor(seconds / 60)
|
||
const remainingSeconds = seconds % 60
|
||
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
|
||
}
|
||
|
||
/**
|
||
* 格式化日期
|
||
*/
|
||
static formatDate(dateString: string): string {
|
||
try {
|
||
const date = new Date(dateString)
|
||
return date.toLocaleDateString('zh-CN', {
|
||
year: 'numeric',
|
||
month: 'short',
|
||
day: 'numeric'
|
||
})
|
||
} catch {
|
||
return dateString
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取模板缩略图URL
|
||
*/
|
||
static getThumbnailUrl(template: TemplateInfo): string {
|
||
if (template.thumbnail_path) {
|
||
// 如果是相对路径,转换为绝对路径
|
||
if (!template.thumbnail_path.startsWith('http') && !template.thumbnail_path.startsWith('/')) {
|
||
return `file://${template.resources_path}/${template.thumbnail_path}`
|
||
}
|
||
return template.thumbnail_path
|
||
}
|
||
return ''
|
||
}
|
||
|
||
/**
|
||
* 检查模板是否为云端模板
|
||
*/
|
||
static isCloudTemplate(template: TemplateInfo): boolean {
|
||
return template.is_cloud || false
|
||
}
|
||
|
||
/**
|
||
* 检查模板是否属于当前用户
|
||
*/
|
||
static isUserTemplate(template: TemplateInfo, userId?: string): boolean {
|
||
return template.user_id === (userId || this.getCurrentUserId())
|
||
}
|
||
}
|