DashBoardComponent.vue 4.49 KB
<script lang="ts" setup>
  import type { ECharts, EChartsOption } from 'echarts';
  import { PropType, watch } from 'vue';
  import { nextTick, onMounted, onUnmounted, ref, unref, computed } from 'vue';
  import { init } from 'echarts';
  import {
    DashboardComponentLayout,
    DashBoardValue,
    instrumentComponent1,
    InstrumentComponentType,
    update_instrument_1_font,
    update_instrument_2_font,
    update_instrument_1_value,
    update_instrument_2_value,
  } from './dashBoardComponent.config';
  import { dateUtil } from '/@/utils/dateUtil';
  import {
    DEFAULT_RADIO_RECORD,
    RadioRecord,
    DEFAULT_DATE_FORMAT,
    fontSize,
  } from '../../detail/config/util';
  import { Tooltip } from 'ant-design-vue';

  const props = defineProps({
    add: {
      type: Function,
    },
    layout: {
      type: Object as PropType<DashboardComponentLayout>,
      default: () => ({}),
    },
    value: {
      type: Object as PropType<DashBoardValue>,
      default: () => ({}),
    },
    radio: {
      type: Object as PropType<RadioRecord>,
      default: () => DEFAULT_RADIO_RECORD,
    },
    random: {
      type: Boolean,
      default: true,
    },
  });

  const getControlsWidgetId = () => `widget-chart-${props.value.id}`;

  const chartRef = ref<Nullable<ECharts>>(null);

  function initChart() {
    const chartDom = document.getElementById(getControlsWidgetId())!;
    chartRef.value = init(chartDom);
    const option: EChartsOption = props.layout.chartOption || instrumentComponent1();

    nextTick(() => {
      option && unref(chartRef)?.setOption(option);
    });
  }

  const getRadio = computed(() => {
    const { radio } = props.radio;
    return radio;
  });

  const beforeUpdateFn = (componentType: InstrumentComponentType) => {
    if (componentType === 'instrument-component-1') return update_instrument_1_font;
    if (componentType === 'instrument-component-2') return update_instrument_2_font;
    return (_radio: number) => {};
  };

  function update() {
    const option = beforeUpdateFn(props.layout.componentType);
    unref(chartRef)?.setOption((option(unref(getRadio)) as unknown as EChartsOption) || {});
    unref(chartRef)?.resize();
  }

  const getUpdateValueFn = (componentType: InstrumentComponentType) => {
    if (componentType === 'instrument-component-1') return update_instrument_1_value;
    if (componentType === 'instrument-component-2') return update_instrument_2_value;
    return (_radio: number) => {};
  };

  watch(
    () => props.value.value,
    (newValue) => {
      const updateFn = getUpdateValueFn(props.layout.componentType);
      unref(chartRef)?.setOption((updateFn(newValue || 0) as unknown as EChartsOption) || {});
    }
  );

  watch(
    () => props.radio,
    () => {
      const option = beforeUpdateFn(props.layout.componentType);
      setTimeout(() => {
        unref(chartRef)?.setOption((option(unref(getRadio)) as unknown as EChartsOption) || {});
      });
    }
  );

  let timeout: Nullable<number> = null;

  function handleRandomValue() {
    const newValue = Math.floor(Math.random() * 100);
    const updateFn = getUpdateValueFn(props.layout.componentType);
    unref(chartRef)?.setOption((updateFn(newValue) as unknown as EChartsOption) || {});
  }

  onMounted(() => {
    initChart();
    props.add && props.add(props.value.id, update);
    if (props.random) timeout = setInterval(handleRandomValue, 2000) as unknown as number;
    console.log(unref(chartRef));
  });

  onUnmounted(() => {
    unref(chartRef)?.clear();
    clearInterval(timeout as number);
    timeout = null;
  });

  defineExpose({ update });
</script>

<template>
  <div class="flex flex-col w-full h-full min-w-3 min-h-3">
    <div :id="getControlsWidgetId()" class="widget-charts w-full h-full flex-auto"></div>
    <div>
      <div class="text-center" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{
        props.value.name
      }}</div>
      <div
        class="text-xs text-center text-gray-400 truncate"
        :style="{ fontSize: fontSize({ radio: getRadio, basic: 12, max: 16 }) }"
      >
        <Tooltip
          placement="topLeft"
          :title="dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT)"
        >
          <span class="mr-2">更新时间:</span>
          <span>
            {{ dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT) }}
          </span>
        </Tooltip>
      </div>
    </div>
  </div>
</template>

<style scoped>
  .widget-charts > div {
    width: 100%;
    height: 100%;
  }
</style>