DashBoardComponent.vue 5.6 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';
  import { useThrottleFn } from '@vueuse/shared';
  import { buildUUID } from '/@/utils/uuid';

  const props = defineProps({
    add: {
      type: Function,
    },
    layout: {
      type: Object as PropType<DashboardComponentLayout>,
      default: () => ({}),
    },
    value: {
      type: Object as PropType<DashBoardValue>,
      default: () => ({ id: buildUUID() }),
    },
    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 props.radio;
  });

  const getChardRadio = computed(() => {
    const realWidth = unref(chartRef)?.getWidth();
    const realHeight = unref(chartRef)?.getHeight();
    const radioRecord = props.radio;
    // const widht
    return {
      ...radioRecord,
      height: realHeight || radioRecord.height,
      width: realWidth || radioRecord.height,
    };
  });

  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: RadioRecord) => {};
  };

  function update() {
    const option = beforeUpdateFn(props.layout.componentType);
    unref(chartRef)?.setOption((option(unref(getChardRadio)) 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: DashBoardValue) => {};
  };

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

  watch(() => props.value, updateChartValue);

  const updateChartFont = useThrottleFn(() => {
    const option = beforeUpdateFn(props.layout.componentType);
    setTimeout(() => {
      unref(chartRef)?.setOption((option(unref(getChardRadio)) as unknown as EChartsOption) || {});
    });
  }, 500);

  watch(() => props.radio, updateChartFont);

  const updateChartType = useThrottleFn(() => {
    unref(chartRef)?.clear();
    unref(chartRef)?.setOption(props?.layout?.chartOption || {});
  }, 500);

  watch(() => props.layout.componentType, updateChartType);

  let timeout: Nullable<number> = null;

  function handleRandomValue() {
    const newValue = Math.floor(Math.random() * 100);
    const updateFn = getUpdateValueFn(props.layout.componentType);
    unref(chartRef)?.setOption(
      (updateFn({ ...props.value, value: 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;
  });

  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({ radioRecord: getRadio, basic: 16, max: 18 }),
          color: '#666',
        }"
      >
        {{ props.value.name }}
      </div>

      <div
        class="text-xs text-center p-5"
        :style="{
          fontSize: fontSize({ radioRecord: getRadio, basic: 12, max: 12 }),
          color: '#999',
        }"
      >
        <Tooltip
          placement="top"
          :title="
            props.value?.updateTime
              ? dateUtil(props?.value?.updateTime).format(DEFAULT_DATE_FORMAT)
              : '暂无更新时间'
          "
        >
          <div class="truncate">
            <span class="mr-2">更新时间:</span>
            <span>
              {{
                props.value?.updateTime
                  ? dateUtil(props?.value?.updateTime).format(DEFAULT_DATE_FORMAT)
                  : '暂无更新时间'
              }}
            </span>
          </div>
        </Tooltip>
      </div>
    </div>
  </div>
</template>

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