feat(dashboard): 控制台剖析图表支持指标国标维度分类切换、去除厚重大色块并启用动态自适应刻度

这个提交包含在:
wikiboss
2026-11-02 16:19:39 +08:00
父节点 e115815596
当前提交 b7ed9ae49b
共有 3 个文件被更改,包括 170 次插入 和 32 次删除

查看文件

@@ -77,27 +77,48 @@
<!-- 仓库农作检测参数数据折线图 -->
<el-row class="row main">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="main-1">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="main-position">
<div class="main-refresh">
<div class="refresh-btn">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="main-1" style="background: #ffffff; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,21,41,0.08); overflow: hidden;">
<style>
.custom-dashboard-bar {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
padding: 14px 20px;
border-bottom: 1px solid #f0f2f5;
}
.category-filter-bar {
padding: 10px 20px;
background: #fafbfc;
border-bottom: 1px solid #ebeef5;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 10px;
}
</style>
<!-- 顶部筛选栏 -->
<div class="custom-dashboard-bar">
<div class="main-refresh" style="display: flex; align-items: center;">
<div class="refresh-btn" @click="getParamsLineCharts" style="cursor: pointer; display: flex; align-items: center; gap: 4px; color: #409eff; font-size: 14px;">
<i class="el-icon-refresh-right"></i>
<span class="main-refresh-tip theme-color-1">刷新图表</span>
<span class="main-refresh-tip" style="font-weight: 500;">刷新图表</span>
</div>
</div>
<div class="main-position-right">
<div class="main-position-right" style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px;">
<div class="search-date">
<el-date-picker
size="small"
value-format="yyyy"
style="width: 220px;"
style="width: 140px;"
v-model="search.year"
type="year"
placeholder="检测年份">
</el-date-picker>
</div>
<div class="granary" style="margin-left: 10px;">
<el-select filterable size="small" style="width: 270px;" v-model="search.gid" placeholder="所属仓库" @change="granaryChange">
<div class="granary">
<el-select filterable size="small" style="width: 200px;" v-model="search.gid" placeholder="所属仓库" @change="granaryChange">
<el-option
v-for="item in granaryList"
:key="item.id"
@@ -106,21 +127,37 @@
</el-option>
</el-select>
</div>
<div class="type-list" style="margin-left: 10px;position: relative;top: -6px;">
<div class="screen-container-right display-flex" style="position: relative; top: 2px;">
<el-radio-group size="small" v-model="search.type" @change="typeChange">
<el-radio-button v-for="(item, index) of typeList" :label="index">{{item.name}}
</el-radio-button>
</el-radio-group>
</div>
<div class="type-list">
<el-radio-group size="small" v-model="search.type" @change="typeChange">
<el-radio-button v-for="(item, index) of typeList" :label="index">{{item.name}}
</el-radio-button>
</el-radio-group>
</div>
<div class="search-btn">
<el-button @click="getParamsLineCharts" size="small" type="primary" plain icon="el-icon-search">查询
</el-button>
</div>
</div>
</el-col>
<div class="chart-data">
</div>
<!-- 指标分类维度专属切换条 -->
<div class="category-filter-bar">
<div style="display: flex; align-items: center;">
<span style="font-size: 13px; color: #4b5563; margin-right: 12px; font-weight: 600;">
<i class="el-icon-s-operation" style="color: #409eff;"></i> 指标维度:
</span>
<el-radio-group size="mini" v-model="selectedCategory" @change="categoryChange">
<el-radio-button label="core">⭐ 核心品质</el-radio-button>
<el-radio-button label="impurity">🌾 物理与杂质</el-radio-button>
<el-radio-button label="storage">🧪 储存品质</el-radio-button>
<el-radio-button label="safety">🛡️ 卫生安全</el-radio-button>
<el-radio-button label="all">📊 全部指标</el-radio-button>
</el-radio-group>
</div>
<div style="font-size: 12px; color: #909399;">
<i class="el-icon-info"></i> 已按国标体系分类,Y轴动态自适应放大微量指标
</div>
</div>
<div class="chart-data" style="padding: 10px 10px 0 10px;">
<div style="height: 520px;" id="main-chart"></div>
</div>
</el-col>

查看文件

