dashBoardComponent.config.ts 8.49 KB
import { EChartsOption } from 'echarts';
import { fontSize } from '../../detail/config/util';
import { Gradient, visualOptionField } from '../../detail/config/visualOptions';
import {
  ComponentInfo,
  DataComponentRecord,
  DataSource,
  GradientInfo,
} from '/@/api/dataBoard/model';
import { isArray } from '/@/utils/is';
import { buildUUID } from '/@/utils/uuid';

export type InstrumentComponentType = 'instrument-component-1' | 'instrument-component-2';

export type GradientKey =
  | visualOptionField.FIRST_PHASE_COLOR
  | visualOptionField.FIRST_PHASE_VALUE
  | visualOptionField.SECOND_PHASE_COLOR
  | visualOptionField.SECOND_PHASE_VALUE
  | visualOptionField.THIRD_PHASE_COLOR
  | visualOptionField.THIRD_PHASE_VALUE;

export interface GradientInfoRecord {
  key: Gradient;
  value: number;
  color: string;
}

export interface DashBoardValue {
  id: string;
  unit?: string;
  name?: string;
  updateTime?: string;
  value?: number;
  valueColor?: string;
  gradientInfo?: GradientInfoRecord[];
}

export interface DashboardComponentLayout {
  chartOption: EChartsOption;
  componentType: InstrumentComponentType;
}

export enum GradientColor {
  FIRST = '#67e0e3',
  SECOND = '#37a2da',
  THIRD = '#fd666d',
}

export const instrumentComponent1 = (params?: Partial<ComponentInfo>): EChartsOption => {
  const { value = 10, unit = '°C' } = params || {};
  return {
    series: [
      {
        type: 'gauge',
        center: ['50%', '60%'],
        startAngle: 200,
        endAngle: -20,
        min: 0,
        max: 100,
        splitNumber: 10,
        itemStyle: {
          color: '#FFAB91',
        },
        progress: {
          show: true,
          width: 30,
        },
        pointer: {
          show: false,
        },
        axisLine: {
          lineStyle: {
            width: 30,
          },
        },
        axisTick: {
          distance: -35,
          splitNumber: 5,
          lineStyle: {
            width: 2,
            color: '#999',
          },
        },
        splitLine: {
          distance: -45,
          length: 14,
          lineStyle: {
            width: 3,
            color: '#999',
          },
        },
        axisLabel: {
          distance: -5,
          color: '#999',
          // fontSize: 20,
        },
        anchor: {
          show: false,
        },
        title: {
          show: false,
        },
        detail: {
          valueAnimation: true,
          width: '60%',
          lineHeight: 10,
          borderRadius: 8,
          offsetCenter: [0, '30%'],
          fontSize: 14,
          fontWeight: 'bolder',
          formatter: `{value} ${unit ?? ''}`,
          color: params?.fontColor || 'inherit',
        },
        data: [
          {
            value: value as number,
          },
        ],
      },
      {
        type: 'gauge',
        center: ['50%', '60%'],
        startAngle: 200,
        endAngle: -20,
        min: 0,
        max: 100,
        itemStyle: {
          color: '#FD7347',
        },
        progress: {
          show: true,
          width: 8,
        },
        pointer: {
          show: false,
        },
        axisLine: {
          show: false,
        },
        axisTick: {
          show: false,
        },
        splitLine: {
          show: false,
        },
        axisLabel: {
          show: false,
        },
        detail: {
          show: false,
        },
        data: [
          {
            value: value as number,
          },
        ],
      },
    ],
  };
};

