Files
portfolio-generator-app/pages/print/[id].vue
Valentin Le Moign 59dfbe4155 Générateur de portfolios PDF Figures Libres (app Nuxt autonome)
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>
2026-07-05 18:37:09 +02:00

72 lines
1.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>