@@ -4,7 +4,7 @@ return array (
'name' => '中央储备粮遵义直属库有限公司',
'beian' => '',
'cdnurl' => '',
'version' => '20261102_v3',
'version' => '20261102_v6',
'timezone' => 'Asia/Shanghai',
'forbiddenip' => '',
'languages' =>

查看文件

@@ -1,5 +1,38 @@
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echarts-theme', 'template'], function ($, undefined, Backend, Datatable, Table, Echarts, undefined, Template) {
var CATEGORY_DEFS = {
core: {
name: '核心品质',
keywords: ['水分', '整精米率', '容重', '出糙率', '色泽', '气味', '纯粮率']
},
impurity: {
name: '物理与杂质',
keywords: ['杂质', '黄粒米', '谷外糙米', '互混', '不完善粒', '生霉粒', '加热损伤粒']
},
storage: {
name: '储存品质',
keywords: ['脂肪酸值', '面筋吸水量', '品尝评分', '酸价', '过氧化值', '发芽率', '还原糖']
},
safety: {
name: '卫生安全',
keywords: ['铅', '镉', '总汞', '汞', '无机砷', '砷', '黄曲霉毒素', '黄曲霉毒素B1', '马拉硫磷', '农药']
}
};
function filterSeriesByCategory(seriesData, categoryKey) {
if (!seriesData || !Array.isArray(seriesData)) return [];
if (!categoryKey || categoryKey === 'all') return seriesData;
var cat = CATEGORY_DEFS[categoryKey];
if (!cat) return seriesData;
return seriesData.filter(function (item) {
var name = item.name || '';
return cat.keywords.some(function (kw) {
return name.indexOf(kw) !== -1;
});
});
}
var Controller = {
index: function () {
var vue = new Vue({
@@ -8,6 +41,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
lineCharts: [],
granaryList: [],
typeList: [],
selectedCategory: 'core',
search: {
gid: '',
year: '',
@@ -18,6 +52,9 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
this.getInitData();
},
methods: {
categoryChange(cat) {
this.paramsLineCharts();
},
// 仓库切换智能联动其品种并刷新折线图
granaryChange(gid) {
let cur = this.granaryList.find(function (item) { return item.id === gid; });
@@ -96,19 +133,38 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
}
})
},
// 折线图
// 折线图 (平滑无遮挡 + 指标分类过滤 + 自适应刻度)
paramsLineCharts() {
let series = this.lineCharts || {};
let lineChart = Echarts.init(document.getElementById('main-chart'));
let legendData = [];
let hasData = false;
if (series.seriesData && series.seriesData.length) {
for (let i = 0; i < series.seriesData.length; i++) {
let item = series.seriesData[i];
let rawSeriesData = (series.seriesData && Array.isArray(series.seriesData)) ? series.seriesData : [];
let displaySeries = filterSeriesByCategory(rawSeriesData, this.selectedCategory);
if (!displaySeries.length && this.selectedCategory !== 'all' && rawSeriesData.length) {
displaySeries = [];
}
if (displaySeries && displaySeries.length) {
for (let i = 0; i < displaySeries.length; i++) {
let item = displaySeries[i];
item.type = 'line';
item.areaStyle = {
focus: 'series'
item.smooth = true;
item.symbol = 'circle';
item.symbolSize = 7;
delete item.areaStyle;
item.lineStyle = {
width: 2.5
};
item.label = {
show: true,
position: 'top',
fontSize: 11,
color: '#4b5563',
formatter: function (p) {
return (p.value !== 0 && p.value !== '0' && p.value !== null && p.value !== undefined) ? p.value : '';
}
};
legendData.push(item.name);
if (item.data && item.data.length && item.data.some(function (v) { return v !== null && v !== undefined && v !== ''; })) {
@@ -122,11 +178,19 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
let granaryName = curGranary ? curGranary.name : '所选仓库';
let typeName = this.typeList && this.typeList[this.search.type] ? this.typeList[this.search.type].name : this.search.type;
let yearText = this.search.year || '';
let currentCatName = (CATEGORY_DEFS[this.selectedCategory] ? CATEGORY_DEFS[this.selectedCategory].name : '指标');
let emptySubtext = '';
if (!rawSeriesData.length) {
emptySubtext = (yearText ? yearText + '年 ' : '') + granaryName + ' 暂无【' + typeName + '】检测报告,可切换年份或对应品种查看';
} else {
emptySubtext = (yearText ? yearText + '年 ' : '') + granaryName + '【' + typeName + '】暂无【' + currentCatName + '】项检测数据,可切换其他分类或全部指标查看';
}
let option = {
title: !hasData ? {
text: '暂无检测数据',
subtext: (yearText ? yearText + '年 ' : '') + granaryName + ' 暂无【' + typeName + '】检测报告,可切换年份或对应品种查看',
subtext: emptySubtext,
left: 'center',
top: 'middle',
textStyle: {
@@ -143,6 +207,13 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(255, 255, 255, 0.96)',
borderColor: '#e4e7ed',
borderWidth: 1,
textStyle: {
color: '#303133',
fontSize: 12
},
axisPointer: {
type: 'cross',
label: {
@@ -151,7 +222,12 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
}
},
legend: {
data: hasData ? legendData : []
data: hasData ? legendData : [],
top: 5,
textStyle: {
fontSize: 12,
color: '#606266'
}
},
toolbox: {
feature: {
@@ -159,24 +235,49 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
}
},
grid: {
left: '3%',
left: '4%',
right: '4%',
bottom: 0,
top: 50,
bottom: 20,
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: hasData ? (series.list || []) : []
data: hasData ? (series.list || []) : [],
axisLine: {
lineStyle: {
color: '#dcdfe6'
}
},
axisLabel: {
color: '#606266'
}
}
],
yAxis: [
{
type: 'value'
type: 'value',
scale: true,
axisLine: {
show: true,
lineStyle: {
color: '#dcdfe6'
}
},
axisLabel: {
color: '#606266'
},
splitLine: {
lineStyle: {
type: 'dashed',
color: '#f2f3f5'
}
}
}
],
series: hasData ? series.seriesData : []
series: hasData ? displaySeries : []
};
lineChart.setOption(option, true);