index.vue 4.89 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType, DataFetchUpdateFn } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { useDataFetch } from '/@/views/visual/packages/hook/useSocket';
  import { ref, computed, unref } from 'vue';
  import { Space } from 'ant-design-vue';
  import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale';
  import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime';

  const props = defineProps<{
    config: ComponentPropsConfigType<typeof option>;
  }>();

  const currentValue = ref(99.23);

  const time = ref<Nullable<number>>(null);

  const integerPart = computed(() => {
    let number = unref(currentValue);
    const max = 5;
    if (isNaN(number)) number = 0;
    let _value = number.toString().split('.')[0];

    if (_value.length > max) return ''.padStart(max, '9');
    if (_value.length < max) return _value.padStart(max, '0');

    return _value;
  });

  const decimalPart = computed(() => {
    let number = unref(currentValue);

    const keepNumber = 2;

    if (isNaN(number)) number = 0;

    let _value = number.toString().split('.')[1] || '0';

    if (_value.length < keepNumber) return ''.padStart(keepNumber, '0');

    if (_value.length > keepNumber) return _value.slice(0, 2);

    return _value;
  });

  const getDesign = computed(() => {
    const { option, persetOption } = props.config;
    const { componentInfo, attribute, attributeRename } = option;
    const { fontColor: presetFontColor, unit: presetUnit } = persetOption || {};
    const { unit, fontColor } = componentInfo || {};
    return {
      unit: unit ?? presetUnit,
      fontColor: fontColor ?? presetFontColor,
      attribute: attributeRename || attribute,
    };
  });

  const updateFn: DataFetchUpdateFn = (message, attribute) => {
    const { data = {} } = message;
    const [latest] = data[attribute] || [];
    const [timespan, value] = latest;
    time.value = timespan;
    currentValue.value = isNaN(value as unknown as number) ? 0 : Number(value);
  };

  useDataFetch(props, updateFn);

  const { getScale } = useComponentScale(props);
</script>

<template>
  <main class="w-full h-full flex flex-col justify-center items-center">
    <div class="flex flex-col w-full h-full">
      <div class="flex-1 flex justify-center items-center">
        <div class="flex px-4 items-center transform scale-75" :style="getScale">
          <Space
            justify="end"
            class="justify-end"
            :size="4"
            :style="{
              backgroundColor: '#585357',
              padding: '10px',
            }"
          >
            <div
              v-for="number in integerPart"
              :key="number"
              class="digital-wrapper__int"
              :style="{
                color: getDesign.fontColor,
              }"
            >
              <div class="digital-text__int p-1 text-light-50"> {{ number }}</div>
            </div>
          </Space>
          <div
            class="m-0.5 rounded-1/2"
            style="background-color: #333; width: 6px; height: 6px; align-self: flex-end"
          >
          </div>
          <Space
            justify="end"
            class="justify-end"
            :size="4"
            :style="{
              backgroundColor: '#b74940',
              padding: '10px',
            }"
          >
            <div
              v-for="number in decimalPart"
              :key="number"
              class="digital-wrapper__float"
              :style="{
                color: getDesign.fontColor,
              }"
            >
              <div class="digital-text__float p-1 text-light-50">
                {{ number }}
              </div>
            </div>
          </Space>
          <div class="px-1 font-bold">
            {{ getDesign.unit || 'kw/h' }}
          </div>
        </div>
      </div>

      <div class="text-center truncate text-xs text-gray-500">
        <span>{{ getDesign.attribute || '电表' }}</span>
      </div>

      <UpdateTime :time="time" />
    </div>
  </main>
</template>

<style scoped lang="less">
  .digital-wrapper__int {
    border-radius: 1px;
    box-shadow: inset 0 1px 3px 0 rgba(0, 0, 0, 0.7);
    background: url('/@/assets/images/digital-wrapper-bg-int.png') 0 -1px no-repeat;
    padding: 5px;
    background-size: 100% 100%;
  }

  .digital-text_int {
    display: inline-block;
    overflow-wrap: break-word;
    color: rgba(255, 255, 255, 1);
    white-space: nowrap;
    text-align: center;
  }

  .digital-wrapper__float {
    border-radius: 1px;
    box-shadow: inset 0 1px 3px 0 rgba(112, 22, 15, 1);
    background: url('/@/assets/images/digital-wrapper-bg-float.png') 0 -1px no-repeat;
    padding: 5px;
    background-size: 100% 100%;
  }

  .digital-text_float {
    display: inline-block;
    overflow-wrap: break-word;
    color: rgba(255, 255, 255, 1);
    white-space: nowrap;
    text-align: center;
  }
</style>