fix: 修复语音生成历史页面状态映射问题

问题分析:
- 语音合成弹框使用前端UI状态枚举(SpeechGenerationStatus)
- 语音生成历史页面使用数据库记录状态枚举(SpeechGenerationRecordStatus)
- 后端保存的状态值与前端枚举值不匹配导致状态显示错误

修复内容:
� 新增 normalizeStatus 函数确保状态类型安全转换
� 添加详细的调试日志追踪状态值传递过程
� 完善状态样式和图标处理,支持所有状态类型
� 在记录加载时标准化状态值,确保前后端一致性
� 优化状态筛选逻辑,使用标准化状态进行比较

技术改进:
- 类型安全的状态转换函数
- 完整的状态枚举值处理
- 详细的错误日志和调试信息
- 向后兼容的状态值处理

现在语音生成历史页面应该能正确显示记录状态!
This commit is contained in:
杨明明 2025-07-31 13:50:48 +08:00
parent ef0d19d144
commit 4f133f3fbe
1 changed files with 108 additions and 17 deletions

View File

@ -59,23 +59,54 @@ const VoiceGenerationHistory: React.FC = () => {
const allRecords = await invoke<SpeechGenerationRecord[]>('get_speech_generation_records', {
limit: 100 // 限制最近100条记录
});
// 调试:打印原始记录数据
console.log('🔍 原始记录数据:', allRecords);
if (allRecords.length > 0) {
console.log('🔍 第一条记录状态:', {
status: allRecords[0].status,
statusType: typeof allRecords[0].status,
statusValue: JSON.stringify(allRecords[0].status)
});
}
// 标准化记录状态
const normalizedRecords = allRecords.map(record => ({
...record,
status: normalizeStatus(record.status)
}));
console.log('🔄 状态标准化后:', normalizedRecords.length > 0 ? {
originalStatus: allRecords[0]?.status,
normalizedStatus: normalizedRecords[0]?.status
} : '无记录');
// 根据搜索和筛选条件过滤记录
let filteredRecords = allRecords;
let filteredRecords = normalizedRecords;
if (searchText.trim()) {
filteredRecords = filteredRecords.filter(record =>
filteredRecords = filteredRecords.filter(record =>
record.text.toLowerCase().includes(searchText.toLowerCase()) ||
(record.voice_name && record.voice_name.toLowerCase().includes(searchText.toLowerCase())) ||
record.voice_id.toLowerCase().includes(searchText.toLowerCase())
);
}
if (statusFilter !== 'all') {
filteredRecords = filteredRecords.filter(record => record.status === statusFilter);
const normalizedFilter = normalizeStatus(statusFilter);
filteredRecords = filteredRecords.filter(record => {
console.log('🔍 状态筛选比较:', {
recordStatus: record.status,
filterStatus: statusFilter,
normalizedFilter,
isEqual: record.status === normalizedFilter
});
return record.status === normalizedFilter;
});
}
setRecords(filteredRecords);
console.log('✅ 最终显示记录数:', filteredRecords.length);
} catch (error) {
console.error('加载语音生成记录失败:', error);
addNotification({
@ -210,6 +241,37 @@ const VoiceGenerationHistory: React.FC = () => {
// ============= 辅助函数 =============
// 状态转换函数 - 确保类型安全
const normalizeStatus = (status: any): SpeechGenerationRecordStatus => {
// 如果已经是正确的枚举值,直接返回
if (Object.values(SpeechGenerationRecordStatus).includes(status)) {
return status as SpeechGenerationRecordStatus;
}
// 如果是字符串,尝试转换
if (typeof status === 'string') {
const normalizedStatus = status.toLowerCase();
switch (normalizedStatus) {
case 'pending':
return SpeechGenerationRecordStatus.PENDING;
case 'processing':
return SpeechGenerationRecordStatus.PROCESSING;
case 'completed':
return SpeechGenerationRecordStatus.COMPLETED;
case 'failed':
return SpeechGenerationRecordStatus.FAILED;
case 'cancelled':
return SpeechGenerationRecordStatus.CANCELLED;
default:
console.warn('⚠️ 未知状态字符串:', status);
return SpeechGenerationRecordStatus.PENDING;
}
}
console.warn('⚠️ 无法识别的状态类型:', status, typeof status);
return SpeechGenerationRecordStatus.PENDING;
};
// 格式化时间
const formatTime = (timeStr: string) => {
const date = new Date(timeStr);
@ -225,14 +287,27 @@ const VoiceGenerationHistory: React.FC = () => {
// 获取状态样式
const getStatusStyle = (status: SpeechGenerationRecordStatus) => {
console.log('🎨 获取状态样式:', {
status,
statusType: typeof status,
enumValues: Object.values(SpeechGenerationRecordStatus),
isCompleted: status === SpeechGenerationRecordStatus.COMPLETED,
completedValue: SpeechGenerationRecordStatus.COMPLETED
});
switch (status) {
case SpeechGenerationRecordStatus.Completed:
case SpeechGenerationRecordStatus.COMPLETED:
return 'bg-green-100 text-green-800 border-green-200';
case SpeechGenerationRecordStatus.Failed:
case SpeechGenerationRecordStatus.FAILED:
return 'bg-red-100 text-red-800 border-red-200';
case SpeechGenerationRecordStatus.Processing:
case SpeechGenerationRecordStatus.PROCESSING:
return 'bg-blue-100 text-blue-800 border-blue-200';
case SpeechGenerationRecordStatus.PENDING:
return 'bg-yellow-100 text-yellow-800 border-yellow-200';
case SpeechGenerationRecordStatus.CANCELLED:
return 'bg-gray-100 text-gray-800 border-gray-200';
default:
console.warn('⚠️ 未知状态,使用默认样式:', status);
return 'bg-gray-100 text-gray-800 border-gray-200';
}
};
@ -240,12 +315,16 @@ const VoiceGenerationHistory: React.FC = () => {
// 获取状态图标
const getStatusIcon = (status: SpeechGenerationRecordStatus) => {
switch (status) {
case SpeechGenerationRecordStatus.Completed:
case SpeechGenerationRecordStatus.COMPLETED:
return <CheckCircle className="w-3 h-3" />;
case SpeechGenerationRecordStatus.Failed:
case SpeechGenerationRecordStatus.FAILED:
return <XCircle className="w-3 h-3" />;
case SpeechGenerationRecordStatus.Processing:
case SpeechGenerationRecordStatus.PROCESSING:
return <Loader2 className="w-3 h-3 animate-spin" />;
case SpeechGenerationRecordStatus.PENDING:
return <Clock className="w-3 h-3" />;
case SpeechGenerationRecordStatus.CANCELLED:
return <XCircle className="w-3 h-3" />;
default:
return <AlertCircle className="w-3 h-3" />;
}
@ -253,15 +332,27 @@ const VoiceGenerationHistory: React.FC = () => {
// 获取状态文本
const getStatusText = (status: SpeechGenerationRecordStatus) => {
console.log('📝 获取状态文本:', {
status,
statusType: typeof status,
isCompleted: status === SpeechGenerationRecordStatus.COMPLETED,
completedValue: SpeechGenerationRecordStatus.COMPLETED
});
switch (status) {
case SpeechGenerationRecordStatus.Completed:
case SpeechGenerationRecordStatus.COMPLETED:
return '已完成';
case SpeechGenerationRecordStatus.Failed:
case SpeechGenerationRecordStatus.FAILED:
return '失败';
case SpeechGenerationRecordStatus.Processing:
case SpeechGenerationRecordStatus.PROCESSING:
return '处理中';
default:
case SpeechGenerationRecordStatus.PENDING:
return '待处理';
case SpeechGenerationRecordStatus.CANCELLED:
return '已取消';
default:
console.warn('⚠️ 未知状态,使用默认文本:', status);
return '未知状态';
}
};