WIP: #258 Compare page

This commit is contained in:
Cindy Chang
2024-06-18 09:12:18 +08:00
parent 9b88de4c3f
commit 94dbe1dee6
2 changed files with 347 additions and 4 deletions

View File

@@ -182,7 +182,7 @@ export function followTimeLabel(second, max, fixedNumber = 0) {
result = (second / day).toFixed(fixedNumber) + 'd'; result = (second / day).toFixed(fixedNumber) + 'd';
break; break;
case 'h': case 'h':
if(((second % day) / hour) === 0) { if((second / hour) === 0) {
fixedNumber = 0; fixedNumber = 0;
} }
result = (second / hour).toFixed(fixedNumber) + 'h'; result = (second / hour).toFixed(fixedNumber) + 'h';

View File

@@ -437,7 +437,7 @@ export default {
getBarChart(chartData, content, caller) { getBarChart(chartData, content, caller) {
const maxX = chartData.x_axis.max; const maxX = chartData.x_axis.max;
const minX = chartData.x_axis.min; const minX = chartData.x_axis.min;
const getMoment = (time)=> this.$moment(time).format('YYYY/M/D hh:mm:ss'); const getMoment = (time)=> this.$moment(time).format('YYYY/MM/DD');
const getDateLabel = getDateLabelByMinMaxDate; const getDateLabel = getDateLabelByMinMaxDate;
let datasetsPrimary = chartData.data[0].data; let datasetsPrimary = chartData.data[0].data;
let xDataPrimary; let xDataPrimary;
@@ -910,6 +910,349 @@ export default {
return [primeVueSetData, primeVueSetOption]; return [primeVueSetData, primeVueSetOption];
}, },
/**
* 建立Case By Task水平長條圖
* 避免共用 PrimeVue 設定值,避免覆蓋設定
* @param { object } chartData chart data
* @param { object } content titels 標題的文字
* @param { boolean } isSingle 單個或雙數 activity
* @param { string } xUnit x 軸單位
*/
getCaseByTaskHorizontalBarChart(chartData, content, isSingle, xUnit = 'count') {
const maxX = chartData.x_axis.max;
const getSimpleTimeLabel = simpleTimeLabel;
const getFollowTimeLabel = followTimeLabel;
const labelPrimary = chartData.data[0].label;
const labelSecondary = chartData.data[1].label;
let primeVueSetData = {};
let primeVueSetOption = {};
// 大到小排序: Primary 為主
const datasetsPrimary = chartData.data[0].data;
const datasetsSecondary = chartData.data[1].data;
datasetsPrimary.sort((a, b) => b.y - a.y);
datasetsSecondary.sort((a, b) => {
// Find the index of a.x in data1
let indexA = datasetsPrimary.findIndex(item => item.x === a.x);
// Find the index of b.x in data1
let indexB = datasetsPrimary.findIndex(item => item.x === b.x);
// Compare the indexes
return indexA - indexB;
});
// 找出排序後,分別拉出 x, y Data
const xLabelData = datasetsPrimary.map(item => item.x);
const yDataPrimary = datasetsPrimary.map(item => item.y);
const yDataSecondary = datasetsSecondary.map(item => item.y);
primeVueSetData = {
labels: xLabelData,
datasets: [
{
label: labelPrimary,
data: yDataPrimary,
backgroundColor: this.colorPrimary,
},
{
label: labelSecondary,
data: yDataSecondary,
backgroundColor: this.colorSecondary,
},
]
};
primeVueSetOption = {
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 16,
left: 8,
right: 8,
}
},
plugins: {
legend: false, // 圖例
tooltip: {
// displayColors: false,
mode: 'index', // 可顯示全部的 data label
titleFont: {weight: 'normal'},
callbacks: {}
},
title: {
display: false,
},
},
scales: {
x: {
title: {
display: true,
color: '#334155',
font: {
size: 12,
lineHeight: 2
},
text: content.x,
},
ticks: {
display: true,
maxRotation: 0, // 不旋轉 lable 0~50
color: '#64748b',
callback: function(value, index, ticks) {
return value; // 計算數量,沒有時間單位才對
}
},
grid: {
color: '#64748b',
tickLength: 0, // 網格是否超過邊線
},
border: {
display:false,
},
},
y: {
beginAtZero: true, // scale 包含 0
type: 'category',
title: {
display: true,
color: '#334155',
font: {
size: 12,
lineHeight: 2
},
text: content.y,
},
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
display:false,
color: '#64748b',
},
border: {
display: false, // 隱藏左側多出來的線
},
},
},
};
switch (xUnit) {
case 'count':
default:
primeVueSetOption.scales.x.ticks.precision = 0; // x 軸顯示小數點後 0 位
primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
let value = context.parsed.y;
value = context.parsed.x === null ? "n/a" : context.parsed.x;
switch (context.datasetIndex) {
case 0: // Primary
return `${labelPrimary}: ${value}`;
case 1: // Secondary
return `${labelSecondary}: ${value}`;
}
};
break;
}
if(isSingle) { // 設定一個活動的 y label、提示框文字
primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
return `${content.y}: ${context[0].label}`;
};
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
let label = xLabelData[index];
if(label) {
return label.length > 21 ? `${label.substring(0, 18)}...` : label
};
}
}else { // 設定「活動」到「活動」的 y label、提示框文字
primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
return `${content.y}: ${context[0].label.replace(',', ' - ')}`
};
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
let label = xLabelData[index];
let labelStart = label[0];
let labelEnd = label[1];
labelStart = labelStart.length > 10 ? `${labelStart.substring(0,7)}...` : labelStart;
labelEnd = labelEnd.length > 10 ? `${labelEnd.substring(0,7)}...` : labelEnd;
return labelStart + " - " + labelEnd
};
}
return [primeVueSetData, primeVueSetOption]
},
/**
* 建立 Average Processing Time水平長條圖
* 避免共用 PrimeVue 設定值,避免覆蓋設定
* @param { object } chartData chart data
* @param { object } content titels 標題的文字
* @param { boolean } isSingle 單個或雙數 activity
* @param { string } xUnit x 軸單位 'date' | 'count',可傳入以上任一。
*/
getAvgProcessTimeHorizontalBarChart(chartData, content, isSingle, xUnit="date") {
const maxY = chartData.y_axis.max;
const getSimpleTimeLabel = simpleTimeLabel;
const getFollowTimeLabel = followTimeLabel;
const labelPrimary = chartData.data[0].label;
const labelSecondary = chartData.data[1].label;
let primeVueSetData = {};
let primeVueSetOption = {};
// 大到小排序: Primary 為主
const datasetsPrimary = chartData.data[0].data;
const datasetsSecondary = chartData.data[1].data;
datasetsPrimary.sort((a, b) => b.y - a.y);
datasetsSecondary.sort((a, b) => {
// Find the index of a.x in data1
let indexA = datasetsPrimary.findIndex(item => item.x === a.x);
// Find the index of b.x in data1
let indexB = datasetsPrimary.findIndex(item => item.x === b.x);
// Compare the indexes
return indexA - indexB;
});
// 找出排序後,分別拉出 x, y Data
const xLabelData = datasetsPrimary.map(item => item.x);
const yDataPrimary = datasetsPrimary.map(item => item.y);
const yDataSecondary = datasetsSecondary.map(item => item.y);
primeVueSetData = {
labels: xLabelData,
datasets: [
{
label: labelPrimary,
data: yDataPrimary,
backgroundColor: this.colorPrimary,
},
{
label: labelSecondary,
data: yDataSecondary,
backgroundColor: this.colorSecondary,
},
]
};
primeVueSetOption = {
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 16,
left: 8,
right: 8,
}
},
plugins: {
legend: false, // 圖例
tooltip: {
// displayColors: false,
mode: 'index', // 可顯示全部的 data label
titleFont: {weight: 'normal'},
callbacks: {}
},
title: {
display: false,
},
},
scales: {
x: {
title: {
display: true,
color: '#334155',
font: {
size: 12,
lineHeight: 2
},
text: content.x,
},
ticks: {
display: true,
maxRotation: 0, // 不旋轉 lable 0~50
color: '#64748b',
},
grid: {
color: '#64748b',
tickLength: 0, // 網格是否超過邊線
},
border: {
display:false,
},
},
y: {
beginAtZero: true, // scale 包含 0
type: 'category',
title: {
display: true,
color: '#334155',
font: {
size: 12,
lineHeight: 2
},
text: content.y
},
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
display:false,
color: '#64748b',
},
border: {
display: false, // 隱藏左側多出來的線
},
},
},
};
switch (xUnit) {
case 'date':
default:
primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
let value = context.parsed.y;
value = context.parsed.x === null ? "n/a" : getSimpleTimeLabel(context.parsed.x, 2);
switch (context.datasetIndex) {
case 0: // Primary
return `${labelPrimary}: ${value}`;
case 1: // Secondary
return `${labelSecondary}: ${value}`;
}
};
primeVueSetOption.scales.x.ticks.callback = function (value, index, ticks) {
return getFollowTimeLabel(value, maxY, 1)
};
break;
}
if(isSingle) { // 設定一個活動的 y label、提示框文字
primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
return `${content.y}: ${context[0].label}`;
};
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
let label = xLabelData[index];
if(label) {
return label.length > 21 ? `${label.substring(0, 18)}...` : label
};
}
}else { // 設定「活動」到「活動」的 y label、提示框文字
primeVueSetOption.plugins.tooltip.callbacks.title = function(context) {
return `${content.y}: ${context[0].label.replace(',', ' - ')}`
};
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
let label = xLabelData[index];
let labelStart = label[0];
let labelEnd = label[1];
labelStart = labelStart.length > 10 ? `${labelStart.substring(0,7)}...` : labelStart;
labelEnd = labelEnd.length > 10 ? `${labelEnd.substring(0,7)}...` : labelEnd;
return labelStart + " - " + labelEnd
};
}
return [primeVueSetData, primeVueSetOption]
},
}, },
async created() { async created() {
this.isLoading = true; // moubeted 才停止 loading this.isLoading = true; // moubeted 才停止 loading
@@ -944,7 +1287,7 @@ export default {
this.compareDashboardData.time.avg_cycle_efficiency, this.contentData.avgCycleEfficiency, "Cycle Eff"); this.compareDashboardData.time.avg_cycle_efficiency, this.contentData.avgCycleEfficiency, "Cycle Eff");
[this.avgProcessTimeData, this.avgProcessTimeOptions] = this.getLineChart( [this.avgProcessTimeData, this.avgProcessTimeOptions] = this.getLineChart(
this.compareDashboardData.time.avg_process_time, this.contentData.avgProcessTime, 'date'); this.compareDashboardData.time.avg_process_time, this.contentData.avgProcessTime, 'date');
[this.avgProcessTimeByTaskData, this.avgProcessTimeByTaskOptions] = this.getHorizontalBarChart( [this.avgProcessTimeByTaskData, this.avgProcessTimeByTaskOptions] = this.getAvgProcessTimeHorizontalBarChart(
this.compareDashboardData.time.avg_process_time_by_task, this.compareDashboardData.time.avg_process_time_by_task,
this.contentData.avgProcessTimeByTask, true, 'date'); this.contentData.avgProcessTimeByTask, true, 'date');
[this.avgWaitingTimeData, this.avgWaitingTimeOptions] = this.getLineChart( [this.avgWaitingTimeData, this.avgWaitingTimeOptions] = this.getLineChart(
@@ -958,7 +1301,7 @@ export default {
} }
[this.freqData, this.freqOptions] = this.getLineChart( [this.freqData, this.freqOptions] = this.getLineChart(
this.compareDashboardData.freq.cases, this.contentData.freq, 'count'); this.compareDashboardData.freq.cases, this.contentData.freq, 'count');
[this.casesByTaskData, this.casesByTaskOptions] = this.getHorizontalBarChart( [this.casesByTaskData, this.casesByTaskOptions] = this.getCaseByTaskHorizontalBarChart(
this.compareDashboardData.freq.cases_by_task, this.contentData.casesByTask, true, 'count'); this.compareDashboardData.freq.cases_by_task, this.contentData.casesByTask, true, 'count');
}, },
mounted() { mounted() {