From 265680ae4501677724db7ee30d225278aadeb32c Mon Sep 17 00:00:00 2001 From: Cindy Chang Date: Mon, 3 Jun 2024 16:48:22 +0800 Subject: [PATCH] WIP: refactoring Compare page --- src/module/timeLabel.js | 26 +- src/views/Compare/Dashboard/index.vue | 373 ++++++++++++++------------ 2 files changed, 221 insertions(+), 178 deletions(-) diff --git a/src/module/timeLabel.js b/src/module/timeLabel.js index f698f5b..ff25589 100644 --- a/src/module/timeLabel.js +++ b/src/module/timeLabel.js @@ -76,19 +76,27 @@ export function followTimeLabel(second, max, fixedNumber = 0) { maxUnit = dd > 0 ? 'd' : hh > 0 ? 'h' : mm > 0 ? 'm' : 's'; switch (maxUnit) { case 'd': - if((second / day) === 0) fixedNumber = 0; + if((second / day) === 0) { + fixedNumber = 0; + } result = (second / day).toFixed(fixedNumber) + 'd'; break; case 'h': - if(((second % day) / hour) === 0) fixedNumber = 0; + if(((second % day) / hour) === 0) { + fixedNumber = 0; + } result = ((second % day) / hour).toFixed(fixedNumber) + 'h'; break; case 'm': - if(((second % hour) / minutes) === 0) fixedNumber = 0; + if(((second % hour) / minutes) === 0) { + fixedNumber = 0; + } result = ((second % hour) / minutes).toFixed(fixedNumber) + 'm'; break; case 's': - if(second === 0) fixedNumber = 0; + if(second === 0) { + fixedNumber = 0; + } result = second.toFixed(fixedNumber) + 's'; break; } @@ -113,18 +121,18 @@ export function dateLabel(date, maxDate, minDate) { let timeDiff = maxDate - minDate; // 計算相差的月份 - var diffMonths = (maxDate.getFullYear() - minDate.getFullYear()) * 12; + let diffMonths = (maxDate.getFullYear() - minDate.getFullYear()) * 12; diffMonths -= minDate.getMonth(); diffMonths += maxDate.getMonth(); // 計算相差的日期,要取整數才能接續下方的邏輯判斷 `diffDays > 0` // 毫秒 * 秒 * 分鐘 * 小時 = 一天的時間量 - var diffDays = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); + const diffDays = Math.floor(timeDiff / (1000 * 60 * 60 * 24)); // 計算相差的小時、分鐘、秒 - var diffHours = Math.floor(timeDiff / (1000 * 60 * 60)); - var diffMinutes = Math.floor(timeDiff / (1000 * 60)); - var diffSeconds = Math.floor(timeDiff / 1000); + const diffHours = Math.floor(timeDiff / (1000 * 60 * 60)); + const diffMinutes = Math.floor(timeDiff / (1000 * 60)); + const diffSeconds = Math.floor(timeDiff / 1000); // 顯示結果 if (diffMonths > 0) return moment(date).format('YYYY/MM/DD'); diff --git a/src/views/Compare/Dashboard/index.vue b/src/views/Compare/Dashboard/index.vue index cd2ab19..dff2b63 100644 --- a/src/views/Compare/Dashboard/index.vue +++ b/src/views/Compare/Dashboard/index.vue @@ -155,6 +155,163 @@ import { setLineChartData } from '@/module/setChartData.js'; import { simpleTimeLabel, followTimeLabel, dateLabel } from '@/module/timeLabel.js'; import i18next from '@/i18n/i18n'; +const knownLayoutChartOption = { + padding: { + top: 16, + left: 8, + right: 8, + } +}; +const knownScaleLineChartOptions = { + x: { + type: 'time', + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + } + }, + time: { + displayFormats: { + second: 'h:mm:ss', // ex: 1:11:11 + minute: 'M/d h:mm', // ex: 1/1 1:11 + hour: 'M/d h:mm', // ex: 1/1 1:11 + day: 'M/d h', // ex: 1/1 1 + month: 'y/M/d', // ex: 1911/1/1 + }, + }, + ticks: { + display: true, + maxRotation: 0, // 不旋轉 lable 0~50 + color: '#64748b', + source: 'labels', // 依比例彈性顯示 label 數量 + }, + border: { + color: '#64748b', + }, + grid: { + tickLength: 0, // 網格是否超過邊線 + } + }, + y: { + beginAtZero: true, // scale 包含 0 + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + }, + }, + ticks:{ + color: '#64748b', + padding: 8, + }, + grid: { + color: '#64748b', + }, + border: { + display: false, // 隱藏左側多出來的線 + }, + }, +}; +const knownScaleHorizontalChartOptions = { + x: { + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + } + }, + 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 + }, + }, + ticks:{ + color: '#64748b', + padding: 8, + }, + grid: { + display:false, + color: '#64748b', + }, + border: { + display: false, // 隱藏左側多出來的線 + }, + }, +}; +const knownScaleBarChartOptions = { + x: { + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + } + }, + 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 + }, + }, + ticks:{ + color: '#64748b', + padding: 8, + }, + grid: { + display:false, + color: '#64748b', + }, + border: { + display: false, // 隱藏左側多出來的線 + }, + }, + }; + export default { setup() { const loadingStore = LoadingStore(); @@ -171,12 +328,12 @@ export default { return { i18next: i18next, timeUsageData: [ - {tagId: '#cycleTime', label: 'Cycle Efficiency'}, - {tagId: '#processingTime', label: 'Processing Time'}, - {tagId: '#waitingTime', label: 'Waiting Time'}, + {tagId: '#cycleTime', label: i18next.t("Compare.cycleEfficiency")}, + {tagId: '#processingTime', label: i18next.t("Compare.ProcessingTime")}, + {tagId: '#waitingTime', label: i18next.t("Compare.WaitingTime")}, ], frequencyData: [ - {tagId: '#cases', label: 'Number of Cases'}, + {tagId: '#cases', label: i18next.t("Compare.NumberOfCases")}, // {tagId: '#trace', label: 'Number of Trace'}, // {tagId: '#resource', label: 'Resource'}, ], @@ -277,6 +434,7 @@ export default { * @param { object } chartData chart data * @param { object } content titels 標題文字 * @param { string } yUnit y 軸單位 'date' | 'count',可傳入以上任一。 + * @returns { [setData, setOption] } 這兩者為符合 PriveVue 圖表格式的數據資料 */ getLineChart(chartData, content, yUnit) { let datasetsPrimary; @@ -356,63 +514,7 @@ export default { display: false, }, }, - scales: { - x: { - type: 'time', - title: { - display: true, - text: content.x, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - } - }, - time: { - displayFormats: { - second: 'h:mm:ss', // ex: 1:11:11 - minute: 'M/d h:mm', // ex: 1/1 1:11 - hour: 'M/d h:mm', // ex: 1/1 1:11 - day: 'M/d h', // ex: 1/1 1 - month: 'y/M/d', // ex: 1911/1/1 - }, - }, - ticks: { - display: true, - maxRotation: 0, // 不旋轉 lable 0~50 - color: '#64748b', - source: 'labels', // 依比例彈性顯示 label 數量 - }, - border: { - color: '#64748b', - }, - grid: { - tickLength: 0, // 網格是否超過邊線 - } - }, - y: { - beginAtZero: true, // scale 包含 0 - title: { - display: true, - text: content.y, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - }, - }, - ticks:{ - color: '#64748b', - padding: 8, - }, - grid: { - color: '#64748b', - }, - border: { - display: false, // 隱藏左側多出來的線 - }, - }, - }, + scales: this.customizeScaleChartOptionTitleByContent(knownScaleLineChartOptions, content), }; switch (yUnit) { case 'date': @@ -452,7 +554,7 @@ export default { /** * 建立長條圖 * @param { object } chartData chart data - * @param { object } content titels 文字標題 + * @param { object } content titles 文字標題 */ getBarChart(chartData, content) { const maxX = chartData.x_axis.max; @@ -506,13 +608,7 @@ export default { setOption = { responsive: true, maintainAspectRatio: false, - layout: { - padding: { - top: 16, - left: 8, - right: 8, - } - }, + layout: knownLayoutChartOption, interaction: { intersect: false, mode: 'index', // 可顯示全部的 data label @@ -545,55 +641,7 @@ export default { display: false, }, }, - scales: { - x: { - title: { - display: true, - text: content.x, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - } - }, - ticks: { - display: true, - color: '#64748b', - callback: function(v, i, t) { - let label = xDataPrimary[i] - return getDateLabel(label, maxX, minX) - }, - }, - border: { - color: '#64748b', - }, - grid: { - tickLength: 0, // 網格是否超過邊線 - } - }, - y: { - beginAtZero: true, // scale 包含 0 - title: { - display: true, - text: content.y, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - }, - }, - ticks:{ - color: '#64748b', - padding: 8, - }, - grid: { - color: '#64748b', - }, - border: { - display: false, // 隱藏左側多出來的線 - }, - }, - }, + scales: this.customizeScaleChartOptionTitleByContent(knownScaleBarChartOptions, content), }; return [setData, setOption] @@ -671,55 +719,7 @@ export default { display: false, }, }, - scales: { - x: { - title: { - display: true, - text: content.x, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - } - }, - 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, - text: content.y, - color: '#334155', - font: { - size: 12, - lineHeight: 2 - }, - }, - ticks:{ - color: '#64748b', - padding: 8, - }, - grid: { - display:false, - color: '#64748b', - }, - border: { - display: false, // 隱藏左側多出來的線 - }, - }, - }, + scales: this.customizeScaleChartOptionTitleByContent(knownScaleHorizontalChartOptions, null), }; switch (xUnit) { case 'date': @@ -759,8 +759,11 @@ export default { }; setOption.scales.y.ticks.callback = function (value, index, ticks) { let label = xData[index]; - return label.length > 21 ? `${label.substring(0, 18)}...` : label - }; + if(label) { + return label.length > 21 ? `${label.substring(0, 18)}...` : label + }; + } + }else { // 設定「活動」到「活動」的 y label、提示框文字 setOption.plugins.tooltip.callbacks.title = function(context) { return `${content.y}: ${context[0].label.replace(',', ' - ')}` @@ -778,6 +781,38 @@ export default { return [setData, setOption] }, + /** + * This function alters the title property of known scales object of Chart option + * This is based on the fact that we know the order must be x -> title -> text. + * @param {object} whichScaleObj PrimeVue scale option object to reference to + * @param content whose property includes x and y and stand for titles + * + * @returns { object } an object modified with two titles + */ + customizeScaleChartOptionTitleByContent(whichScaleObj, content){ + if (!content) { + // Early return + return whichScaleObj; + } + + return { + ...whichScaleObj, + x: { + ...whichScaleObj.x, + title: { + ...whichScaleObj.x.title, + text: content.x + } + }, + y: { + ...whichScaleObj.y, + title: { + ...whichScaleObj.y.title, + text: content.y + } + } + }; + } }, async created() { this.isLoading = true; // moubeted 才停止 loading