Corrige proporção de cartazes, layout paisagem e recorte de imagens ilustrativas

This commit is contained in:
2026-06-07 16:09:40 +00:00
parent 03f9317853
commit f81b7c0f5c
3 changed files with 89 additions and 11 deletions
+54 -3
View File
@@ -6998,7 +6998,51 @@ document.addEventListener('DOMContentLoaded', () => {
cartazPrintableArea.style.backgroundColor = bg; cartazPrintableArea.style.backgroundColor = bg;
cartazPrintableArea.style.color = text; cartazPrintableArea.style.color = text;
cartazPrintableArea.style.fontFamily = font; cartazPrintableArea.style.fontFamily = font;
cartazPrintableArea.style.maxWidth = orientacao === 'paisagem' ? '800px' : '500px';
if (orientacao === 'paisagem') {
cartazPrintableArea.style.maxWidth = '800px';
cartazPrintableArea.style.aspectRatio = '1.414 / 1';
cartazPrintableArea.style.height = 'auto';
cartazPreviewContent.style.flexDirection = 'row';
cartazPreviewContent.style.flexWrap = 'wrap';
cartazPreviewContent.style.justifyContent = 'center';
cartazPreviewContent.style.alignContent = 'flex-start';
cartazPreviewContent.style.gap = '12px';
setTimeout(() => {
Array.from(cartazPreviewContent.children).forEach(child => {
child.style.flex = '1 1 calc(50% - 12px)';
child.style.boxSizing = 'border-box';
child.style.margin = '0';
child.style.background = 'rgba(255,255,255,0.25)';
child.style.padding = '12px';
child.style.borderRadius = '8px';
child.style.border = '1px solid rgba(0,0,0,0.05)';
});
}, 0);
} else {
cartazPrintableArea.style.maxWidth = '500px';
cartazPrintableArea.style.aspectRatio = '1 / 1.414';
cartazPrintableArea.style.height = 'auto';
cartazPreviewContent.style.flexDirection = 'column';
cartazPreviewContent.style.flexWrap = 'nowrap';
cartazPreviewContent.style.justifyContent = 'flex-start';
cartazPreviewContent.style.gap = '12px';
setTimeout(() => {
Array.from(cartazPreviewContent.children).forEach(child => {
child.style.flex = '0 0 auto';
child.style.width = '100%';
child.style.boxSizing = 'border-box';
child.style.margin = '0';
child.style.background = 'rgba(255,255,255,0.25)';
child.style.padding = '12px';
child.style.borderRadius = '8px';
child.style.border = '1px solid rgba(0,0,0,0.05)';
});
}, 0);
}
cartazPreviewTitle.textContent = title; cartazPreviewTitle.textContent = title;
cartazPreviewTitle.style.borderColor = text; cartazPreviewTitle.style.borderColor = text;
@@ -7124,7 +7168,7 @@ document.addEventListener('DOMContentLoaded', () => {
const orientacao = document.getElementById('cartazOrientacaoSelect') ? document.getElementById('cartazOrientacaoSelect').value : 'retrato'; const orientacao = document.getElementById('cartazOrientacaoSelect') ? document.getElementById('cartazOrientacaoSelect').value : 'retrato';
const imgContainerHtml = cartazPreviewImageContainer.style.display === 'block' const imgContainerHtml = cartazPreviewImageContainer.style.display === 'block'
? `<div style="width: 100%; margin-bottom: 20px; border-radius: 8px; overflow: hidden; max-height: 400px; border: 2px solid rgba(0,0,0,0.1);"><img src="${cartazPreviewImage.src}" style="width: 100%; height: 100%; object-fit: cover;"></div>` ? `<div style="width: 100%; margin-bottom: 20px; border-radius: 8px; overflow: hidden; border: 2px solid rgba(0,0,0,0.1); text-align: center; background: rgba(0,0,0,0.02);"><img src="${cartazPreviewImage.src}" style="max-width: 100%; max-height: 350px; object-fit: contain; display: inline-block;"></div>`
: ''; : '';
const printWindow = window.open('', '_blank'); const printWindow = window.open('', '_blank');
@@ -7157,9 +7201,12 @@ document.addEventListener('DOMContentLoaded', () => {
border-radius: 16px; border-radius: 16px;
width: 100%; width: 100%;
max-width: ${orientacao === 'paisagem' ? '1200px' : '800px'}; max-width: ${orientacao === 'paisagem' ? '1200px' : '800px'};
aspect-ratio: ${orientacao === 'paisagem' ? '1.414 / 1' : '1 / 1.414'};
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
box-sizing: border-box; box-sizing: border-box;
border: ${border === 'none' ? 'none' : `${border} ${text}`}; border: ${border === 'none' ? 'none' : `${border} ${text}`};
display: flex;
flex-direction: column;
} }
h1 { h1 {
text-align: center; text-align: center;
@@ -7173,17 +7220,21 @@ document.addEventListener('DOMContentLoaded', () => {
font-size: 1.5rem; font-size: 1.5rem;
line-height: 1.6; line-height: 1.6;
display: flex; display: flex;
flex-direction: ${orientacao === 'paisagem' ? 'row' : 'column'};
flex-wrap: wrap; flex-wrap: wrap;
gap: 20px; gap: 20px;
justify-content: center; justify-content: center;
} }
/* Suporte para cards na content-area */ /* Suporte para cards na content-area */
.content-area > div, .content-area > p, .content-area > ul { .content-area > div, .content-area > p, .content-area > ul {
box-sizing: border-box;
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
padding: 20px; padding: 20px;
border-radius: 12px; border-radius: 12px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05); box-shadow: 0 2px 4px rgba(0,0,0,0.05);
width: 100%; width: ${orientacao === 'paisagem' ? 'calc(50% - 20px)' : '100%'};
flex: ${orientacao === 'paisagem' ? '1 1 calc(50% - 20px)' : '0 0 auto'};
margin: 0;
} }
ul { ul {
margin-left: 20px; margin-left: 20px;
+3 -3
View File
@@ -1868,12 +1868,12 @@
<h1 id="cartazPreviewTitle" style="text-align: center; margin-top: 0; font-size: 2.2rem; border-bottom: 2px solid; padding-bottom: 12px; margin-bottom: 20px;">Título do Cartaz</h1> <h1 id="cartazPreviewTitle" style="text-align: center; margin-top: 0; font-size: 2.2rem; border-bottom: 2px solid; padding-bottom: 12px; margin-bottom: 20px;">Título do Cartaz</h1>
<!-- Área da Imagem IA no Cartaz --> <!-- Área da Imagem IA no Cartaz -->
<div id="cartazPreviewImageContainer" style="display: none; width: 100%; margin-bottom: 20px; border-radius: 8px; overflow: hidden; max-height: 250px; border: 2px solid rgba(0,0,0,0.1);"> <div id="cartazPreviewImageContainer" style="display: none; width: 100%; margin-bottom: 20px; border-radius: 8px; border: 2px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.02); text-align: center; overflow: hidden;">
<img id="cartazPreviewImage" src="" style="width: 100%; height: 100%; object-fit: cover;"> <img id="cartazPreviewImage" src="" style="max-width: 100%; max-height: 240px; object-fit: contain; display: inline-block; vertical-align: middle;">
</div> </div>
<!-- Conteúdo de Texto do Cartaz --> <!-- Conteúdo de Texto do Cartaz -->
<div id="cartazPreviewContent" style="font-size: 1.1rem; line-height: 1.6; flex: 1;"> <div id="cartazPreviewContent" style="font-size: 1.1rem; line-height: 1.6; flex: 1; display: flex; flex-direction: column; gap: 12px;">
<p style="text-align: center; color: #718096; font-style: italic;">Clique em "Criar Cartaz Pedagógico" para que a assistente monte e estruture o cartaz ideal para você.</p> <p style="text-align: center; color: #718096; font-style: italic;">Clique em "Criar Cartaz Pedagógico" para que a assistente monte e estruture o cartaz ideal para você.</p>
</div> </div>
</div> </div>
+32 -5
View File
@@ -1400,8 +1400,13 @@ Detalhes do Cartaz:
- Orientação: "${orientacao === 'paisagem' ? 'Paisagem/Horizontal' : 'Retrato/Vertical'}" - Orientação: "${orientacao === 'paisagem' ? 'Paisagem/Horizontal' : 'Retrato/Vertical'}"
Por favor, gere o CONTEÚDO textual e estrutural do cartaz em HTML. Por favor, gere o CONTEÚDO textual e estrutural do cartaz em HTML.
REGRAS FUNDAMENTAIS E ESTÉTICAS:
- O cartaz deve caber ESTRITAMENTE em UMA ÚNICA PÁGINA (Tamanho ${tamanho || 'A4'}, orientação ${orientacao === 'paisagem' ? 'Horizontal' : 'Vertical'}). Não crie textos longos ou listas que fariam a folha "vazar" na impressão. REGRAS DE IDIOMA E LOCALIZAÇÃO:
- O conteúdo gerado deve ser IMPRETERIVELMENTE em português do Brasil (pt-BR). Não use termos em outros idiomas de forma desnecessária.
REGRAS FUNDAMENTAIS E ESTÉTICAS DE DIAGRAMAÇÃO:
- O cartaz deve caber ESTRITAMENTE em UMA ÚNICA PÁGINA FÍSICA (Tamanho ${tamanho || 'A4'}, orientação ${orientacao === 'paisagem' ? 'Horizontal/Paisagem' : 'Vertical/Retrato'}). Não extrapole este espaço de forma alguma.
- Limite a quantidade de conteúdo: gere no máximo 2 ou 3 cards (divs de conteúdo) no total. Cada card deve ter pouquíssimo texto (no máximo 3 ou 4 itens curtos por card).
- Distribua a informação em CARDS (pequenos cartões ou blocos curtos) bem espaçados, parecidos com pôsteres infantis modernos, onde o texto NÃO ocupa uma folha corrida. - Distribua a informação em CARDS (pequenos cartões ou blocos curtos) bem espaçados, parecidos com pôsteres infantis modernos, onde o texto NÃO ocupa uma folha corrida.
- Os textos devem ser extremamente curtos, diretos, visuais e fáceis de ler. - Os textos devem ser extremamente curtos, diretos, visuais e fáceis de ler.
- Use emojis apropriados para crianças. - Use emojis apropriados para crianças.
@@ -1409,7 +1414,7 @@ REGRAS FUNDAMENTAIS E ESTÉTICAS:
- Se for "informativo", destaque avisos gerais e orientações (ex: horários, cardápio, provas) em caixas curtas e legíveis. - Se for "informativo", destaque avisos gerais e orientações (ex: horários, cardápio, provas) em caixas curtas e legíveis.
- Se for "conscientizacao", use frases curtas de impacto sobre campanhas (ex: prevenção, saúde, coleta seletiva), acompanhadas de dicas em pequenos blocos. - Se for "conscientizacao", use frases curtas de impacto sobre campanhas (ex: prevenção, saúde, coleta seletiva), acompanhadas de dicas em pequenos blocos.
- Se for "cultural", promova a atividade de lazer, esporte ou feira destacando o evento de forma animada e pontual. - Se for "cultural", promova a atividade de lazer, esporte ou feira destacando o evento de forma animada e pontual.
- Considere a orientação ${orientacao === 'paisagem' ? 'Paisagem (horizontal)' : 'Retrato (vertical)'} ao organizar o fluxo: para paisagem, use \`display: flex; flex-wrap: wrap; gap: 20px;\` para os cards ficarem lado a lado; para retrato, de cima para baixo. - Considere a orientação ${orientacao === 'paisagem' ? 'Paisagem (horizontal)' : 'Retrato (vertical)'} ao organizar o fluxo: para paisagem, os cards devem ficar lado a lado (2 colunas horizontais); para retrato, eles se empilham verticalmente.
- Retorne apenas o formato HTML (use <div>, <p>, <ul>, <li>, <strong>, <span>). Não adicione <html> ou <body>, retorne apenas o conteúdo interno. Não inclua o título <h1> pois ele já é colocado no topo pela interface.`; - Retorne apenas o formato HTML (use <div>, <p>, <ul>, <li>, <strong>, <span>). Não adicione <html> ou <body>, retorne apenas o conteúdo interno. Não inclua o título <h1> pois ele já é colocado no topo pela interface.`;
let conteudoHtml = ''; let conteudoHtml = '';
@@ -1464,7 +1469,29 @@ REGRAS FUNDAMENTAIS E ESTÉTICAS:
let generatedImageUrl = null; let generatedImageUrl = null;
if (promptImagem && promptImagem.trim().length > 3) { if (promptImagem && promptImagem.trim().length > 3) {
try { try {
console.log('[Cartazes] Gerando ilustração para o cartaz...'); console.log('[Cartazes] Refinando prompt de imagem para inglês (sem texto)...');
let refinedPrompt = promptImagem;
try {
const refineRes = await callMinimax({
messages: [{
role: 'user',
content: `Translate the following Portuguese description into a clean English description suitable for an image generation prompt.
Make sure the prompt specifies a beautiful, colorful, kid-friendly vector/illustration style.
CRITICAL REQUIREMENT: Explicitly specify in the prompt that there should be absolutely no text, no words, no signs, no letters, no labels, no speech bubbles, and no writing of any kind.
Portuguese description: "${promptImagem}"
Return ONLY the English prompt, no extra chat.`
}],
temperature: 0.3,
max_tokens: 250
});
if (refineRes && refineRes.text) {
refinedPrompt = refineRes.text;
}
} catch (refineErr) {
console.error('[Cartazes] Erro ao refinar prompt:', refineErr);
}
console.log('[Cartazes] Gerando ilustração com prompt final:', refinedPrompt);
const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, ''); const minmBase = (process.env.MINIMAX_API_BASE || 'https://api.minimax.io/v1').replace(/\/v1\/?$/, '');
const genResp = await fetch(`${minmBase}/v1/image_generation`, { const genResp = await fetch(`${minmBase}/v1/image_generation`, {
method: 'POST', method: 'POST',
@@ -1474,7 +1501,7 @@ REGRAS FUNDAMENTAIS E ESTÉTICAS:
}, },
body: JSON.stringify({ body: JSON.stringify({
model: 'image-01', model: 'image-01',
prompt: `${promptImagem}. Estilo ilustração de livro infantil de alta qualidade, 3D Pixar, cores suaves, traço limpo, sem texto.`, prompt: `${refinedPrompt}. Complete figures shown from top to bottom without cutoffs, kid-friendly illustration style, 3D Pixar, soft pastel colors, no text, no words, no letters, no writing, no labels.`,
n: 1 n: 1
}) })
}); });