App Nuxt 3 + Nuxt UI qui lit les projets du CMS Grav et compose des portfolios A3 paysage exportés en PDF (gabarit book_v3) : composeur WYSIWYG, templates cover/toc/projet/grille/page libre, pipeline Playwright + Ghostscript, gel du contenu à la génération, partage public opt-in. Dépôt autonome : Dockerfile (base Playwright + Ghostscript + ffmpeg + rsync) inclus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
72 lines
1.8 KiB
Vue
72 lines
1.8 KiB
Vue
<script setup lang="ts">
|
||
// Route de rendu print : toutes les pages du portfolio empilées, imprimées
|
||
// par Playwright/Chromium (une page CSS = une page PDF, spec §10).
|
||
// Accès par jeton interne uniquement (?internal-token=…).
|
||
import type { Portfolio, Project } from '~~/types'
|
||
|
||
definePageMeta({ layout: false })
|
||
|
||
const route = useRoute()
|
||
const token = String(route.query['internal-token'] ?? '')
|
||
const headers = { 'x-internal-token': token }
|
||
|
||
const { data: portfolio } = await useFetch<Portfolio>(`/api/portfolios/${route.params.id}`, { headers })
|
||
if (!portfolio.value) {
|
||
throw createError({ statusCode: 404, statusMessage: 'Portfolio introuvable' })
|
||
}
|
||
|
||
// Contenu figé si présent (régénération à l'identique), live sinon
|
||
const frozen = portfolio.value.frozenContent
|
||
let projects: Record<string, Project>
|
||
if (frozen) {
|
||
projects = frozen.projects
|
||
} else {
|
||
const { data } = await useFetch<{ projects: Project[] }>('/api/projects', { headers })
|
||
projects = Object.fromEntries((data.value?.projects ?? []).map(p => [p.id, p]))
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="print-root">
|
||
<div v-for="(page, i) in portfolio!.pages" :id="`page-${i + 1}`" :key="page.id" class="print-page">
|
||
<PageRenderer
|
||
:portfolio="portfolio!"
|
||
:page="page"
|
||
:index="i"
|
||
:projects="projects"
|
||
render-mode="print"
|
||
:frozen="frozen ? portfolio!.id : undefined"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style>
|
||
/* Une page CSS = une page PDF — A3 paysage du gabarit :
|
||
1190,55 × 841,89 pt ≡ 1587,4 × 1122,5 px */
|
||
@page {
|
||
size: 1190.55pt 841.89pt;
|
||
margin: 0;
|
||
}
|
||
|
||
html,
|
||
body {
|
||
margin: 0;
|
||
padding: 0;
|
||
background: #ffffff;
|
||
}
|
||
|
||
.print-page {
|
||
width: 1587.4px;
|
||
height: 1122.5px;
|
||
overflow: hidden;
|
||
page-break-after: always;
|
||
break-after: page;
|
||
}
|
||
|
||
.print-page:last-child {
|
||
page-break-after: auto;
|
||
break-after: auto;
|
||
}
|
||
</style>
|