sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { Document, Font, Page, StyleSheet, Text, View } from '@react-pdf/renderer';
|
||||
|
||||
import type { Paper } from '../domain/paperModel';
|
||||
|
||||
/**
|
||||
* Register a Unicode TTF so Vietnamese diacritics render (react-pdf's built-in Helvetica does not
|
||||
* cover them). The Roboto TTFs are SELF-HOSTED under public/fonts so PDF export also works in
|
||||
* air-gapped production deploys (no CDN fetch at render time). If glyphs ever render as blanks,
|
||||
* replace the files with a Noto-with-Vietnamese TTF — registration is the only place it is configured.
|
||||
*/
|
||||
Font.register({
|
||||
family: 'Roboto',
|
||||
fonts: [
|
||||
{ src: '/fonts/roboto-regular.ttf' },
|
||||
{ src: '/fonts/roboto-bold.ttf', fontWeight: 'bold' },
|
||||
],
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: { fontFamily: 'Roboto', fontSize: 11, lineHeight: 1.5, padding: 48, color: '#1f2937' },
|
||||
title: { fontSize: 18, fontWeight: 'bold', marginBottom: 4 },
|
||||
titleEn: { fontSize: 12, color: '#6b7280', marginBottom: 12 },
|
||||
meta: { fontSize: 9, color: '#6b7280', marginBottom: 16 },
|
||||
h2: { fontSize: 12, fontWeight: 'bold', marginTop: 14, marginBottom: 4 },
|
||||
body: { textAlign: 'justify' },
|
||||
source: { marginBottom: 3 },
|
||||
badge: { fontSize: 9, color: '#047857', marginTop: 16 },
|
||||
});
|
||||
|
||||
export function PaperPdfDocument({ paper, projectTitle }: { paper: Paper; projectTitle?: string }) {
|
||||
return (
|
||||
<Document title={paper.title || 'Bài báo'} author={paper.approval?.approvedByName}>
|
||||
<Page size="A4" style={styles.page}>
|
||||
<Text style={styles.title}>{paper.title || '(Chưa đặt tiêu đề)'}</Text>
|
||||
{paper.titleEn ? <Text style={styles.titleEn}>{paper.titleEn}</Text> : null}
|
||||
|
||||
<Text style={styles.meta}>
|
||||
{projectTitle ? `Đề tài: ${projectTitle}` : ''}
|
||||
{paper.publishedAt
|
||||
? ` · Xuất bản: ${new Date(paper.publishedAt).toLocaleDateString('vi-VN')}`
|
||||
: ' · Bản thảo'}
|
||||
{paper.approval ? ` · Phê duyệt: ${paper.approval.approvedByName}` : ''}
|
||||
</Text>
|
||||
|
||||
{paper.abstractVi ? (
|
||||
<View>
|
||||
<Text style={styles.h2}>Tóm tắt</Text>
|
||||
<Text style={styles.body}>{paper.abstractVi}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{paper.abstractEn ? (
|
||||
<View>
|
||||
<Text style={styles.h2}>Abstract</Text>
|
||||
<Text style={styles.body}>{paper.abstractEn}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{paper.body ? (
|
||||
<View>
|
||||
<Text style={styles.h2}>Nội dung</Text>
|
||||
<Text style={styles.body}>{paper.body}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{paper.sources.length > 0 ? (
|
||||
<View>
|
||||
<Text style={styles.h2}>Tài liệu tham khảo</Text>
|
||||
{paper.sources.map((s, i) => (
|
||||
<Text key={s.id} style={styles.source}>
|
||||
[{i + 1}] {s.title}
|
||||
{s.authors ? ` — ${s.authors}` : ''}
|
||||
{s.doiOrUrl ? ` (${s.doiOrUrl})` : ''}
|
||||
{s.verifiedReal ? ' ✓' : ''}
|
||||
</Text>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
{paper.status === 'published' && paper.approval ? (
|
||||
<Text style={styles.badge}>
|
||||
Đã phê duyệt & xuất bản bởi {paper.approval.approvedByName} —{' '}
|
||||
{new Date(paper.approval.approvedAt).toLocaleString('vi-VN')}
|
||||
</Text>
|
||||
) : null}
|
||||
</Page>
|
||||
</Document>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user