This commit is contained in:
AmintaCCCP
2025-08-12 20:12:51 +08:00
parent 83bbc588db
commit 0b5d01fbb2
3 changed files with 52 additions and 11 deletions

View File

@@ -126,12 +126,13 @@ export const RepositoryList: React.FC<RepositoryListProps> = ({
const customCategoryNames = customCategories.map(cat => cat.name);
let analyzed = 0;
const concurrency = activeConfig.concurrency || 1;
for (let i = 0; i < targetRepos.length; i++) {
// 并发分析函数
const analyzeRepository = async (repo: Repository, index: number) => {
// 检查是否需要停止
if (shouldStopRef.current) {
console.log('Analysis stopped by user');
break;
return false;
}
// 处理暂停
@@ -141,13 +142,9 @@ export const RepositoryList: React.FC<RepositoryListProps> = ({
// 再次检查停止状态(暂停期间可能被停止)
if (shouldStopRef.current) {
console.log('Analysis stopped during pause');
break;
return false;
}
const repo = targetRepos[i];
setAnalysisProgress({ current: i + 1, total: targetRepos.length });
try {
// 获取README内容
const [owner, name] = repo.full_name.split('/');
@@ -167,11 +164,32 @@ export const RepositoryList: React.FC<RepositoryListProps> = ({
updateRepository(updatedRepo);
analyzed++;
setAnalysisProgress({ current: analyzed, total: targetRepos.length });
// 避免API限制
await new Promise(resolve => setTimeout(resolve, 1000));
return true;
} catch (error) {
console.warn(`Failed to analyze ${repo.full_name}:`, error);
return false;
}
};
// 分批处理,支持并发
for (let i = 0; i < targetRepos.length; i += concurrency) {
if (shouldStopRef.current) {
console.log('Analysis stopped by user');
break;
}
const batch = targetRepos.slice(i, i + concurrency);
const promises = batch.map((repo, batchIndex) =>
analyzeRepository(repo, i + batchIndex)
);
await Promise.all(promises);
// 避免API限制批次间稍作延迟
if (i + concurrency < targetRepos.length && !shouldStopRef.current) {
await new Promise(resolve => setTimeout(resolve, 500));
}
}

View File

@@ -68,6 +68,7 @@ export const SettingsPanel: React.FC = () => {
model: '',
customPrompt: '',
useCustomPrompt: false,
concurrency: 1,
});
const [webdavForm, setWebDAVForm] = useState({
@@ -86,6 +87,7 @@ export const SettingsPanel: React.FC = () => {
model: '',
customPrompt: '',
useCustomPrompt: false,
concurrency: 1,
});
setShowAIForm(false);
setEditingAIId(null);
@@ -119,6 +121,7 @@ export const SettingsPanel: React.FC = () => {
isActive: false,
customPrompt: aiForm.customPrompt || undefined,
useCustomPrompt: aiForm.useCustomPrompt,
concurrency: aiForm.concurrency,
};
if (editingAIId) {
@@ -138,6 +141,7 @@ export const SettingsPanel: React.FC = () => {
model: config.model,
customPrompt: config.customPrompt || '',
useCustomPrompt: config.useCustomPrompt || false,
concurrency: config.concurrency || 1,
});
setEditingAIId(config.id);
setShowAIForm(true);
@@ -531,6 +535,24 @@ Focus on practicality and accurate categorization to help users quickly understa
placeholder="gpt-4"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
{t('并发数', 'Concurrency')}
</label>
<input
type="number"
min="1"
max="10"
value={aiForm.concurrency}
onChange={(e) => setAIForm(prev => ({ ...prev, concurrency: Math.max(1, Math.min(10, parseInt(e.target.value) || 1)) }))}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white"
placeholder="1"
/>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{t('同时进行AI分析的仓库数量 (1-10)', 'Number of repositories to analyze simultaneously (1-10)')}
</p>
</div>
</div>
{/* Custom Prompt Section */}
@@ -631,7 +653,7 @@ Focus on practicality and accurate categorization to help users quickly understa
)}
</h4>
<p className="text-sm text-gray-500 dark:text-gray-400">
{config.baseUrl} {config.model}
{config.baseUrl} {config.model} {t('并发数', 'Concurrency')}: {config.concurrency || 1}
</p>
</div>
</div>

View File

@@ -74,6 +74,7 @@ export interface AIConfig {
isActive: boolean;
customPrompt?: string; // 自定义提示词
useCustomPrompt?: boolean; // 是否使用自定义提示词
concurrency?: number; // AI分析并发数默认为1
}
export interface WebDAVConfig {