mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 11:37:20 +08:00
129 lines
2.6 KiB
Vue
129 lines
2.6 KiB
Vue
<script setup>
|
|
import {
|
|
ArcElement,
|
|
Chart as ChartJS,
|
|
Tooltip,
|
|
} from "chart.js";
|
|
import { computed } from "vue";
|
|
import { Doughnut } from "vue-chartjs";
|
|
|
|
ChartJS.register(ArcElement, Tooltip);
|
|
|
|
const props = defineProps({
|
|
rate: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
});
|
|
|
|
const percentage = computed(() => {
|
|
const rate = Number(props.rate);
|
|
if (!Number.isFinite(rate)) {
|
|
return 0;
|
|
}
|
|
return Math.max(0, Math.min(100, rate * 100));
|
|
});
|
|
|
|
const label = computed(() => {
|
|
const rate = Number(props.rate);
|
|
if (!Number.isFinite(rate)) {
|
|
return "--";
|
|
}
|
|
return `${percentage.value.toFixed(2)}%`;
|
|
});
|
|
|
|
function getSegmentBorderRadius(dataIndex) {
|
|
const radius = 5;
|
|
|
|
if (percentage.value <= 0) {
|
|
return dataIndex === 1
|
|
? {
|
|
outerStart: radius,
|
|
outerEnd: radius,
|
|
innerStart: radius,
|
|
innerEnd: radius,
|
|
}
|
|
: 0;
|
|
}
|
|
|
|
if (percentage.value >= 100) {
|
|
return dataIndex === 0
|
|
? {
|
|
outerStart: radius,
|
|
outerEnd: radius,
|
|
innerStart: radius,
|
|
innerEnd: radius,
|
|
}
|
|
: 0;
|
|
}
|
|
|
|
return dataIndex === 0
|
|
? {
|
|
outerStart: radius,
|
|
outerEnd: 0,
|
|
innerStart: radius,
|
|
innerEnd: 0,
|
|
}
|
|
: {
|
|
outerStart: 0,
|
|
outerEnd: radius,
|
|
innerStart: 0,
|
|
innerEnd: radius,
|
|
};
|
|
}
|
|
|
|
const chartData = computed(() => ({
|
|
labels: ["命中", "未命中"],
|
|
datasets: [
|
|
{
|
|
data: [percentage.value, Math.max(0, 100 - percentage.value)],
|
|
backgroundColor: ["#4ade80", "#373737"],
|
|
borderWidth: 0,
|
|
hoverBorderWidth: 0,
|
|
selfJoin: false,
|
|
borderRadius: ({ dataIndex }) => getSegmentBorderRadius(dataIndex),
|
|
},
|
|
],
|
|
}));
|
|
|
|
const chartOptions = {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
cutout: "82%",
|
|
rotation: -90,
|
|
circumference: 180,
|
|
animation: {
|
|
duration: 450,
|
|
},
|
|
events: [],
|
|
plugins: {
|
|
legend: {
|
|
display: false,
|
|
},
|
|
tooltip: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col items-center gap-3">
|
|
<div
|
|
class="relative h-[82px] w-[132px] shrink-0"
|
|
role="img"
|
|
:aria-label="`缓存命中率 ${label}`"
|
|
>
|
|
<Doughnut class="h-full w-full" :data="chartData" :options="chartOptions" />
|
|
<div class="pointer-events-none absolute inset-x-0 bottom-[10px] flex justify-center">
|
|
<div
|
|
class="text-[20px] leading-none text-white"
|
|
style="font-family: var(--font-num)"
|
|
>
|
|
{{ label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|