diff --git a/frontend/src/views/BookManage/BookDetail/index.vue b/frontend/src/views/BookManage/BookDetail/index.vue index d51b495..2ff3ca3 100644 --- a/frontend/src/views/BookManage/BookDetail/index.vue +++ b/frontend/src/views/BookManage/BookDetail/index.vue @@ -5,8 +5,6 @@ import { getBook, type Book, retryFailed, softDeleteBook } from '@/api/book'; import { getDocumentUrl } from '@/api/document'; import { Message } from '@arco-design/web-vue'; -type FileKind = 'docx' | 'html' | 'json' | 'error_log'; - const route = useRoute(); const router = useRouter(); const bookId = Number(route.params.id); @@ -16,23 +14,23 @@ const loading = ref(false); const selectedDocId = ref(null); const activeTab = ref<'word' | 'html' | 'json'>('html'); -const selectedDoc = computed(() => { - if (!book.value || !selectedDocId.value) return null; - return book.value.documents.find((d) => d.doc_id === selectedDocId.value); -}); - -// 当前 tab 对应的 file_type -const fileType: Record = { +type FileKind = 'docx' | 'html' | 'json' | 'error_log'; +const fileTypeMap: Record = { word: 'docx', html: 'html', json: 'json', }; +const selectedDoc = computed(() => { + if (!book.value || !selectedDocId.value) return null; + return book.value.documents.find((d) => d.doc_id === selectedDocId.value); +}); + const fileUrl = ref(''); const fileLoading = ref(false); const fetchFileUrl = async () => { - if (!selectedDoc.value || !activeTab.value) { + if (!selectedDoc.value) { fileUrl.value = ''; return; } @@ -40,9 +38,9 @@ const fetchFileUrl = async () => { try { const r = await getDocumentUrl( selectedDoc.value.doc_id, - fileType[activeTab.value], + fileTypeMap[activeTab.value], ); - fileUrl.value = r.url; + fileUrl.value = r?.url ?? ''; } catch (e) { fileUrl.value = ''; } finally { @@ -62,7 +60,7 @@ const fetchBook = async () => { } }; -watch([selectedDocId, activeTab], fetchFileUrl); +watch([selectedDocId, activeTab], fetchFileUrl, { immediate: false }); const onRetry = async () => { const r = await retryFailed(bookId); @@ -82,21 +80,8 @@ const onDelete = async () => { } }; -const formatBytes = (n: number): string => { - if (!n) return '0 B'; - if (n < 1024) return `${n} B`; - if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`; - return `${(n / 1024 / 1024).toFixed(2)} MB`; -}; - -const statusColor: Record = { - pending: 'gray', - processing: 'arcoblue', - html_ready: 'green', - json_ready: 'green', - done: 'green', - failed: 'red', - partial: 'orange', +const openInNewTab = (url: string) => { + window.open(url, '_blank'); }; const statusText: Record = { @@ -109,13 +94,14 @@ const statusText: Record = { partial: '部分失败', }; -const docTypeColor: Record = { - 课时作业: 'arcoblue', - 周末提升: 'purple', - 阶段质量评估: 'orange', - 期末质量评估: 'red', - answer: 'cyan', - unknown: 'gray', +const statusColor: Record = { + pending: 'gray', + processing: 'arcoblue', + html_ready: 'green', + json_ready: 'green', + failed: 'red', + partial: 'orange', + done: 'green', }; const completionRate = computed(() => { @@ -123,31 +109,31 @@ const completionRate = computed(() => { return Math.round((book.value.success_count / book.value.total_count) * 100); }); -const openInNewTab = (url: string) => { - window.open(url, '_blank'); -}; +const truncate = (s: string, len = 8) => (s ? `${s.slice(0, len)}…` : ''); onMounted(fetchBook); @@ -387,45 +330,86 @@ onMounted(fetchBook);