update dashboard page
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
import { Line } from '@antv/g2plot'
|
||||
import type { DashboardTrendPoint } from '@/types/api'
|
||||
|
||||
const props = defineProps<{
|
||||
data: DashboardTrendPoint[]
|
||||
loading: boolean
|
||||
groupBy: 'day' | 'week' | 'month'
|
||||
dataType: string | undefined
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:groupBy': ['day' | 'week' | 'month']
|
||||
'update:dataType': [string | undefined]
|
||||
}>()
|
||||
|
||||
const chartRef = ref<HTMLDivElement>()
|
||||
let chart: Line | null = null
|
||||
|
||||
const groupByOptions = [
|
||||
{ label: '日', value: 'day' },
|
||||
{ label: '周', value: 'week' },
|
||||
{ label: '月', value: 'month' },
|
||||
]
|
||||
|
||||
const dataTypeOptions = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '订单', value: 'order' },
|
||||
{ label: '产品', value: 'product' },
|
||||
{ label: '退款', value: 'refund' },
|
||||
{ label: '库存', value: 'inventory' },
|
||||
]
|
||||
|
||||
const flatData = computed(() => {
|
||||
const result: { date: string; value: number; category: string }[] = []
|
||||
for (const point of props.data) {
|
||||
result.push({ date: point.date, value: point.success, category: '成功' })
|
||||
result.push({ date: point.date, value: point.failed, category: '失败' })
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
||||
function createChart() {
|
||||
if (!chartRef.value) return
|
||||
chart = new Line(chartRef.value, {
|
||||
data: flatData.value,
|
||||
xField: 'date',
|
||||
yField: 'value',
|
||||
seriesField: 'category',
|
||||
color: ['#52c41a', '#ff4d4f'],
|
||||
smooth: true,
|
||||
legend: { position: 'top' },
|
||||
xAxis: { label: { autoRotate: true } },
|
||||
yAxis: { label: { formatter: (v: string) => v } },
|
||||
animation: false,
|
||||
})
|
||||
chart.render()
|
||||
}
|
||||
|
||||
function handleGroupByChange(e: unknown) {
|
||||
const val = (e as { target: { value?: string } }).target.value as 'day' | 'week' | 'month'
|
||||
emit('update:groupBy', val)
|
||||
}
|
||||
|
||||
function handleDataTypeChange(val: unknown) {
|
||||
emit('update:dataType', (val as string) || undefined)
|
||||
}
|
||||
|
||||
watch(flatData, () => {
|
||||
if (chart) {
|
||||
chart.changeData(flatData.value)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (props.data.length > 0) {
|
||||
createChart()
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newVal) => {
|
||||
if (newVal.length > 0 && !chart) {
|
||||
nextTick(() => createChart())
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (chart) {
|
||||
chart.destroy()
|
||||
chart = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-card title="数据趋势" class="mb-4">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-radio-group
|
||||
:value="groupBy"
|
||||
size="small"
|
||||
@change="handleGroupByChange"
|
||||
>
|
||||
<a-radio-button v-for="opt in groupByOptions" :key="opt.value" :value="opt.value">
|
||||
{{ opt.label }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-select
|
||||
:value="dataType ?? ''"
|
||||
:options="dataTypeOptions"
|
||||
style="width: 100px"
|
||||
size="small"
|
||||
@change="handleDataTypeChange"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-spin :spinning="loading">
|
||||
<div ref="chartRef" style="height: 350px" />
|
||||
<a-empty v-if="!loading && data.length === 0" description="暂无趋势数据" />
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</template>
|
||||
Reference in New Issue
Block a user