Files
gao-customer-h5/src/components/DateRangeChartCard.vue
T
2026-09-23 16:12:09 +08:00

121 lines
2.7 KiB
Vue

<template>
<section class="date-range-chart-card">
<div class="title">
<h2 v-text="title" />
<span v-if="caption" class="caption" v-text="caption" />
</div>
<div ref="chartElement" class="chart" :style="{ height }" />
<div v-if="loading" class="center-tips">
<t-loading size="1.5rem" text="加载中" />
</div>
<chart-range-slider
v-if="chartShowSlider"
:model-value="sliderValue"
:max="maxSliderValue"
:min-range="5"
:label="rangeText"
@change="handleSliderChange"
/>
</section>
</template>
<script setup lang="ts">
import type { EChartsOption } from "echarts";
import ChartRangeSlider from "@/components/ChartRangeSlider.vue";
import { useStoreChart, useStoreChartWindow } from "@/pages/store/component/useStoreChart";
type ChartOptionBuilder = (visibleDateTextList: string[], chartWidth: number) => EChartsOption;
const props = withDefaults(defineProps<{
caption?: string;
dateTextList?: string[];
height?: string;
hasData?: boolean;
loading?: boolean;
option: EChartsOption | ChartOptionBuilder;
title: string;
}>(), {
caption: "",
dateTextList: () => [],
height: "16rem",
loading: false
});
const dateTextList = computed(() => props.dateTextList);
const chartWidth = ref(window.innerWidth);
const {
rangeText,
showSlider: chartShowSlider,
sliderValue,
maxSliderValue,
visibleDateTextList,
handleSliderChange
} = useStoreChartWindow(dateTextList);
const option = computed<EChartsOption>(() => typeof props.option === "function"
? props.option(visibleDateTextList.value, chartWidth.value)
: props.option);
const { chartElement } = useStoreChart(option);
let resizeObserver: ResizeObserver | undefined;
onMounted(() => {
resizeObserver = new window.ResizeObserver(updateChartWidth);
if (chartElement.value) {
resizeObserver.observe(chartElement.value);
updateChartWidth();
}
});
onBeforeUnmount(() => {
resizeObserver?.disconnect();
resizeObserver = undefined;
});
function updateChartWidth(): void {
chartWidth.value = chartElement.value?.clientWidth || window.innerWidth;
}
</script>
<style scoped lang="less">
.date-range-chart-card {
padding: 1rem;
position: relative;
background: rgba(255, 255, 255, .92);
box-shadow: var(--td-shadow-1);
border-radius: 1.25rem;
.title {
gap: .5rem;
display: flex;
align-items: baseline;
justify-content: space-between;
h2 {
color: #0f172a;
margin: 0 0 .875rem 0;
font-size: 1rem;
font-weight: 700;
}
.caption {
color: #94a3b8;
font-size: .6875rem;
}
}
.chart {
width: 100%;
}
}
:global(html.theme-dark) {
.chart-section {
background: rgba(15, 23, 42, .88);
box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32);
h2 {
color: #e2e8f0;
}
}
}
</style>