| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <template>
- <TechCard>
- <div class="card-header">
- <div class="title">跌倒与告警统计</div>
- </div>
- <div ref="chartRef" class="chart-container" />
- </TechCard>
- </template>
- <script lang="ts" setup>
- import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
- import * as echarts from 'echarts'
- import TechCard from '../TechCard/index.vue'
- defineOptions({ name: 'AlertFallCompareCard' })
- const chartRef = ref<HTMLDivElement | null>(null)
- const chartInstance = ref<echarts.ECharts | null>(null)
- interface Props {
- fallCount: number
- alertCount: number
- }
- const props = withDefaults(defineProps<Props>(), {
- fallCount: 0,
- alertCount: 0,
- })
- const createChart = () => {
- if (!chartRef.value) return
- if (chartInstance.value) {
- chartInstance.value.dispose()
- }
- chartInstance.value = echarts.init(chartRef.value)
- updateChart()
- }
- const updateChart = () => {
- if (!chartInstance.value) return
- chartInstance.value.setOption({
- tooltip: {
- trigger: 'axis',
- axisPointer: { type: 'shadow' },
- formatter: '{b}: {c} 次',
- },
- grid: {
- left: 40,
- right: 20,
- top: 20,
- bottom: 40,
- },
- xAxis: {
- type: 'category',
- data: ['跌倒', '告警'],
- axisLabel: { color: '#9cc5e0' },
- axisTick: { show: false },
- axisLine: { show: false },
- },
- yAxis: {
- type: 'value',
- axisLabel: { color: '#9cc5e0' },
- splitLine: { show: false },
- },
- series: [
- {
- type: 'bar',
- data: [props.fallCount, props.alertCount],
- barWidth: 40,
- itemStyle: {
- color: (params: { dataIndex: number }) => ['#ff4d6d', '#f39c12'][params.dataIndex],
- },
- label: {
- show: true,
- position: 'top',
- color: '#fff',
- fontSize: 14,
- },
- },
- ],
- })
- }
- const resizeChart = () => {
- if (chartInstance.value) {
- chartInstance.value.resize()
- }
- }
- onMounted(() => {
- nextTick(() => {
- createChart()
- window.addEventListener('resize', resizeChart)
- })
- })
- watch(
- () => [props.fallCount, props.alertCount],
- () => {
- updateChart()
- }
- )
- // 组件卸载时销毁图表实例和事件监听
- onUnmounted(() => {
- if (chartInstance.value) {
- chartInstance.value.dispose()
- chartInstance.value = null
- }
- window.removeEventListener('resize', resizeChart)
- })
- </script>
- <style lang="less" scoped>
- .card-header {
- text-align: center;
- margin-bottom: 12px;
- .title {
- font-size: 16px;
- font-weight: bold;
- color: #00f0ff;
- }
- }
- .chart-container {
- width: 100%;
- height: 200px;
- }
- </style>
|