mixvideo-v2/apps/desktop/src/services/similaritySearchService.ts

167 lines
4.5 KiB
TypeScript

import { invoke } from '@tauri-apps/api/core';
import {
SimilaritySearchRequest,
SimilaritySearchConfig,
SearchResponse,
} from '../types/similaritySearch';
/**
* 相似度检索工具API服务
* 遵循 Tauri 开发规范的API服务设计原则
*/
export class SimilaritySearchService {
/**
* 执行快速相似度搜索
*/
static async quickSimilaritySearch(request: SimilaritySearchRequest): Promise<SearchResponse> {
try {
const response = await invoke<SearchResponse>('quick_similarity_search', {
query: request.query,
relevanceThreshold: request.relevance_threshold,
pageSize: request.page_size,
pageOffset: request.page_offset,
config: request.config, // 传递高级过滤器配置
});
return response;
} catch (error) {
console.error('Failed to perform similarity search:', error);
throw new Error(`相似度搜索失败: ${error}`);
}
}
/**
* 获取搜索建议
*/
static async getSuggestions(query: string): Promise<string[]> {
try {
const suggestions = await invoke<string[]>('get_similarity_search_suggestions', { query });
return suggestions;
} catch (error) {
console.error('Failed to get search suggestions:', error);
return [];
}
}
/**
* 获取工具配置
*/
static async getConfig(): Promise<SimilaritySearchConfig> {
try {
const config = await invoke<SimilaritySearchConfig>('get_similarity_search_config');
return config;
} catch (error) {
console.error('Failed to get similarity search config:', error);
throw new Error(`获取配置失败: ${error}`);
}
}
/**
* 验证搜索查询
*/
static validateQuery(query: string): boolean {
return query.trim().length > 0 && query.trim().length <= 200;
}
/**
* 格式化阈值标签
*/
static formatThresholdLabel(threshold: string): string {
const labels: Record<string, string> = {
'LOWEST': '最低',
'LOW': '较低',
'MEDIUM': '中等',
'HIGH': '较高',
};
return labels[threshold] || threshold;
}
/**
* 获取阈值描述
*/
static getThresholdDescription(threshold: string): string {
const descriptions: Record<string, string> = {
'LOWEST': '显示更多相关结果,包含相关性较低的内容',
'LOW': '包含较多相关结果,适合探索性搜索',
'MEDIUM': '平衡相关性和数量,推荐使用',
'HIGH': '只显示高度相关结果,结果更精准',
};
return descriptions[threshold] || '未知阈值';
}
/**
* 生成搜索建议
*/
static generateSearchSuggestions(query: string, baseList: string[]): string[] {
if (!query || query.trim().length === 0) {
return baseList.slice(0, 6);
}
const lowercaseQuery = query.toLowerCase();
const filtered = baseList.filter(item =>
item.toLowerCase().includes(lowercaseQuery) ||
lowercaseQuery.split('').some(char => item.includes(char))
);
return filtered.length > 0 ? filtered.slice(0, 8) : baseList.slice(0, 6);
}
/**
* 计算总页数
*/
static getTotalPages(totalResults: number, pageSize: number): number {
return Math.ceil(totalResults / pageSize);
}
/**
* 检查是否有更多结果
*/
static hasMoreResults(currentPage: number, totalPages: number): boolean {
return currentPage < totalPages;
}
/**
* 获取页面范围信息
*/
static getPageRangeInfo(currentPage: number, pageSize: number, totalResults: number): {
start: number;
end: number;
total: number;
} {
const start = (currentPage - 1) * pageSize + 1;
const end = Math.min(currentPage * pageSize, totalResults);
return { start, end, total: totalResults };
}
/**
* 格式化搜索时间
*/
static formatSearchTime(timeMs: number): string {
if (timeMs < 1000) {
return `${timeMs}ms`;
} else if (timeMs < 60000) {
return `${(timeMs / 1000).toFixed(1)}s`;
} else {
return `${(timeMs / 60000).toFixed(1)}min`;
}
}
/**
* 获取相关性评分颜色
*/
static getRelevanceScoreColor(score: number): string {
if (score >= 0.9) return 'text-green-600';
if (score >= 0.7) return 'text-blue-600';
if (score >= 0.5) return 'text-yellow-600';
return 'text-gray-600';
}
/**
* 格式化相关性评分
*/
static formatRelevanceScore(score: number): string {
return `${(score * 100).toFixed(0)}%`;
}
}
export default SimilaritySearchService;