feat(batch-import): implement backend batch import service with adaptive concurrency

- Add BatchImportService with concurrent execution using asyncio.gather
- Implement AdaptiveConcurrencyController with dynamic adjustment
- Add input validation for URLs and local paths
- Support duplicate detection via skip_duplicates parameter
- Add WebSocket progress broadcasting for real-time updates
- Create comprehensive unit tests for batch import functionality
- Update API handlers and route registrations
- Add i18n translation keys for batch import UI
This commit is contained in:
Will Miao
2026-03-14 06:54:24 +08:00
parent c89d4dae85
commit f86651652c
8 changed files with 1928 additions and 127 deletions

View File

@@ -729,6 +729,42 @@
"failed": "Failed to repair recipe: {message}",
"missingId": "Cannot repair recipe: Missing recipe ID"
}
},
"batchImport": {
"title": "Batch Import Recipes",
"action": "Batch Import",
"urlsMode": "URLs / Paths",
"directoryMode": "Directory",
"urlsDescription": "Enter image URLs or local file paths (one per line). Each will be imported as a recipe.",
"urlsLabel": "Image URLs or Local Paths",
"urlsPlaceholder": "https://civitai.com/images/...\nhttps://civitai.com/images/...\nC:/path/to/image.png\n...",
"directoryDescription": "Enter a directory path to import all images from that folder.",
"directoryLabel": "Directory Path",
"directoryPlaceholder": "/path/to/images/folder",
"tagsOptional": "Tags (optional, applied to all recipes)",
"addTagPlaceholder": "Add a tag",
"addTag": "Add",
"noTags": "No tags added",
"skipNoMetadata": "Skip images without metadata",
"skipNoMetadataHelp": "Images without LoRA metadata will be skipped automatically.",
"startImport": "Start Import",
"importing": "Importing Recipes...",
"progress": "Progress",
"currentItem": "Current",
"preparing": "Preparing...",
"cancelImport": "Cancel",
"cancelled": "Batch import cancelled",
"completed": "Import Completed",
"completedSuccess": "Successfully imported {count} recipe(s)",
"successCount": "Successful",
"failedCount": "Failed",
"skippedCount": "Skipped",
"totalProcessed": "Total processed",
"errors": {
"enterUrls": "Please enter at least one URL or path",
"enterDirectory": "Please enter a directory path",
"startFailed": "Failed to start import: {message}"
}
}
},
"checkpoints": {