Migrate all Vue components from Options API to <script setup>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 17:10:06 +08:00
parent a619be7881
commit 3b7b6ae859
61 changed files with 10835 additions and 11750 deletions

View File

@@ -2,7 +2,7 @@
<Chart type="line" :data="primeVueSetDataState" :options="primeVueSetOptionsState" class="h-96" />
</template>
<script>
<script setup>
import { ref, onMounted } from 'vue';
import {
setTimeStringFormatBaseOnTimeDifference,
@@ -65,220 +65,208 @@ y: {
},
};
// 試著把 chart 獨立成一個 vue component
// 企圖防止 PrimeVue 誤用其他圖表 option 值的 bug
export default {
props: {
chartData: {
type: Object,
const props = defineProps({
chartData: {
type: Object,
},
content: {
type: Object,
},
yUnit: {
type: String,
},
pageName: {
type: String,
},
});
const primeVueSetDataState = ref(null);
const primeVueSetOptionsState = ref(null);
const colorPrimary = ref('#0099FF');
const colorSecondary = ref('#FFAA44');
/**
* Compare page and Performance have this same function.
* @param whichScaleObj PrimeVue scale option object to reference to
* @param customizeOptions
* @param customizeOptions.content
* @param customizeOptions.ticksOfXAxis
*/
const getCustomizedScaleOption = (whichScaleObj, {customizeOptions: {
content,
ticksOfXAxis,
},
content: {
type: Object,
},
yUnit: {
type: String,
},
pageName: {
type: String,
},
},
setup(props) {
const primeVueSetDataState = ref(null);
const primeVueSetOptionsState = ref(null);
const colorPrimary = ref('#0099FF');
const colorSecondary = ref('#FFAA44');
/**
* Compare page and Performance have this same function.
* @param whichScaleObj PrimeVue scale option object to reference to
* @param customizeOptions
* @param customizeOptions.content
* @param customizeOptions.ticksOfXAxis
*/
const getCustomizedScaleOption = (whichScaleObj, {customizeOptions: {
content,
ticksOfXAxis,
},
}) => {
let resultScaleObj;
resultScaleObj = customizeScaleChartOptionTitleByContent(whichScaleObj, content);
resultScaleObj = customizeScaleChartOptionTicks(resultScaleObj, ticksOfXAxis);
return resultScaleObj;
};
/**
* Compare page and Performance have this same function.
* @param {object} scaleObjectToAlter this object follows the format of prive vue chart
* @param {Array<string>} ticksOfXAxis For example, ['05/06', '05,07', '05/08']
* or ['08:03:01', '08:11:18', '09:03:41', ], and so on.
*/
const customizeScaleChartOptionTicks = (scaleObjectToAlter, ticksOfXAxis) => {
return {
...scaleObjectToAlter,
x: {
...scaleObjectToAlter.x,
ticks: {
...scaleObjectToAlter.x.ticks,
callback: function(value, index) {
// 根據不同的級距客製化 x 軸的時間刻度
return ticksOfXAxis[index];
},
},
},
};
};
/** Compare page and Performance have this same function.
* 在一個基本的物件上加以客製化這個物件,客製化的參照來源是 content 的內容
* 之所以有辦法這樣撰寫,是因為我們知道物件的順序是先 x 再 title 再 text
* 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
*/
const 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
}
}
};
};
const getLineChartPrimeVueSetting = (chartData, content, pageName) => {
let datasetsArr;
let datasets;
let datasetsPrimary; // For Compare page case
let datasetsSecondary; // For Compare page case
const minX = chartData?.x_axis?.min;
const maxX = chartData?.x_axis?.max;
let xData;
let primeVueSetData = {};
let primeVueSetOption = {};
// 考慮 chartData.data 的dimension
// 當我們遇到了 Compare 頁面的案例
if(pageName === "Compare"){
datasetsPrimary = chartData.data[0].data;
datasetsSecondary = chartData.data[1].data;
datasetsArr = [
{
label: chartData.data[0].label,
data: datasetsPrimary,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: colorPrimary,
pointBackgroundColor: colorPrimary,
},
{
label: chartData.data[1].label,
data: datasetsSecondary,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: colorSecondary,
pointBackgroundColor: colorSecondary,
}
];
xData = chartData.data[0].data.map(item => new Date(item.x).getTime());
} else {
datasets = chartData.data;
datasetsArr = [
{
label: content.title,
data: datasets,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: '#0099FF',
}
];
xData = chartData.data.map(item => new Date(item.x).getTime());
}
// Customize X axis ticks due to different differences between min and max of data group
// Compare page and Performance page share the same logic
const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX);
const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xData, formatToSet);
const customizedScaleOption = getCustomizedScaleOption(
knownScaleLineChartOptions, {
customizeOptions: {
content, ticksOfXAxis,
}
});
primeVueSetData = {
labels: xData,
datasets: datasetsArr,
};
primeVueSetOption = {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 16,
left: 8,
right: 8,
}
},
plugins: {
legend: false, // 圖例
tooltip: {
displayColors: true,
titleFont: {weight: 'normal'},
callbacks: {
label: function(tooltipItem) {
// 取得數據
const label = tooltipItem.dataset.label || '';
// 建立一個小方塊顯示顏色
return `${label}: ${tooltipItem.parsed.y}`; // 使用 Unicode 方塊表示顏色
},
},
},
title: {
display: false,
},
},
scales: customizedScaleOption,
};
primeVueSetOption.scales.y.ticks.precision = 0; // y 軸顯示小數點後 0 位
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
return value; //這裡的Y軸刻度沒有後綴代表時間的英文字母
};
primeVueSetDataState.value = primeVueSetData;
primeVueSetOptionsState.value = primeVueSetOption;
};
onMounted(() => {
getLineChartPrimeVueSetting(props.chartData, props.content, props.pageName);
});
return {
...props,
primeVueSetDataState,
primeVueSetOptionsState,
};
}
}) => {
let resultScaleObj;
resultScaleObj = customizeScaleChartOptionTitleByContent(whichScaleObj, content);
resultScaleObj = customizeScaleChartOptionTicks(resultScaleObj, ticksOfXAxis);
return resultScaleObj;
};
</script>
/**
* Compare page and Performance have this same function.
* @param {object} scaleObjectToAlter this object follows the format of prive vue chart
* @param {Array<string>} ticksOfXAxis For example, ['05/06', '05,07', '05/08']
* or ['08:03:01', '08:11:18', '09:03:41', ], and so on.
*/
const customizeScaleChartOptionTicks = (scaleObjectToAlter, ticksOfXAxis) => {
return {
...scaleObjectToAlter,
x: {
...scaleObjectToAlter.x,
ticks: {
...scaleObjectToAlter.x.ticks,
callback: function(value, index) {
// 根據不同的級距客製化 x 軸的時間刻度
return ticksOfXAxis[index];
},
},
},
};
};
/** Compare page and Performance have this same function.
* 在一個基本的物件上加以客製化這個物件,客製化的參照來源是 content 的內容
* 之所以有辦法這樣撰寫,是因為我們知道物件的順序是先 x 再 title 再 text
* 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
*/
const 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
}
}
};
};
const getLineChartPrimeVueSetting = (chartData, content, pageName) => {
let datasetsArr;
let datasets;
let datasetsPrimary; // For Compare page case
let datasetsSecondary; // For Compare page case
const minX = chartData?.x_axis?.min;
const maxX = chartData?.x_axis?.max;
let xData;
let primeVueSetData = {};
let primeVueSetOption = {};
// 考慮 chartData.data 的dimension
// 當我們遇到了 Compare 頁面的案例
if(pageName === "Compare"){
datasetsPrimary = chartData.data[0].data;
datasetsSecondary = chartData.data[1].data;
datasetsArr = [
{
label: chartData.data[0].label,
data: datasetsPrimary,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: colorPrimary,
pointBackgroundColor: colorPrimary,
},
{
label: chartData.data[1].label,
data: datasetsSecondary,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: colorSecondary,
pointBackgroundColor: colorSecondary,
}
];
xData = chartData.data[0].data.map(item => new Date(item.x).getTime());
} else {
datasets = chartData.data;
datasetsArr = [
{
label: content.title,
data: datasets,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: '#0099FF',
}
];
xData = chartData.data.map(item => new Date(item.x).getTime());
}
// Customize X axis ticks due to different differences between min and max of data group
// Compare page and Performance page share the same logic
const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX);
const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xData, formatToSet);
const customizedScaleOption = getCustomizedScaleOption(
knownScaleLineChartOptions, {
customizeOptions: {
content, ticksOfXAxis,
}
});
primeVueSetData = {
labels: xData,
datasets: datasetsArr,
};
primeVueSetOption = {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 16,
left: 8,
right: 8,
}
},
plugins: {
legend: false, // 圖例
tooltip: {
displayColors: true,
titleFont: {weight: 'normal'},
callbacks: {
label: function(tooltipItem) {
// 取得數據
const label = tooltipItem.dataset.label || '';
// 建立一個小方塊顯示顏色
return `${label}: ${tooltipItem.parsed.y}`; // 使用 Unicode 方塊表示顏色
},
},
},
title: {
display: false,
},
},
scales: customizedScaleOption,
};
primeVueSetOption.scales.y.ticks.precision = 0; // y 軸顯示小數點後 0 位
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
return value; //這裡的Y軸刻度沒有後綴代表時間的英文字母
};
primeVueSetDataState.value = primeVueSetData;
primeVueSetOptionsState.value = primeVueSetOption;
};
onMounted(() => {
getLineChartPrimeVueSetting(props.chartData, props.content, props.pageName);
});
</script>

File diff suppressed because it is too large Load Diff