|  | 1 | +<script lang="ts" setup> | 
|  | 2 | +  import moment from 'moment'; | 
|  | 3 | +  import { nextTick, onMounted, onUnmounted, Ref, ref, unref } from 'vue'; | 
|  | 4 | +  import { getDeviceDataKeys, getDeviceHistoryInfo } from '/@/api/alarm/position'; | 
|  | 5 | +  import { Empty } from 'ant-design-vue'; | 
|  | 6 | +  import { useECharts } from '/@/hooks/web/useECharts'; | 
|  | 7 | +  import { dateUtil } from '/@/utils/dateUtil'; | 
|  | 8 | +  import { | 
|  | 9 | +    AggregateDataEnum, | 
|  | 10 | +    eChartOptions, | 
|  | 11 | +    selectDeviceAttrSchema, | 
|  | 12 | +  } from '/@/views/device/localtion/config.data'; | 
|  | 13 | +  import { useTimePeriodForm } from '/@/views/device/localtion/cpns/TimePeriodForm'; | 
|  | 14 | +  import { defaultSchemas, QueryWay } from '/@/views/device/localtion/cpns/TimePeriodForm/config'; | 
|  | 15 | +  import TimePeriodForm from '/@/views/device/localtion/cpns/TimePeriodForm/TimePeriodForm.vue'; | 
|  | 16 | +  import { SchemaFiled } from '/@/views/report/config/config.data'; | 
|  | 17 | +  import { useGridLayout } from '/@/hooks/component/useGridLayout'; | 
|  | 18 | +  import { ColEx } from '/@/components/Form/src/types'; | 
|  | 19 | + | 
|  | 20 | +  interface DeviceDetail { | 
|  | 21 | +    tbDeviceId: string; | 
|  | 22 | +  } | 
|  | 23 | + | 
|  | 24 | +  const props = defineProps<{ | 
|  | 25 | +    deviceDetail: DeviceDetail; | 
|  | 26 | +  }>(); | 
|  | 27 | + | 
|  | 28 | +  const chartRef = ref(); | 
|  | 29 | + | 
|  | 30 | +  const deviceAttrs = ref<string[]>([]); | 
|  | 31 | + | 
|  | 32 | +  const loading = ref(false); | 
|  | 33 | + | 
|  | 34 | +  const isNull = ref(false); | 
|  | 35 | + | 
|  | 36 | +  function getSearchParams(value: Recordable) { | 
|  | 37 | +    const { startTs, endTs, interval, agg, limit, keys, way } = value; | 
|  | 38 | +    if (way === QueryWay.LATEST) { | 
|  | 39 | +      return { | 
|  | 40 | +        entityId: props.deviceDetail.tbDeviceId, | 
|  | 41 | +        keys: keys ? keys : unref(deviceAttrs).join(), | 
|  | 42 | +        startTs: moment().subtract(startTs, 'ms').valueOf(), | 
|  | 43 | +        endTs: Date.now(), | 
|  | 44 | +        interval, | 
|  | 45 | +        agg, | 
|  | 46 | +        limit, | 
|  | 47 | +      }; | 
|  | 48 | +    } else { | 
|  | 49 | +      return { | 
|  | 50 | +        entityId: props.deviceDetail.tbDeviceId, | 
|  | 51 | +        keys: keys ? keys : unref(deviceAttrs).join(), | 
|  | 52 | +        startTs: moment(startTs).valueOf(), | 
|  | 53 | +        endTs: moment(endTs).valueOf(), | 
|  | 54 | +        interval, | 
|  | 55 | +        agg, | 
|  | 56 | +        limit, | 
|  | 57 | +      }; | 
|  | 58 | +    } | 
|  | 59 | +  } | 
|  | 60 | + | 
|  | 61 | +  function hasDeviceAttr() { | 
|  | 62 | +    if (!unref(deviceAttrs).length) { | 
|  | 63 | +      return false; | 
|  | 64 | +    } else { | 
|  | 65 | +      return true; | 
|  | 66 | +    } | 
|  | 67 | +  } | 
|  | 68 | + | 
|  | 69 | +  const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>); | 
|  | 70 | + | 
|  | 71 | +  function setChartOptions(data, keys?) { | 
|  | 72 | +    const dataArray: any[] = []; | 
|  | 73 | +    for (const key in data) { | 
|  | 74 | +      for (const item1 of data[key]) { | 
|  | 75 | +        let { ts, value } = item1; | 
|  | 76 | +        const time = dateUtil(ts).format('YYYY-MM-DD HH:mm:ss'); | 
|  | 77 | +        value = Number(value).toFixed(2); | 
|  | 78 | +        dataArray.push([time, value, key]); | 
|  | 79 | +      } | 
|  | 80 | +    } | 
|  | 81 | +    keys = keys ? [keys] : unref(deviceAttrs); | 
|  | 82 | +    const series: any = keys.map((item) => { | 
|  | 83 | +      return { | 
|  | 84 | +        name: item, | 
|  | 85 | +        type: 'line', | 
|  | 86 | +        data: dataArray.filter((item1) => item1[2] === item), | 
|  | 87 | +      }; | 
|  | 88 | +    }); | 
|  | 89 | +    // 设置数据 | 
|  | 90 | +    setOptions(eChartOptions(series, keys)); | 
|  | 91 | +  } | 
|  | 92 | + | 
|  | 93 | +  const [register, method] = useTimePeriodForm({ | 
|  | 94 | +    schemas: [...defaultSchemas, ...selectDeviceAttrSchema], | 
|  | 95 | +    baseColProps: useGridLayout(2, 3, 4) as unknown as ColEx, | 
|  | 96 | +    async submitFunc() { | 
|  | 97 | +      // 表单验证 | 
|  | 98 | +      await method.validate(); | 
|  | 99 | +      const value = method.getFieldsValue(); | 
|  | 100 | +      const searchParams = getSearchParams(value); | 
|  | 101 | + | 
|  | 102 | +      if (!hasDeviceAttr()) return; | 
|  | 103 | +      // 发送请求 | 
|  | 104 | +      loading.value = true; | 
|  | 105 | +      const res = await getDeviceHistoryInfo(searchParams); | 
|  | 106 | +      // 判断数据对象是否为空 | 
|  | 107 | +      if (!Object.keys(res).length) { | 
|  | 108 | +        isNull.value = false; | 
|  | 109 | +        return; | 
|  | 110 | +      } else { | 
|  | 111 | +        isNull.value = true; | 
|  | 112 | +      } | 
|  | 113 | +      setChartOptions(res, value.keys); | 
|  | 114 | +      loading.value = false; | 
|  | 115 | +    }, | 
|  | 116 | +  }); | 
|  | 117 | + | 
|  | 118 | +  const getDeviceDataKey = async () => { | 
|  | 119 | +    const { tbDeviceId } = props.deviceDetail || {}; | 
|  | 120 | +    try { | 
|  | 121 | +      deviceAttrs.value = (await getDeviceDataKeys(tbDeviceId)) || []; | 
|  | 122 | +    } catch (error) {} | 
|  | 123 | +  }; | 
|  | 124 | + | 
|  | 125 | +  const openHistoryPanel = async () => { | 
|  | 126 | +    await nextTick(); | 
|  | 127 | +    method.updateSchema({ | 
|  | 128 | +      field: 'keys', | 
|  | 129 | +      componentProps: { | 
|  | 130 | +        options: unref(deviceAttrs).map((item) => ({ label: item, value: item })), | 
|  | 131 | +      }, | 
|  | 132 | +    }); | 
|  | 133 | + | 
|  | 134 | +    method.setFieldsValue({ | 
|  | 135 | +      [SchemaFiled.START_TS]: 1 * 24 * 60 * 60 * 1000, | 
|  | 136 | +      [SchemaFiled.LIMIT]: 7, | 
|  | 137 | +      [SchemaFiled.AGG]: AggregateDataEnum.NONE, | 
|  | 138 | +    }); | 
|  | 139 | + | 
|  | 140 | +    if (!hasDeviceAttr()) return; | 
|  | 141 | + | 
|  | 142 | +    const res = await getDeviceHistoryInfo({ | 
|  | 143 | +      entityId: props.deviceDetail.tbDeviceId, | 
|  | 144 | +      keys: unref(deviceAttrs).join(), | 
|  | 145 | +      startTs: Date.now() - 1 * 24 * 60 * 60 * 1000, | 
|  | 146 | +      endTs: Date.now(), | 
|  | 147 | +      agg: AggregateDataEnum.NONE, | 
|  | 148 | +    }); | 
|  | 149 | + | 
|  | 150 | +    // 判断对象是否为空 | 
|  | 151 | +    if (!Object.keys(res).length) { | 
|  | 152 | +      isNull.value = false; | 
|  | 153 | +      return; | 
|  | 154 | +    } else { | 
|  | 155 | +      isNull.value = true; | 
|  | 156 | +    } | 
|  | 157 | +    setChartOptions(res); | 
|  | 158 | +  }; | 
|  | 159 | + | 
|  | 160 | +  onMounted(async () => { | 
|  | 161 | +    await getDeviceDataKey(); | 
|  | 162 | +    await openHistoryPanel(); | 
|  | 163 | +  }); | 
|  | 164 | + | 
|  | 165 | +  onUnmounted(() => { | 
|  | 166 | +    getInstance()?.clear(); | 
|  | 167 | +  }); | 
|  | 168 | +</script> | 
|  | 169 | + | 
|  | 170 | +<template> | 
|  | 171 | +  <section class="flex flex-col p-4 h-full" style="color: #f0f2f5"> | 
|  | 172 | +    <section class="bg-white p-3"> | 
|  | 173 | +      <TimePeriodForm @register="register" /> | 
|  | 174 | +    </section> | 
|  | 175 | +    <section class="bg-white p-3"> | 
|  | 176 | +      <div v-show="isNull" ref="chartRef" :style="{ height: '550px', width: '100%' }"> | 
|  | 177 | +        <Loading :loading="loading" :absolute="true" /> | 
|  | 178 | +      </div> | 
|  | 179 | +      <Empty v-show="!isNull" /> | 
|  | 180 | +    </section> | 
|  | 181 | +  </section> | 
|  | 182 | +</template> | 
|  | 183 | + | 
|  | 184 | +<style scoped></style> | 
... | ... |  |