254 lines
9.5 KiB
Plaintext
254 lines
9.5 KiB
Plaintext
@page "/report/sub-ability-detail"
|
|
@model MiAssessment.Api.Pages.Report.SubAbilityDetailModel
|
|
@{
|
|
ViewData["Title"] = "细分能力精准分析";
|
|
ViewData["PageTitle"] = null;
|
|
ViewData["PageNumber"] = null;
|
|
}
|
|
|
|
@if (!Model.IsSuccess)
|
|
{
|
|
<div class="report-error" data-render-error="true">
|
|
<p>@Model.ErrorMessage</p>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="sad-page">
|
|
<!-- 板块标题 -->
|
|
<div class="sad-section-title">3.@(Model.SectionIndex)、个人40项细分能力精准分析</div>
|
|
|
|
<!-- 上半部分:雷达图 + 柱状图 -->
|
|
<div class="sad-charts">
|
|
<!-- 左侧:雷达图 -->
|
|
<div class="sad-chart-panel">
|
|
<div class="sad-chart-title" style="color: @Model.ChartColor">@(Model.ParentName)能力分析</div>
|
|
<canvas id="radarChart" width="480" height="380"></canvas>
|
|
</div>
|
|
|
|
<!-- 右侧:横向柱状图 -->
|
|
<div class="sad-chart-panel">
|
|
<div class="sad-chart-title" style="color: @Model.ChartColor">@(Model.ParentName)能力分析排序</div>
|
|
<canvas id="barChart" width="540" height="380"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 下半部分:结论卡片 -->
|
|
<div class="sad-conclusions">
|
|
<!-- 最强能力解读 -->
|
|
<div class="sad-conclusion-card sad-card-strong">
|
|
<div class="sad-badge sad-badge-strong">最强能力解读</div>
|
|
<div class="sad-ability-name">@Model.StrongestName</div>
|
|
<div class="sad-conclusion-content">
|
|
@if (Model.StrongestConclusion != null)
|
|
{
|
|
@Html.Raw(Model.StrongestConclusion.Content?.Replace("\n", "<br/>") ?? "暂无结论")
|
|
}
|
|
else
|
|
{
|
|
<span class="no-content">暂无结论数据</span>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 较弱能力解读 -->
|
|
<div class="sad-conclusion-card sad-card-weak">
|
|
<div class="sad-badge sad-badge-weak">较弱能力解读</div>
|
|
<div class="sad-ability-name">@Model.WeakestName</div>
|
|
<div class="sad-conclusion-content">
|
|
@if (Model.WeakestConclusion != null)
|
|
{
|
|
@Html.Raw(Model.WeakestConclusion.Content?.Replace("\n", "<br/>") ?? "暂无结论")
|
|
}
|
|
else
|
|
{
|
|
<span class="no-content">暂无结论数据</span>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@section Styles {
|
|
<link rel="stylesheet" href="/css/pages/sub-ability-detail.css" />
|
|
}
|
|
|
|
@section Scripts {
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
|
|
<script>
|
|
window.__deferRenderComplete = true;
|
|
|
|
// 雷达图数据(按 CategoryId 排序)
|
|
var radarLabels = [@Html.Raw(string.Join(",", Model.SubItems.Select(x => $"\"{x.CategoryName}\"")))];
|
|
var radarScores = [@Html.Raw(string.Join(",", Model.SubItems.Select(x => x.Score.ToString("F0"))))];
|
|
var maxScore = 20;
|
|
|
|
// 柱状图数据(按分数降序)
|
|
var barLabels = [@Html.Raw(string.Join(",", Model.SubItemsByScore.Select(x => $"\"{x.CategoryName}\"")))];
|
|
var barScores = [@Html.Raw(string.Join(",", Model.SubItemsByScore.Select(x => x.Score.ToString("F0"))))];
|
|
var avgScore = @Model.AverageScore.ToString("F1");
|
|
var barMax = Math.ceil(Math.max(...barScores) / 5) * 5 + 5;
|
|
|
|
// 配色
|
|
var chartColor = '@Model.ChartColor';
|
|
var chartColorAlpha = '@Model.ChartColorAlpha';
|
|
|
|
// ---- 雷达图 ----
|
|
var ctxRadar = document.getElementById('radarChart').getContext('2d');
|
|
new Chart(ctxRadar, {
|
|
type: 'radar',
|
|
data: {
|
|
labels: radarLabels,
|
|
datasets: [{
|
|
data: radarScores,
|
|
backgroundColor: chartColorAlpha.replace('0.6)', '0.12)'),
|
|
borderColor: chartColorAlpha.replace('0.6)', '0.8)'),
|
|
borderWidth: 2,
|
|
pointBackgroundColor: chartColorAlpha.replace('0.6)', '0.9)'),
|
|
pointBorderColor: '#fff',
|
|
pointRadius: 4,
|
|
pointBorderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: false,
|
|
plugins: { legend: { display: false } },
|
|
scales: {
|
|
r: {
|
|
beginAtZero: true,
|
|
max: maxScore,
|
|
ticks: {
|
|
stepSize: 5,
|
|
font: { size: 11 },
|
|
backdropColor: 'transparent',
|
|
color: '#999'
|
|
},
|
|
pointLabels: {
|
|
font: { size: 13, weight: '500' },
|
|
color: '#333',
|
|
padding: 10
|
|
},
|
|
grid: { color: 'rgba(0,0,0,0.06)' },
|
|
angleLines: { color: 'rgba(0,0,0,0.06)' }
|
|
}
|
|
}
|
|
},
|
|
plugins: [{
|
|
afterDatasetsDraw: function(chart) {
|
|
var meta = chart.getDatasetMeta(0);
|
|
var ctx2 = chart.ctx;
|
|
ctx2.font = 'bold 12px sans-serif';
|
|
ctx2.fillStyle = chartColor;
|
|
ctx2.textBaseline = 'middle';
|
|
meta.data.forEach(function(point, i) {
|
|
var val = radarScores[i];
|
|
var cx = chart.scales.r.xCenter;
|
|
var cy = chart.scales.r.yCenter;
|
|
var dx = point.x - cx;
|
|
var dy = point.y - cy;
|
|
var dist = Math.sqrt(dx * dx + dy * dy);
|
|
if (dist === 0) dist = 1;
|
|
var ox = (dx / dist) * 16;
|
|
var oy = (dy / dist) * 16;
|
|
ctx2.textAlign = 'center';
|
|
ctx2.fillText(val, point.x + ox, point.y + oy);
|
|
});
|
|
}
|
|
}]
|
|
});
|
|
|
|
// ---- 横向柱状图 + 平均值线 ----
|
|
var avgLinePlugin = {
|
|
id: 'avgLine',
|
|
afterDatasetsDraw: function(chart) {
|
|
var xScale = chart.scales.x;
|
|
var yScale = chart.scales.y;
|
|
var ctx = chart.ctx;
|
|
var xPos = xScale.getPixelForValue(avgScore);
|
|
|
|
// 画竖线
|
|
ctx.save();
|
|
ctx.strokeStyle = '#52A06A';
|
|
ctx.lineWidth = 2;
|
|
ctx.setLineDash([6, 4]);
|
|
ctx.beginPath();
|
|
ctx.moveTo(xPos, yScale.top);
|
|
ctx.lineTo(xPos, yScale.bottom);
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
|
|
// 画标签
|
|
ctx.save();
|
|
ctx.fillStyle = '#52A06A';
|
|
ctx.font = 'bold 12px "Microsoft YaHei", sans-serif';
|
|
ctx.textAlign = 'center';
|
|
ctx.fillText('平均值:' + avgScore, xPos, yScale.top - 8);
|
|
ctx.restore();
|
|
}
|
|
};
|
|
|
|
var barDataLabelPlugin = {
|
|
id: 'barDataLabels',
|
|
afterDatasetsDraw: function(chart) {
|
|
var ctx = chart.ctx;
|
|
var meta = chart.getDatasetMeta(0);
|
|
var dataset = chart.data.datasets[0];
|
|
ctx.font = 'bold 12px "Microsoft YaHei", sans-serif';
|
|
ctx.textBaseline = 'middle';
|
|
meta.data.forEach(function(bar, i) {
|
|
var val = dataset.data[i];
|
|
ctx.fillStyle = chartColor;
|
|
ctx.textAlign = 'left';
|
|
ctx.fillText(val, bar.x + 4, bar.y);
|
|
});
|
|
}
|
|
};
|
|
|
|
var ctxBar = document.getElementById('barChart').getContext('2d');
|
|
new Chart(ctxBar, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: barLabels,
|
|
datasets: [{
|
|
data: barScores,
|
|
backgroundColor: chartColorAlpha,
|
|
borderColor: chartColor,
|
|
borderWidth: 0,
|
|
borderRadius: 2,
|
|
barThickness: 32
|
|
}]
|
|
},
|
|
options: {
|
|
indexAxis: 'y',
|
|
responsive: false,
|
|
plugins: { legend: { display: false } },
|
|
scales: {
|
|
x: {
|
|
beginAtZero: true,
|
|
max: barMax,
|
|
ticks: {
|
|
font: { size: 11 },
|
|
color: '#999'
|
|
},
|
|
grid: { color: 'rgba(0,0,0,0.05)' }
|
|
},
|
|
y: {
|
|
ticks: {
|
|
font: { size: 13 },
|
|
color: '#666'
|
|
},
|
|
grid: { display: false }
|
|
}
|
|
},
|
|
layout: {
|
|
padding: { right: 30, top: 20 }
|
|
}
|
|
},
|
|
plugins: [avgLinePlugin, barDataLabelPlugin]
|
|
});
|
|
|
|
document.body.setAttribute('data-render-complete', 'true');
|
|
</script>
|
|
}
|