123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- <template>
- <div class="bar-chart-container">
- <div class="chart-wrapper">
- <v-chart
- class="chart"
- :option="chartOption"
- :autoresize="true"
- style="height: 244px;"
- />
- </div>
- <div class="title">{{ title }}</div>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref, computed, onMounted, watch } from 'vue'
- import { use } from 'echarts/core'
- import { CanvasRenderer } from 'echarts/renderers'
- import { BarChart } from 'echarts/charts'
- import {
- TitleComponent,
- TooltipComponent,
- LegendComponent,
- GridComponent
- } from 'echarts/components'
- import VChart from 'vue-echarts'
- use([
- CanvasRenderer,
- BarChart,
- TitleComponent,
- TooltipComponent,
- LegendComponent,
- GridComponent
- ])
- interface BarItem {
- name: string
- value: number
- percentage: string
- }
- const props = withDefaults(defineProps<{
- data?: BarItem[]
- title?: string
- }>(), {
- data: () => []
- })
- // 默认数据
- const defaultData: BarItem[] = [
- { name: '6次以上', value: 45, percentage: '45.0%' },
- { name: '5次', value: 23, percentage: '23.0%' },
- { name: '4次', value: 15, percentage: '15.0%' },
- { name: '3次', value: 8, percentage: '8.0%' },
- { name: '2次', value: 6, percentage: '6.0%' },
- { name: '1次', value: 3, percentage: '3.0%' }
- ]
- const displayData = computed(() => {
- return props.data && props.data.length > 0 ? props.data : defaultData
- })
- const chartOption = computed(() => {
- return {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'shadow'
- },
- formatter: function(params: any) {
- const data = params[0]
- return `${data.name}<br/>设备数:${data.value} (${data.data.percentage})`
- },
- backgroundColor: 'rgba(255, 255, 255, 0.9)',
- borderColor: '#e6e6e6',
- borderWidth: 1,
- textStyle: {
- color: '#333'
- }
- },
- grid: {
- left: '0',
- right: '0',
- bottom: '0',
- top: '3%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- data: displayData.value.map(item => item.name),
- axisLine: {
- lineStyle: {
- color: '#e6e6e6'
- }
- },
- axisTick: {
- show: false
- },
- axisLabel: {
- color: 'rgba(100, 100, 100, 1)',
- fontSize: 14
- }
- },
- yAxis: {
- type: 'value',
- name: '次数',
- nameTextStyle: {
- color: 'rgba(100, 100, 100, 1)',
- fontSize: 14
- },
- axisLine: {
- show: false
- },
- axisTick: {
- show: false
- },
- axisLabel: {
- color: 'rgba(100, 100, 100, 1)',
- fontSize: 13
- },
- splitLine: {
- lineStyle: {
- color: '#f0f0f0',
- type: 'dashed'
- }
- }
- },
- series: [
- {
- name: '卸载次数',
- type: 'bar',
- data: displayData.value.map(item => ({
- value: item.value,
- percentage: item.percentage
- })),
- itemStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- { offset: 0, color: 'rgba(109, 173, 249, 1)' },
- { offset: 1, color: 'rgba(109, 173, 249, 1)' }
- ]
- },
- borderRadius: [0, 0, 0, 0]
- },
- emphasis: {
- itemStyle: {
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 0,
- y2: 1,
- colorStops: [
- { offset: 0, color: 'rgba(109, 173, 249, 1)' },
- { offset: 1, color: 'rgba(109, 173, 249, 1)' }
- ]
- }
- }
- },
- barWidth: '60%'
- }
- ]
- }
- })
- onMounted(() => {
- // 组件挂载后的初始化逻辑
- })
- // 监听数据变化
- watch(displayData, (newData) => {
- console.log('Bar chart data updated:', newData)
- }, { deep: true })
- </script>
- <style scoped lang="scss">
- .bar-chart-container {
- width: 100%;
- height: 100%;
- text-align: center;
- }
- .chart-wrapper {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .chart {
- width: 100%;
- height: 100%;
- }
- .title {
- display: inline-block;
- color: rgba(18, 18, 18, 1);
- font-family: Source Han Sans SC;
- font-weight: 400;
- font-style: Regular;
- font-size: 14px;
- padding-left: 14px;
- position: relative;
- margin-top: 30px;
- &::before {
- content: '';
- position: absolute;
- left: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 8px;
- height: 8px;
- background-color: rgba(109, 173, 249, 1);
- }
- }
- </style>
|