From 5b73983805ae31eb73ada8f5eec9b70695e5eab0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA?= <ник@zeroday.su> Date: Mon, 8 Jun 2026 21:10:16 +0300 Subject: [PATCH] =?UTF-8?q?feat(document):=20=D0=BF=D0=BE=D0=B4=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D1=8B=205.1/5.2=20+=20=D0=B1?= =?UTF-8?q?=D0=BB=D0=BE=D0=BA=20=C2=AB=D0=A0=D0=B0=D0=B7=D1=80=D1=8B=D0=B2?= =?UTF-8?q?=C2=BB=20+=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B5=D0=B3=D0=B8=D0=BE=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Расширил генератор чтобы он умел рендерить структуру эталонного отчёта: - §5 'Сравнительный анализ предприятий' разбит на 5.1 (лидеры) и 5.2 (кластеры) - 5.1: heading2 + text.leaders5_1 (массив или строка) + chart2 - 5.2: heading2 + text.cluster5_2 + text.clusterGroups (массив объектов {title, text} рендерится как жирный bullet + текст) + chart3 + text.gap (calloutBox с красной полосой) - chart4 + text.regionComparisonSummary — после блока кластеризации Раздел 5 теперь визуально соответствует эталону DT_Вологда_2026.docx. --- src/generators/document.js | 78 +++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/src/generators/document.js b/src/generators/document.js index a43a986..d67d1f8 100644 --- a/src/generators/document.js +++ b/src/generators/document.js @@ -293,31 +293,73 @@ async function buildDocument ({ subject, period, data, text, meta = {}, charts = } } - // ═══ 5. РЕГИОНАЛЬНЫЙ РАЗРЕЗ ════════════════════════════════════════════════ - if (charts.chart2 || charts.chart3 || charts.chart4) { - children.push(heading1('5. Региональный разрез и эффективность'), spacer(60)) + // ═══ 5. СРАВНИТЕЛЬНЫЙ АНАЛИЗ ══════════════════════════════════════════════ + if (charts.chart2 || charts.chart3 || charts.chart4 || text.leaders5_1 || text.cluster5_2) { + children.push(heading1('5. Сравнительный анализ предприятий'), spacer(60)) - if (text.regionalSummary) { - children.push(body(text.regionalSummary), spacer(100)) + // 5.1 Лидеры по субсидиям, прибыли и переработке + if (text.leaders5_1 || charts.chart2) { + children.push(heading2('5.1. Лидеры по субсидиям, прибыли и переработке')) + if (text.leaders5_1) { + if (Array.isArray(text.leaders5_1)) text.leaders5_1.forEach(t => children.push(body(t))) + else children.push(body(text.leaders5_1)) + children.push(spacer(60)) + } + if (charts.chart2) { + children.push(caption('Рисунок 2. Лидеры рынка: чистая прибыль и объём переработки')) + children.push(imgPara(charts.chart2)) + children.push(spacer(120)) + } } - if (charts.chart2) { - children.push(caption('Рисунок 2. Лидеры по закупочной цене молока')) - children.push(imgPara(charts.chart2)) - children.push(spacer(80)) + // 5.2 Кластеризация предприятий по финансовым индексам (II / OH / CS) + if (text.cluster5_2 || (text.clusterGroups && text.clusterGroups.length) || charts.chart3 || text.gap) { + children.push(heading2('5.2. Кластеризация предприятий по финансовым индексам (II / OH / CS)')) + + if (text.cluster5_2) { + if (Array.isArray(text.cluster5_2)) text.cluster5_2.forEach(t => children.push(body(t))) + else children.push(body(text.cluster5_2)) + } + + if (text.clusterGroups && text.clusterGroups.length) { + text.clusterGroups.forEach(g => { + if (typeof g === 'string') { + children.push(dashBullet(g)) + } else { + // объект { title, text } — рендерим title жирно + текст + children.push(new Paragraph({ + spacing: { after: 80 }, + indent: { left: 360, hanging: 240 }, + children: [ + run('–\t', { size: 21, color: D.dGray }), + run((g.title || '') + ' ', { size: 21, bold: true, color: D.dGray }), + run(g.text || '', { size: 21, color: D.dGray }) + ] + })) + } + }) + children.push(spacer(80)) + } + + if (charts.chart3) { + children.push(caption('Рисунок 3. EBITDA margin производителей · ранжирование по группам А–В')) + children.push(imgPara(charts.chart3)) + children.push(spacer(120)) + } + + // Блок «Разрыв ...» — выделенный + if (text.gap && (text.gap.title || text.gap.text)) { + children.push(calloutBox(text.gap.title || 'Разрыв лидеров и аутсайдеров', text.gap.text || '')) + children.push(spacer(160)) + } } + // Сравнение с соседними регионами / другими ФО if (charts.chart4) { - children.push(caption('Рисунок 3. Сравнение регионов: лидеры и аутсайдеры')) + children.push(caption('Рисунок 4. Сравнение с соседними регионами и РФ')) children.push(imgPara(charts.chart4)) - children.push(spacer(80)) - } - - if (charts.chart3) { - children.push(caption('Рисунок 4. EBITDA-маржа по группам эффективности хозяйств')) - children.push(imgPara(charts.chart3)) - if (text.efficiencySummary) children.push(body(text.efficiencySummary)) - children.push(spacer(80)) + if (text.regionComparisonSummary) children.push(body(text.regionComparisonSummary)) + children.push(spacer(120)) } }