Skip to content

Commit 84fc8db

Browse files
committed
chore: bump version to 2.7.0 in package.json
- Updated version number in package.json to 2.7.0. - Enhanced subtitle translation progress tracking in fileProcessor.ts. - Improved logging for AI batch translation in ai.ts. - Added progress display and consistency checks in TaskStatus.tsx and useIpcCommunication.tsx. - Updated UI components to include new icons and improved functionality.
1 parent c12a681 commit 84fc8db

7 files changed

Lines changed: 152 additions & 24 deletions

File tree

main/helpers/fileProcessor.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,43 @@ async function generateSubtitle(
5656
* 翻译字幕
5757
*/
5858
async function translateSubtitle(event, file: IFiles, formData, provider) {
59+
// 强制发送翻译开始状态
5960
event.sender.send('taskFileChange', {
6061
...file,
6162
translateSubtitle: 'loading',
63+
translateSubtitleProgress: 0,
6264
});
6365

66+
// 强制发送初始进度
67+
event.sender.send('taskProgressChange', file, 'translateSubtitle', 0);
68+
6469
const onProgress = (progress) => {
70+
const normalizedProgress = Math.min(Math.max(progress, 0), 100);
6571
event.sender.send(
6672
'taskProgressChange',
6773
file,
6874
'translateSubtitle',
69-
Math.min(progress, 100),
75+
normalizedProgress,
7076
);
7177
};
78+
7279
try {
7380
await translate(event, file, formData, provider, onProgress);
74-
event.sender.send('taskFileChange', { ...file, translateSubtitle: 'done' });
81+
82+
// 确保最终状态的正确发送
83+
event.sender.send('taskProgressChange', file, 'translateSubtitle', 100);
84+
event.sender.send('taskFileChange', {
85+
...file,
86+
translateSubtitle: 'done',
87+
translateSubtitleProgress: 100,
88+
});
89+
90+
logMessage(
91+
`Translation completed successfully for ${file.fileName}`,
92+
'info',
93+
);
7594
} catch (error) {
95+
// 确保错误状态下也发送当前进度(从文件状态获取)
7696
onError(event, file, 'translateSubtitle', error);
7797
}
7898
}

main/translate/services/ai.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,24 @@ export async function handleAIBatchTranslation(
2222
const { provider, sourceLanguage, targetLanguage, translator } = config;
2323
const results: TranslationResult[] = [];
2424
const totalBatches = Math.ceil(subtitles.length / batchSize);
25+
let processedSubtitles = 0;
26+
27+
logMessage(
28+
`开始AI批量翻译:总共 ${subtitles.length} 条字幕,分为 ${totalBatches} 个批次,每批次 ${batchSize} 条`,
29+
'info',
30+
);
2531

2632
for (let i = 0; i < subtitles.length; i += batchSize) {
2733
const batch = subtitles.slice(i, i + batchSize);
2834
const currentBatchIndex = Math.floor(i / batchSize) + 1;
2935
let retryCount = 0;
3036
let batchSuccess = false;
37+
let batchResults: TranslationResult[] = [];
38+
39+
logMessage(
40+
`处理批次 ${currentBatchIndex}/${totalBatches},包含 ${batch.length} 条字幕`,
41+
'info',
42+
);
3143

3244
while (!batchSuccess && retryCount <= maxRetries) {
3345
try {
@@ -89,7 +101,7 @@ export async function handleAIBatchTranslation(
89101

90102
const parsedValues = Object.values(parsedContent);
91103

92-
const batchResults = batch.map((subtitle, index) => ({
104+
batchResults = batch.map((subtitle, index) => ({
93105
id: subtitle.id,
94106
startEndTime: subtitle.startEndTime,
95107
sourceContent: subtitle.content.join('\n'),
@@ -106,7 +118,13 @@ export async function handleAIBatchTranslation(
106118
}
107119

108120
results.push(...batchResults);
121+
processedSubtitles += batch.length;
109122
batchSuccess = true;
123+
124+
logMessage(
125+
`批次 ${currentBatchIndex}/${totalBatches} 翻译成功,已处理 ${processedSubtitles}/${subtitles.length} 条字幕`,
126+
'info',
127+
);
110128
} else {
111129
throw new Error(
112130
'Invalid response format: Failed to parse JSON structure',
@@ -136,7 +154,7 @@ export async function handleAIBatchTranslation(
136154
'error',
137155
);
138156
// 如果全部重试都失败,则添加失败记录,并继续下一批
139-
const failedResults = batch.map((subtitle) => ({
157+
batchResults = batch.map((subtitle) => ({
140158
id: subtitle.id,
141159
startEndTime: subtitle.startEndTime,
142160
sourceContent: subtitle.content.join('\n'),
@@ -145,22 +163,41 @@ export async function handleAIBatchTranslation(
145163

146164
// 对失败的结果也进行处理和保存
147165
if (onTranslationResult) {
148-
await onTranslationResult(failedResults);
166+
await onTranslationResult(batchResults);
149167
}
150168

151-
results.push(...failedResults);
169+
results.push(...batchResults);
170+
processedSubtitles += batch.length;
152171
batchSuccess = true; // 标记为完成,继续下一批次
172+
173+
logMessage(
174+
`批次 ${currentBatchIndex}/${totalBatches} 已标记为失败完成,继续下一批次`,
175+
'warning',
176+
);
153177
}
154178
}
155179
}
156180

157-
// 更新翻译进度
158-
const progress = Math.min(((i + batchSize) / subtitles.length) * 100, 100);
181+
// 更新翻译进度 - 使用实际处理的字幕数量计算
182+
const progress = Math.min(
183+
(processedSubtitles / subtitles.length) * 100,
184+
100,
185+
);
159186
if (onProgress) {
160187
onProgress(progress);
161188
}
189+
190+
logMessage(
191+
`进度更新: ${progress.toFixed(2)}% (${processedSubtitles}/${subtitles.length})`,
192+
'info',
193+
);
162194
}
163195

196+
logMessage(
197+
`AI批量翻译完成:共处理 ${processedSubtitles} 条字幕,成功 ${results.filter((r) => !r.targetContent.startsWith('[翻译失败:')).length} 条`,
198+
'info',
199+
);
200+
164201
return results;
165202
}
166203

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"private": true,
33
"name": "smartsub",
44
"description": "视频转字幕,字幕翻译软件",
5-
"version": "2.6.0",
5+
"version": "2.7.0",
66
"author": "buxuku <buxuku@gmail.com>",
77
"main": "app/background.js",
88
"scripts": {

renderer/components/TaskListControl.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Import, FileText } from 'lucide-react';
1+
import { Import, FileText, Trash2 } from 'lucide-react';
22
import { Button } from './ui/button';
33
import { useTranslation } from 'next-i18next';
44
import { useState } from 'react';
@@ -37,6 +37,7 @@ const TaskListControl = ({ setFiles, formData }) => {
3737
variant="outline"
3838
onClick={handleClearList}
3939
>
40+
<Trash2 className="size-5 mr-2" />
4041
{t('clearList')}
4142
</Button>
4243
<Button

renderer/components/TaskStatus.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,40 @@ import {
1010
const TaskStatus = ({ file, checkKey, skip = false }) => {
1111
if (skip) return <RedoDot className="size-4" />;
1212

13-
if (file[checkKey] === 'loading') {
13+
// 状态调试:检查进度与状态的一致性
14+
const progressKey = `${checkKey}Progress`;
15+
const progress = file[progressKey];
16+
const status = file[checkKey];
17+
18+
// 调试日志(仅在开发环境)
19+
if (process.env.NODE_ENV === 'development') {
20+
// 检查状态不一致的情况
21+
if (status === 'done' && progress !== undefined && progress < 100) {
22+
console.warn(`状态不一致: ${checkKey} 状态为 done 但进度为 ${progress}%`);
23+
}
24+
if (status === 'loading' && progress === undefined) {
25+
console.warn(`状态不一致: ${checkKey} 状态为 loading 但没有进度信息`);
26+
}
27+
}
28+
29+
if (status === 'loading') {
1430
// 检查是否有进度信息
15-
const progressKey = `${checkKey}Progress`;
16-
const hasProgress = file[progressKey] !== undefined;
31+
const hasProgress = progress !== undefined && progress !== null;
32+
const displayProgress = hasProgress ? Number(progress).toFixed(2) : '0.00';
33+
1734
return (
1835
<div className="flex items-center gap-1">
1936
<Loader className="animate-spin size-4" />
20-
{hasProgress && (
21-
<span className="text-xs">{file[progressKey].toFixed(2)}%</span>
22-
)}
37+
<span className="text-xs">{displayProgress}%</span>
2338
</div>
2439
);
2540
}
2641

27-
if (file[checkKey] === 'done') {
42+
if (status === 'done') {
2843
return <CircleCheck className="size-4" />;
2944
}
3045

31-
if (file[checkKey] === 'error') {
46+
if (status === 'error') {
3247
const errorKey = `${checkKey}Error`;
3348
const errorMsg = file[errorKey] || '未知错误';
3449

@@ -40,6 +55,9 @@ const TaskStatus = ({ file, checkKey, skip = false }) => {
4055
</TooltipTrigger>
4156
<TooltipContent>
4257
<p>{errorMsg}</p>
58+
{progress !== undefined && (
59+
<p className="text-xs text-gray-500 mt-1">进度:{progress}%</p>
60+
)}
4361
</TooltipContent>
4462
</Tooltip>
4563
</TooltipProvider>

renderer/hooks/useIpcCommunication.tsx

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,31 @@ export default function useIpcCommunication(setFiles) {
2525
key: string,
2626
progress: number,
2727
) => {
28+
// 验证进度值的合理性
29+
const normalizedProgress = Math.min(Math.max(progress || 0, 0), 100);
30+
2831
setFiles((prevFiles) => {
2932
const progressKey = `${key}Progress`;
30-
const updatedFiles = prevFiles.map((file) =>
31-
file.uuid === res?.uuid ? { ...file, [progressKey]: progress } : file,
32-
);
33+
const updatedFiles = prevFiles.map((file) => {
34+
if (file.uuid === res?.uuid) {
35+
const currentProgress = file[progressKey] || 0;
36+
37+
// 防止进度回退,除非是重新开始(进度为0)
38+
if (
39+
normalizedProgress === 0 ||
40+
normalizedProgress >= currentProgress
41+
) {
42+
return { ...file, [progressKey]: normalizedProgress };
43+
}
44+
45+
// 如果进度回退了,记录警告但仍然更新(可能是重试)
46+
console.warn(
47+
`Progress rollback detected for ${key}: ${currentProgress} -> ${normalizedProgress}`,
48+
);
49+
return { ...file, [progressKey]: normalizedProgress };
50+
}
51+
return file;
52+
});
3353
return updatedFiles;
3454
});
3555
};
@@ -50,9 +70,41 @@ export default function useIpcCommunication(setFiles) {
5070

5171
const handleFileChange = (res: IFiles) => {
5272
setFiles((prevFiles) => {
53-
const updatedFiles = prevFiles.map((file) =>
54-
file.uuid === res?.uuid ? { ...file, ...res } : file,
55-
);
73+
const updatedFiles = prevFiles.map((file) => {
74+
if (file.uuid === res?.uuid) {
75+
const updatedFile = { ...file, ...res };
76+
77+
// 状态一致性检查:如果状态变为 'done',确保进度为100%
78+
Object.keys(res).forEach((key) => {
79+
if (key.endsWith('Subtitle') && res[key] === 'done') {
80+
const progressKey = `${key}Progress`;
81+
if (
82+
!updatedFile[progressKey] ||
83+
updatedFile[progressKey] < 100
84+
) {
85+
updatedFile[progressKey] = 100;
86+
}
87+
}
88+
89+
// 如果状态变为 'error',保持当前进度不变
90+
if (key.endsWith('Subtitle') && res[key] === 'error') {
91+
const progressKey = `${key}Progress`;
92+
// 保持原有进度,不重置
93+
}
94+
95+
// 如果状态变为 'loading',确保有初始进度
96+
if (key.endsWith('Subtitle') && res[key] === 'loading') {
97+
const progressKey = `${key}Progress`;
98+
if (!updatedFile[progressKey]) {
99+
updatedFile[progressKey] = 0;
100+
}
101+
}
102+
});
103+
104+
return updatedFile;
105+
}
106+
return file;
107+
});
56108
return updatedFiles;
57109
});
58110
};

resources/WechatIMG428.png

30 KB
Loading

0 commit comments

Comments
 (0)