feat: add translated PDF format selection (layout/reflow)

- Add generate_translated_layout_pdf() method for layout-preserving translated PDFs
- Add generate_translated_pdf() method for reflow translated PDFs
- Update translate router to accept format parameter (layout/reflow)
- Update frontend with dropdown to select translated PDF format
- Fix reflow PDF table cell extraction from content dict
- Add embedded images handling in reflow PDF tables
- Archive improve-translated-text-fitting openspec proposal

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-03 10:10:28 +08:00
parent 0dcea4a7e7
commit 08adf3d01d
15 changed files with 1384 additions and 1222 deletions

View File

@@ -494,16 +494,20 @@ class ApiClientV2 {
/**
* Download task result as PDF
* @param taskId - The task ID
* @param format - PDF format: 'layout' (default) or 'reflow'
*/
async downloadPDF(taskId: string): Promise<void> {
async downloadPDF(taskId: string, format: 'layout' | 'reflow' = 'layout'): Promise<void> {
const response = await this.client.get(`/tasks/${taskId}/download/pdf`, {
params: format === 'reflow' ? { format: 'reflow' } : undefined,
responseType: 'blob',
})
const blob = new Blob([response.data], { type: 'application/pdf' })
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = `${taskId}_result.pdf`
const formatSuffix = format === 'reflow' ? '_reflow' : '_layout'
link.download = `${taskId}${formatSuffix}.pdf`
link.click()
window.URL.revokeObjectURL(link.href)
}
@@ -688,18 +692,26 @@ class ApiClientV2 {
}
/**
* Download translated PDF with layout preservation
* Download translated PDF
* @param taskId - The task ID
* @param lang - Target language code
* @param format - PDF format: 'layout' or 'reflow' (default: 'reflow')
*/
async downloadTranslatedPdf(taskId: string, lang: string): Promise<void> {
async downloadTranslatedPdf(
taskId: string,
lang: string,
format: 'layout' | 'reflow' = 'reflow'
): Promise<void> {
const response = await this.client.post(`/translate/${taskId}/pdf`, null, {
params: { lang },
params: { lang, format },
responseType: 'blob',
})
const formatSuffix = format === 'layout' ? '_layout' : '_reflow'
const blob = new Blob([response.data], { type: 'application/pdf' })
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = `${taskId}_translated_${lang}.pdf`
link.download = `${taskId}_translated_${lang}${formatSuffix}.pdf`
link.click()
window.URL.revokeObjectURL(link.href)
}