This commit is contained in:
root
2025-12-20 23:25:02 +05:00
parent 6a7556df2f
commit e186e36a74
3 changed files with 297 additions and 81 deletions
+15 -81
View File
@@ -392,34 +392,7 @@
</div>
<!-- Segments Channel Matrix (Heatmap) -->
<div v-if="segment.segmentsChannelMatrix" class="mt-6">
<div class="flex align-items-center mb-3">
<i class="pi pi-th-large text-primary-500 mr-2"></i>
<h4 class="text-lg font-semibold text-surface-700 dark:text-surface-300 m-0">Матрица каналов по сегментам</h4>
</div>
<div class="overflow-x-auto border-round" style="border: 1px solid var(--surface-border)">
<table class="channel-matrix-table w-full border-collapse">
<thead>
<tr>
<th class="channel-matrix-th">Сегмент</th>
<th v-for="channel in segment.segmentsChannelMatrix.channels" :key="channel" class="channel-matrix-th text-center">
{{ channel }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, idx) in segment.segmentsChannelMatrix.data" :key="idx" class="channel-matrix-tr">
<td class="channel-matrix-td font-semibold">{{ row.segmentName }}</td>
<td v-for="channel in segment.segmentsChannelMatrix.channels" :key="channel" class="channel-matrix-td text-center">
<span class="channel-matrix-badge" :style="{ backgroundColor: getChannelMatrixColor(row[channel]) }">
{{ row[channel] || '-' }}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<SegmentsChannelMatrixHeatmap v-if="segment.segmentsChannelMatrix" :matrix="segment.segmentsChannelMatrix" />
<!-- Key Takeaways -->
<div v-if="segment.keyTakeaways && segment.keyTakeaways.length > 0" class="mt-6">
@@ -438,6 +411,10 @@
</div>
</div>
<div v-else-if="segment.type === 'segmentsChannelMatrix'">
<HeatmapTable :matrix="segment.matrix" :title="segment.title || 'Матрица каналов по сегментам'" />
</div>
<div v-else-if="segment.type === 'competitors'">
<div class="mb-4">
<h3 class="text-xl font-semibold text-surface-900 dark:text-surface-0"><i class="pi pi-chart-line mr-2"></i>Анализ конкурентов</h3>
@@ -783,6 +760,7 @@
</template>
<script setup>
import SegmentsChannelMatrixHeatmap from '@/components/marketing/SegmentsChannelMatrixHeatmap.vue';
import MarketingService from '@/service/MarketingService';
import { marked } from 'marked';
import markedKatex from 'marked-katex-extension';
@@ -1812,16 +1790,6 @@ const getHeatmapColor = (value) => {
return 'rgba(239, 68, 68, 0.9)'; // red-500
};
// Get channel matrix color based on value (high/medium/low)
const getChannelMatrixColor = (value) => {
if (!value) return 'rgba(156, 163, 175, 0.5)'; // gray
const normalizedValue = String(value).toLowerCase();
if (normalizedValue === 'high' || normalizedValue === 'высокий' || normalizedValue === 'высокая') return 'rgba(16, 185, 129, 0.9)'; // green
if (normalizedValue === 'medium' || normalizedValue === 'средний' || normalizedValue === 'средняя') return 'rgba(245, 158, 11, 0.9)'; // amber
if (normalizedValue === 'low' || normalizedValue === 'низкий' || normalizedValue === 'низкая') return 'rgba(239, 68, 68, 0.9)'; // red
return 'rgba(156, 163, 175, 0.5)'; // gray
};
// Helper: detect Chart.js "data" shape (labels + datasets)
const isChartJsData = (value) => {
return !!(value && typeof value === 'object' && !Array.isArray(value) && Array.isArray(value.labels) && Array.isArray(value.datasets));
@@ -2272,6 +2240,15 @@ const mapJsonBlockToSegment = (identifier, data, rawText) => {
}
};
}
case 'segmentschannelmatrix': {
const matrix = buildSegmentsChannelMatrix(data);
if (!matrix || !Array.isArray(matrix.data) || matrix.data.length === 0) return null;
return {
type: 'segmentsChannelMatrix',
title: 'Матрица каналов по сегментам',
matrix
};
}
default:
// Unknown block type: render raw markdown so nothing is lost
return {
@@ -3492,49 +3469,6 @@ onBeforeUnmount(() => {
position: relative;
}
/* Channel Matrix Table Styles */
.channel-matrix-table {
border: 1px solid var(--surface-border);
border-radius: 0.5rem;
overflow: hidden;
}
.channel-matrix-th {
padding: 0.75rem 1rem;
text-align: left;
font-weight: 600;
color: var(--text-color);
background-color: var(--surface-100);
border-bottom: 2px solid var(--surface-border);
white-space: nowrap;
}
.channel-matrix-td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--surface-border);
color: var(--text-color);
}
.channel-matrix-tr:last-child .channel-matrix-td {
border-bottom: none;
}
.channel-matrix-tr:hover {
background-color: var(--surface-50);
}
.channel-matrix-badge {
display: inline-block;
padding: 0.375rem 0.75rem;
border-radius: 0.375rem;
color: white;
font-weight: 600;
font-size: 0.875rem;
min-width: 70px;
text-align: center;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
/* Competitors Heatmap Table Styles */
.competitors-heatmap-table {
border: 1px solid var(--surface-border);