charts with period selection
This commit is contained in:
parent
e3a5d306d6
commit
8442b8e6b1
1 changed files with 140 additions and 2 deletions
|
|
@ -1,14 +1,152 @@
|
|||
<script setup>
|
||||
defineProps({
|
||||
import { ref, watch } from 'vue'
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
PointElement,
|
||||
CategoryScale,
|
||||
TimeScale,
|
||||
LinearScale
|
||||
} from 'chart.js'
|
||||
import { Line } from 'vue-chartjs'
|
||||
import 'chartjs-adapter-date-fns'
|
||||
|
||||
ChartJS.register(
|
||||
Title, Tooltip, Legend, LineElement, PointElement,
|
||||
CategoryScale, TimeScale, LinearScale
|
||||
)
|
||||
|
||||
const props = defineProps({
|
||||
chartsData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const originColors = {
|
||||
surugaya: '#FF4560',
|
||||
mandarake: '#775DD0'
|
||||
}
|
||||
|
||||
const chartData = ref({
|
||||
datasets: []
|
||||
})
|
||||
|
||||
const chartOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
animation: false,
|
||||
plugins: {
|
||||
legend: { display: true },
|
||||
tooltip: {
|
||||
mode: 'index',
|
||||
intersect: false,
|
||||
callbacks: {
|
||||
title: (context) => {
|
||||
const date = new Date(context[0].parsed.x)
|
||||
return date.toLocaleString('ru-RU', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
tooltipFormat: 'dd.MM.yyyy HH:mm',
|
||||
unit: 'day',
|
||||
displayFormats: { day: 'dd MMM' }
|
||||
},
|
||||
title: { display: true, text: 'Date' }
|
||||
},
|
||||
y: {
|
||||
title: { display: true, text: 'Price' },
|
||||
ticks: { precision: 0 }
|
||||
}
|
||||
},
|
||||
elements: {
|
||||
line: { borderWidth: 2, tension: 0, spanGaps: true },
|
||||
point: { radius: 4, hoverRadius: 6 }
|
||||
},
|
||||
interaction: {
|
||||
mode: 'nearest',
|
||||
axis: 'x',
|
||||
intersect: false
|
||||
}
|
||||
}
|
||||
|
||||
function transformToChartJSSeries(payload) {
|
||||
const datasets = []
|
||||
for (const origin of payload.origins) {
|
||||
if (!origin.Prices || origin.Prices.length === 0) continue
|
||||
|
||||
const data = origin.Prices
|
||||
.filter(p => p.value != null)
|
||||
.map(p => {
|
||||
let y = p.value
|
||||
if (typeof y === 'string') {
|
||||
y = parseFloat(y)
|
||||
}
|
||||
const x = typeof p.created_at === 'number'
|
||||
? p.created_at * 1000
|
||||
: new Date(p.created_at).getTime()
|
||||
|
||||
return {
|
||||
x,
|
||||
y: typeof y === 'number' && !isNaN(y) ? y : null
|
||||
}
|
||||
})
|
||||
.filter(p => p.y !== null)
|
||||
.sort((a, b) => a.x - b.x)
|
||||
|
||||
if (data.length === 0) continue
|
||||
|
||||
const color = originColors[origin.origin] || '#000000'
|
||||
|
||||
datasets.push({
|
||||
label: origin.origin,
|
||||
data,
|
||||
borderColor: color,
|
||||
backgroundColor: color + '20', // прозрачность
|
||||
fill: false,
|
||||
pointRadius: 4,
|
||||
pointHoverRadius: 6,
|
||||
type: 'line'
|
||||
})
|
||||
}
|
||||
return datasets
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.chartsData,
|
||||
(newData) => {
|
||||
if (newData?.origins) {
|
||||
const datasets = transformToChartJSSeries(newData)
|
||||
chartData.value = { datasets }
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-card :title="chartsData.name" class="charts-card" style="--n-padding-bottom: 5px">
|
||||
<div style="height: 400px; position: relative">
|
||||
<Line
|
||||
:data="chartData"
|
||||
:options="chartOptions"
|
||||
style="height: 100%; width: 100%"
|
||||
/>
|
||||
</div>
|
||||
<p class="micro-uuid text-center">{{ chartsData.merch_uuid }}</p>
|
||||
</n-card>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue