fix
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import * as echarts from 'echarts'
|
||||
import { getControlCaseChartData, type CsvChartResponse } from '@/api.ts'
|
||||
import { formatApiError } from '@/api_client.ts'
|
||||
|
||||
const route = useRoute()
|
||||
const containerRef = ref<HTMLDivElement | null>(null)
|
||||
const loading = ref(false)
|
||||
const error = ref('')
|
||||
const data = ref<CsvChartResponse | null>(null)
|
||||
let chart: echarts.ECharts | null = null
|
||||
|
||||
const id = computed(() => Number(route.params.id))
|
||||
|
||||
function buildOption(payload: CsvChartResponse): echarts.EChartsOption {
|
||||
const [xKey, ...seriesKeys] = payload.columns
|
||||
const rows = payload.rows
|
||||
|
||||
const xValues = rows.map((row) => row[0] ?? '')
|
||||
const series = seriesKeys.map((name, index) => ({
|
||||
name,
|
||||
type: 'line' as const,
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
data: rows.map((row) => row[index + 1] ?? null),
|
||||
}))
|
||||
|
||||
return {
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: { top: 0 },
|
||||
grid: { left: 48, right: 24, top: 48, bottom: 48, containLabel: true },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
name: xKey ?? 'x',
|
||||
data: xValues,
|
||||
},
|
||||
yAxis: { type: 'value' },
|
||||
series,
|
||||
}
|
||||
}
|
||||
|
||||
function renderChart() {
|
||||
if (!chart || !data.value) return
|
||||
chart.setOption(buildOption(data.value), true)
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
if (!Number.isFinite(id.value)) {
|
||||
error.value = 'Некорректный ID'
|
||||
data.value = null
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
try {
|
||||
data.value = await getControlCaseChartData(id.value)
|
||||
renderChart()
|
||||
} catch (err) {
|
||||
error.value = formatApiError(err, 'Не удалось загрузить данные графика.')
|
||||
data.value = null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
chart?.resize()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (containerRef.value) {
|
||||
chart = echarts.init(containerRef.value)
|
||||
window.addEventListener('resize', handleResize)
|
||||
}
|
||||
await loadData()
|
||||
})
|
||||
|
||||
watch(id, loadData)
|
||||
watch(data, renderChart)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
chart?.dispose()
|
||||
chart = null
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="d-flex flex-column gap-3">
|
||||
<div class="d-flex align-items-center justify-content-between gap-2 flex-wrap">
|
||||
<div>
|
||||
<RouterLink class="link-secondary text-decoration-none" :to="{ name: 'control-case-detail', params: { id } }">
|
||||
← Назад к кейсу
|
||||
</RouterLink>
|
||||
<h1 class="h3 mt-2 mb-0">График control case {{ id }}</h1>
|
||||
</div>
|
||||
<button class="btn btn-outline-secondary" type="button" @click="loadData" :disabled="loading">
|
||||
Обновить
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="alert alert-danger mb-0" role="alert">{{ error }}</div>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="position-relative" style="min-height: 560px;">
|
||||
<div ref="containerRef" style="height: 560px; width: 100%;"></div>
|
||||
<div
|
||||
v-if="loading"
|
||||
class="position-absolute top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center bg-white bg-opacity-75"
|
||||
>
|
||||
<div class="text-muted">Загрузка...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
Reference in New Issue
Block a user