export const instrumentComponent2 = (params?: Partial<ComponentInfo>): EChartsOption => {
  const { gradientInfo = [], value = 0, unit = 'km/h' } = params || {};
  const firstRecord = getGradient(Gradient.FIRST, gradientInfo);
  const secondRecord = getGradient(Gradient.SECOND, gradientInfo);
  const thirdRecord = getGradient(Gradient.THIRD, gradientInfo);

  let max = thirdRecord?.value || secondRecord?.value || firstRecord?.value || 70;
  max = Number(1 + Array(String(max).length).fill(0).join(''));

  const firstGradient = firstRecord?.value ? firstRecord.value / max : 0.3;
  const secondGradient = secondRecord?.value ? secondRecord.value / max : 0.7;
  // const thirdGradient = thirdRecord?.value ? thirdRecord.value / max : 1;

  return {
    series: [
      {
        type: 'gauge',
        min: 0,
        max,
        axisLine: {
          lineStyle: {
            width: 20,
            color: [
              [firstGradient, firstRecord?.color || GradientColor.FIRST],
              [secondGradient, secondRecord?.color || GradientColor.SECOND],
              [1, thirdRecord?.color || GradientColor.THIRD],
            ],
          },
        },
        pointer: {
          itemStyle: {
            color: 'inherit',
          },
        },
        axisTick: {
          distance: -30,
          length: 8,
          splitNumber: max / 100,
          lineStyle: {
            color: '#fff',
            width: 2,
          },
        },
        splitLine: {
          distance: -10,
          length: 30,
          lineStyle: {
            color: '#fff',
            width: 4,
          },
        },
        axisLabel: {
          color: 'inherit',
          distance: 5,
          fontSize: 6,
        },
        detail: {
          valueAnimation: true,
          formatter: `{value} ${unit ?? ''}`,
          color: params?.fontColor || 'inherit',
          offsetCenter: [0, '70%'],
          fontSize: 14,
        },
        data: [
          {
            value: value as number,
          },
        ],
      },
    ],
  };
};

export const getGradient = (key: Gradient, record: GradientInfo[] = []) => {
  if (!isArray(record)) return;
  return record.find((item) => item.key === key);
};

export const update_instrument_1_font = (radio: number) => {
  const basicFontSize = fontSize({ radio, basic: 10, max: 20 });
  return {
    series: [
      {
        axisLabel: {
          fontSize: basicFontSize,
        },
        detail: {
          fontSize: basicFontSize,
        },
      },
    ],
  } as EChartsOption;
};

export const update_instrument_2_font = (radio: number) => {
  const axisLabelFontSize = fontSize({ radio, basic: 10, max: 16 });
  const detailFontSize = fontSize({ radio, basic: 12 });
  return {
    series: [
      {
        axisLabel: {
          fontSize: axisLabelFontSize,
        },
        detail: {
          fontSize: detailFontSize,
        },
      },
    ],
  } as EChartsOption;
};

const handleValue = (value: any) => {
  return Number(value).toFixed(2);
};

export const update_instrument_1_value = (value: number) => {
  return {
    series: [
      {
        data: [{ value: handleValue(value) }],
      },
      {
        data: [{ value: handleValue(value) }],
      },
    ],
  } as EChartsOption;
};

export const update_instrument_2_value = (value: number) => {
  return {
    series: [
      {
        data: [{ value: handleValue(value) }],
      },
    ],
  } as EChartsOption;
};

function setGradientInfo(dataSource: DataSource) {
  const componentInfo = dataSource.componentInfo;
  return instrumentComponent2(componentInfo);
}

export const Instrument1DefaultConfig: Partial<ComponentInfo> = {
  fontColor: '#FD7347',
};

export const Instrument2DefaultConfig: Partial<ComponentInfo> = {
  fontColor: GradientColor.FIRST,
  unit: 'km/h',
  gradientInfo: [
    { key: Gradient.FIRST, value: 30, color: GradientColor.FIRST },
    { key: Gradient.SECOND, value: 70, color: GradientColor.SECOND },
    { key: Gradient.THIRD, value: 80, color: GradientColor.THIRD },
  ],
};

export const transformDashboardComponentConfig = (
  config: DashboardComponentLayout,
  record: DataComponentRecord,
  dataSourceRecord: DataSource
) => {
  let chartOption = config.chartOption;
  if (config.componentType === 'instrument-component-2') {
    chartOption = setGradientInfo(dataSourceRecord);
  }
  if (config.componentType === 'instrument-component-1') {
    const componentInfo = dataSourceRecord.componentInfo;
    chartOption = instrumentComponent1({
      unit: componentInfo.unit,
      value: 0,
      fontColor: componentInfo.fontColor,
    });
  }
  return {
    layout: {
      chartOption: chartOption,
      componentType: config.componentType,
    } as DashboardComponentLayout,
    value: {
      id: buildUUID(),
      name: dataSourceRecord.attributeRename || dataSourceRecord.attribute,
      value: dataSourceRecord.componentInfo.value,
      unit: dataSourceRecord.componentInfo.unit,
      updateTime: dataSourceRecord.componentInfo.updateTime,
      fontColor: dataSourceRecord.componentInfo.fontColor,
      gradientInfo: dataSourceRecord.componentInfo.gradientInfo,
    },
  };
};