From 7e15431937f2db06e03c9c00e4ec55948216b6a1 Mon Sep 17 00:00:00 2001 From: houhuan Date: Tue, 12 May 2026 21:31:40 +0800 Subject: [PATCH] refactor: Images.vue uses shared composables, fix error handling - Import statusType/statusText/fmtTime from useFileUtils composable - Use useFilePreview composable for preview state and logic - Remove duplicated preview refs, cleanupPreview, and utility functions - Add try/finally to loadData for reliable loading state - Properly handle cancel vs error in deleteFile and batchDelete Co-Authored-By: Claude Opus 4.7 --- web/frontend/src/views/files/Images.vue | 60 +++++++------------------ 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/web/frontend/src/views/files/Images.vue b/web/frontend/src/views/files/Images.vue index ade6780..5f48149 100644 --- a/web/frontend/src/views/files/Images.vue +++ b/web/frontend/src/views/files/Images.vue @@ -121,9 +121,12 @@ import { ref, onMounted } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { Right } from '@element-plus/icons-vue' import { useProcessingStore } from '../../stores/processing' +import { statusType, statusText, fmtTime } from '../../composables/useFileUtils' +import { useFilePreview } from '../../composables/useFilePreview' import api from '../../api' const processingStore = useProcessingStore() +const { showPreview, previewType, previewSrc, previewRows, openPreview, cleanupPreview } = useFilePreview() const items = ref([]) const total = ref(0) @@ -135,65 +138,28 @@ const sortBy = ref('created_at') const sortOrder = ref('desc') const uploadInput = ref() -const showPreview = ref(false) -const previewType = ref('') -const previewSrc = ref('') -const previewRows = ref([]) const showDetailDlg = ref(false) const detailLogs = ref([]) -function statusType(s: string) { - const m: Record = { done: 'success', merged: 'success', excel_done: 'warning', ocr_done: 'info', pending: 'info' } - return m[s] || 'info' -} -function statusText(s: string) { - const m: Record = { done: '已完成', merged: '已合并', excel_done: '已处理', ocr_done: '已OCR', pending: '待处理' } - return m[s] || s -} - -function fmtTime(t: string): string { - if (!t) return '--' - return t.replace('T', ' ').slice(0, 19) -} - async function loadData() { loading.value = true try { const res = await api.get('/files/relations', { params: { view: 'images', page: page.value, page_size: pageSize, sort_by: sortBy.value, sort_order: sortOrder.value } }) items.value = res.data.items total.value = res.data.total - } catch {} - loading.value = false + } catch { + ElMessage.error('加载文件列表失败') + } finally { + loading.value = false + } } function onSelect(rows: any[]) { selected.value = rows } async function previewFile(row: any) { - const token = localStorage.getItem('token') const fname = row.input_image || row.output_excel || row.result_purchase const dir = row.input_image ? 'input' : row.output_excel ? 'output' : 'result' - try { - const resp = await fetch(`/api/files/preview/${dir}/${encodeURIComponent(fname)}`, { headers: { Authorization: `Bearer ${token}` } }) - const ct = resp.headers.get('content-type') || '' - if (ct.includes('image')) { - previewType.value = 'image' - const blob = await resp.blob() - previewSrc.value = URL.createObjectURL(blob) - } else { - const data = await resp.json() - if (data.type === 'excel') { previewType.value = 'excel'; previewRows.value = data.rows } - } - showPreview.value = true - } catch { ElMessage.error('预览失败') } -} - -function cleanupPreview() { - if (previewSrc.value && previewSrc.value.startsWith('blob:')) { - URL.revokeObjectURL(previewSrc.value) - } - previewSrc.value = '' - previewType.value = '' - previewRows.value = [] + await openPreview(dir, fname) } function showDetail(row: any) { @@ -269,7 +235,9 @@ async function deleteFile(row: any) { if (row.id) await api.delete('/files/relations', { data: { ids: [row.id] } }) ElMessage.success('已删除') loadData() - } catch {} + } catch (err: any) { + if (err !== 'cancel') ElMessage.error('删除失败') + } } async function batchPipeline() { @@ -314,7 +282,9 @@ async function batchDelete() { } ElMessage.success('批量删除完成') loadData() - } catch {} + } catch (err: any) { + if (err !== 'cancel') ElMessage.error('批量删除失败') + } } onMounted(loadData)