diff --git a/frontend/src/views/ArticleDetail.vue b/frontend/src/views/ArticleDetail.vue index 9336800..484a03f 100644 --- a/frontend/src/views/ArticleDetail.vue +++ b/frontend/src/views/ArticleDetail.vue @@ -64,6 +64,64 @@ const publishedAt = computed(() => article.value?.published_at || article.value? const isOwner = computed(() => auth.isOwner) const categories = computed(() => (article.value?.category || '').split(',').filter(Boolean)) +/** 把"一坨"译文/原文按"中文句号"切成
段,改善"挤在一起"的观感。 + * 优先按 \n 切(LLM 排版过的),没有换行再按句号/问号/感叹号切。 + * 句中常见的"Mr./U.S."等缩写不会出现在中文译文里,按 6+ 字符才切,避免半句话被切。 + */ +function splitIntoParagraphs(html: string): string { + // 已经是 HTML 标签(LLM 排版过),不动 + if (/<(p|div|br)\b/i.test(html)) return html + // 按 \n 切 + if (/\n/.test(html)) { + return html + .split(/\n+/) + .map((p) => p.trim()) + .filter(Boolean) + .map((p) => `
${escapeHtml(p)}
`) + .join('') + } + // 一坨纯文字:按句号/问号/感叹号切,每段最多 140 字 + const text = html.trim() + if (!text) return '' + const chunks: string[] = [] + const re = /([。!?!?])(?=[^。!?!?]{0,140})/g + let last = 0 + let m: RegExpExecArray | null + while ((m = re.exec(text)) !== null) { + const end = m.index + 1 + if (end - last > 6) { + chunks.push(text.slice(last, end)) + last = end + } + } + if (last < text.length) chunks.push(text.slice(last)) + return chunks.map((p) => `${escapeHtml(p.trim())}
`).join('') +} + +function escapeHtml(s: string): string { + return s + .replace(/&/g, '&') + .replace(//g, '>') +} + +const translationBody = computed(() => { + const a = article.value + if (!a) return '' + if (a.body_zh_formatted) return a.body_zh_formatted + if (a.body_zh_html) return splitIntoParagraphs(a.body_zh_html) + if (a.body_zh_text) return splitIntoParagraphs(a.body_zh_text) + return '' +}) + +const originalBody = computed(() => { + const a = article.value + if (!a) return '' + if (a.body_html) return splitIntoParagraphs(a.body_html) + if (a.body_text) return splitIntoParagraphs(a.body_text) + return '' +}) + async function rerunTranslation() { if (!article.value) return if (!confirm('重新翻译会消耗配额,确认?')) return @@ -234,8 +292,7 @@ onMounted(load) 📖 文章译文(原始) - -