|
|
@@ -0,0 +1,224 @@
|
|
|
+<template>
|
|
|
+ <v-chart ref="chartRef" :option="chartOptions" autoresize class="chart" />
|
|
|
+ <div class="box">
|
|
|
+ <div>
|
|
|
+ <span class="count">{{ data.high }}</span>
|
|
|
+ <div>
|
|
|
+ <div class="hight"></div>
|
|
|
+ <span class="label">High</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="count">{{ data.medium }}</span>
|
|
|
+ <div>
|
|
|
+ <div class="mediun"></div>
|
|
|
+ <span class="label">Mediun</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="count">{{ data.low }}</span>
|
|
|
+ <div>
|
|
|
+ <div class="low"></div>
|
|
|
+ <span class="label">Low</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup name="CountPage">
|
|
|
+import { ref, computed } from 'vue';
|
|
|
+import { use } from 'echarts/core';
|
|
|
+import { BarChart } from 'echarts/charts';
|
|
|
+import {
|
|
|
+ TooltipComponent,
|
|
|
+ LegendComponent,
|
|
|
+ GridComponent,
|
|
|
+} from 'echarts/components';
|
|
|
+import { CanvasRenderer } from 'echarts/renderers';
|
|
|
+import type { AlarmTotalRes } from '@/api/home';
|
|
|
+import type { ComposeOption } from 'echarts/core';
|
|
|
+import type { BarSeriesOption } from 'echarts/charts';
|
|
|
+import type {
|
|
|
+ TooltipComponentOption,
|
|
|
+ LegendComponentOption,
|
|
|
+ GridComponentOption,
|
|
|
+} from 'echarts/components';
|
|
|
+
|
|
|
+interface ListPageProps {
|
|
|
+ data: AlarmTotalRes;
|
|
|
+}
|
|
|
+const props = withDefaults(defineProps<ListPageProps>(), {
|
|
|
+ data: () => ({}) as AlarmTotalRes,
|
|
|
+});
|
|
|
+// 使用 computed 来处理数据,确保响应性
|
|
|
+const chartData = computed(() => props.data);
|
|
|
+use([
|
|
|
+ TooltipComponent,
|
|
|
+ LegendComponent,
|
|
|
+ GridComponent,
|
|
|
+ BarChart,
|
|
|
+ CanvasRenderer,
|
|
|
+]);
|
|
|
+
|
|
|
+type EChartsOption = ComposeOption<
|
|
|
+ | TooltipComponentOption
|
|
|
+ | LegendComponentOption
|
|
|
+ | GridComponentOption
|
|
|
+ | BarSeriesOption
|
|
|
+>;
|
|
|
+
|
|
|
+const chartOptions = computed<EChartsOption>(() => {
|
|
|
+ return {
|
|
|
+ backgroundColor: 'transparent',
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'shadow',
|
|
|
+ },
|
|
|
+ formatter: '{b}: {c}',
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: 0,
|
|
|
+ top: 0,
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ show: false,
|
|
|
+ type: 'value',
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 12,
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ lineStyle: {
|
|
|
+ color: 'rgba(255, 255, 255, 0.1)',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ show: false,
|
|
|
+ type: 'category',
|
|
|
+ data: ['High', 'Medium', 'Low'],
|
|
|
+ axisLine: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 14,
|
|
|
+ margin: 10,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '数值',
|
|
|
+ type: 'bar',
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ value: props.data?.high || 0,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#ff4d4f',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: props.data?.medium || 0,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#ffa940',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: props.data?.low || 0,
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: '#52c41a',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ barWidth: '40%',
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'right',
|
|
|
+ color: '#fff',
|
|
|
+ fontSize: 14,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+});
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.chart {
|
|
|
+ width: 100%;
|
|
|
+ height: 220px;
|
|
|
+}
|
|
|
+
|
|
|
+.box {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ div {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 33.33%;
|
|
|
+
|
|
|
+ .count {
|
|
|
+ margin-bottom: 5px;
|
|
|
+ color: var(--color-white);
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 24px;
|
|
|
+ }
|
|
|
+
|
|
|
+ div {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ width: 200px;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ margin-left: 8px;
|
|
|
+ color: var(--color-white);
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .hight {
|
|
|
+ width: 15px;
|
|
|
+ height: 15px;
|
|
|
+ background-color: #ff4d4f;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mediun {
|
|
|
+ width: 15px;
|
|
|
+ height: 15px;
|
|
|
+ background-color: #ffa940;
|
|
|
+ }
|
|
|
+
|
|
|
+ .low {
|
|
|
+ width: 15px;
|
|
|
+ height: 15px;
|
|
|
+ background-color: #52c41a;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|