各项目进度情况展示
配置项如下
// 指定图表的配置项和数据
/**
* 基本思路就是把分类名映射成数值
*/
// 阶段分类与数值的映射
var phaseParent = [{
name: '方案制定阶段',
color: '#3b1a40',
order: 1,
children: [{
name: '收到业务需求',
order: 1
},
{
name: '需求评审',
order: 2
},
{
name: '提交建设方案',
order: 3
},
]
},
{
name: '立项阶段',
color: '#463793',
order: 2,
children: [{
name: '建设方案评审',
order: 4
},
{
name: '立项决策会',
order: 5
},
{
name: '可研评审',
order: 6
},
{
name: '可研批复',
order: 7
},
]
},
{
name: '采购准备阶段',
color: '#3c6df0',
order: 3,
children: [{
name: '采购材料编制提交',
order: 8
},
{
name: '采购材料评审',
order: 9
},
{
name: '采购预申请',
order: 10
},
{
name: '采购正式申请',
order: 11
},
]
},
{
name: '采购发生阶段',
color: '#ffab18',
order: 4,
children: [{
name: '采购方案决策',
order: 12
},
{
name: '采购结果公布',
order: 13
},
{
name: '合同签订',
order: 14
},
]
},
{
name: '设计阶段',
color: '#9dff6b',
order: 5,
children: [{
name: '设计批复',
order: 15
}, ]
},
{
name: '工程实施阶段',
color: '#7ed2c6',
order: 6,
children: [{
name: '项目开工',
order: 16
},
{
name: '设备到货',
order: 17
},
{
name: '设备安装',
order: 18
},
{
name: '需求分析',
order: 19
},
{
name: '系统设计',
order: 20
},
{
name: '开发阶段',
order: 21
},
{
name: '集成测试',
order: 22
},
{
name: '验收测试',
order: 23
},
{
name: '割接上线',
order: 24
},
{
name: '试运行',
order: 25
},
{
name: '竣工验收',
order: 26
},
]
}
];
var allSubPhase = [];
for (var i = 0; i < phaseParent.length; i++) {
var children = phaseParent[i].children;
for (var j = 0; j < children.length; j++) {
var child = children[j];
child.color = phaseParent[i].color;
allSubPhase.push(child)
}
}
var all_phase_cnt = allSubPhase.length;
var projectPhase = [
['收到业务需求', 'ERP集中化项目'],
['需求评审', '430项目'],
['建设方案评审', '可视化大屏项目'],
['立项决策会', '资产管理系统扩容改造项目'],
['项目开工', '大数据架构升级项目'],
['收到业务需求', 'ERP集中化项目1'],
['需求评审', '430项目2'],
['建设方案评审', '可视化大屏项目3'],
['立项决策会', '资产管理系统扩容改造项目4'],
['合同签订', '大数据架构升级项目5'],
['收到业务需求', 'ERP集中化项目7'],
['需求评审', '430项目7'],
];
var yData = projectPhase.map(data => data[1]);
/**
* 把数据的分类阶段转换成数值
* @param arr
* @returns {[]}
*/
function getBarData(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
var cur = arr[i];
for (var j = 0; j < allSubPhase.length; j++) {
if (cur[0] === allSubPhase[j].name) {
res.push([allSubPhase[j].order, cur[1]])
break;
}
}
}
return res;
}
function toPercent(decimal) {
return (decimal * 100).toFixed(4) + '%'
}
var option = {
title: {
text: ''
},
tooltip: {
show: true,
formatter: function(params) {
if (params.seriesIndex > 0) {
return null;
}
const phaseOrder = params.data[0];
return params.data[1] + ":"
// 获取阶段名称
+
allSubPhase.find(phase => phaseOrder === phase.order).name;
}
},
grid: [{
top: 100,
bottom: 101,
},
// 展示一级阶段
{
height: 50,
top: 0
},
// 展示二级阶段
{
height: 50,
top: 50
},
// 第四个网格没有实际数据,仅用于辅助展示网格线
{
top: 100,
bottom: 101
},
],
xAxis: [{
type: 'value',
position: 'top',
min: 0,
max: 26,
gridIndex: 0,
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false,
},
axisTick: {
show: false
}
},
{
type: 'category',
position: 'top',
gridIndex: 1,
axisLine: {
show: false
},
zlevel: 1
},
{
type: 'category',
position: 'top',
gridIndex: 2,
axisLine: {
show: false
},
zlevel: 2
},
// 第四个网格没有实际数据,仅用于辅助展示网格线
{
type: 'category',
position: 'bottom',
gridIndex: 3,
data: allSubPhase.map(phase => phase.name),
zlevel: 0,
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: true,
interval: 0,
lineStyle: {
type: 'dotted'
}
},
axisTick: {
show: false
}
}
],
yAxis: [{
type: 'category',
gridIndex: 0,
data: yData,
axisLine: {
show: false,
},
axisTick: {
show: false
}
},
{
type: 'value',
gridIndex: 1,
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
}
},
{
type: 'value',
gridIndex: 2,
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
}
},
// 第四个网格没有实际数据,仅用于辅助展示网格线
{
type: 'value',
gridIndex: 3,
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
}
},
],
series: [{
type: 'bar',
data: getBarData(projectPhase),
xAxisIndex: 0,
yAxisIndex: 0,
itemStyle: {
normal: {
color: (params) => {
let colors = ['#4150d8', '#28bf7e', '#ed7c2f', '#f2a93b', '#f9cf36', '#4a5bdc', '#4cd698', '#f4914e', '#fcb75b', '#ffe180', '#b6c2ff', '#96edc1']
return colors[params.dataIndex]
}
}
},
}],
};
// 增加一级阶段
for (var i = 0; i < phaseParent.length; i++) {
option.series.push({
data: [{
name: phaseParent[i].name,
value: 1
}],
label: {
show: true,
position: 'inside',
formatter: '{b}',
textStyle: {
color: '#fff',
fontWeight: 'bold',
}
},
type: 'bar',
barGap: 0,
barWidth: toPercent(phaseParent[i].children.length / all_phase_cnt),
itemStyle: {
color: phaseParent[i].color,
borderColor: '#efefef',
borderWidth: 1,
},
xAxisIndex: 1,
yAxisIndex: 1
})
}
// 增加二级阶段
for (var i = 0; i < allSubPhase.length; i++) {
var curPhase = allSubPhase[i];
// 把二级阶段名分两行展示
var phaseName = curPhase.name;
var halfLen = phaseName.length / 2;
var showName = phaseName.substr(0, halfLen) + '\n' + phaseName.substr(halfLen);
option.series.push({
data: [{
name: showName,
value: 1
}],
label: {
show: true,
position: 'inside',
formatter: '{b}',
textStyle: {
fontSize: 10,
lineHeight: 12,
color: '#fff',
}
},
type: 'bar',
barGap: 0,
barWidth: toPercent(1 / all_phase_cnt),
itemStyle: {
color: curPhase.color,
borderColor: '#efefef',
borderWidth: 1,
},
xAxisIndex: 2,
yAxisIndex: 2
})
}