Commit 1248c5ee6ead93a0d54eebfed6615e41c48f0f1f

Authored by xp.Huang
2 parents c528cfdd b4857133

Merge branch 'fix/OverrideLineForDeviceHistoryQuery' into 'main_dev'

fix: 修复查询单设备属性历史数据组件无分组间隔

See merge request yunteng/thingskit-view!123
... ... @@ -34,7 +34,8 @@ export const option = {
34 34 queryCondition: {
35 35 timeRange: [new Date().getTime() - 86400000, new Date().getTime()], //默认最近一天
36 36 limit: 7,
37   - agg: 'NONE'
  37 + agg: 'NONE',
  38 + interval: null
38 39 },
39 40 ...otherConfig,
40 41 tooltip: {
... ...
  1 +import dayjs, { Dayjs } from 'dayjs';
  2 +
  3 +enum TimeUnit {
  4 + SECOND = 'second',
  5 + MINUTE = 'MINUTE',
  6 + HOUR = 'HOUR',
  7 + DAY = 'DAY',
  8 +}
  9 +
  10 +const unitMapping = {
  11 + [TimeUnit.SECOND]: '秒',
  12 + [TimeUnit.MINUTE]: '分',
  13 + [TimeUnit.HOUR]: '小时',
  14 + [TimeUnit.DAY]: '天',
  15 +};
  16 +
  17 +const unitConversion = {
  18 + [TimeUnit.SECOND]: 1 * 1000,
  19 + [TimeUnit.MINUTE]: 1 * 60 * 1000,
  20 + [TimeUnit.HOUR]: 1 * 60 * 60 * 1000,
  21 + [TimeUnit.DAY]: 1 * 60 * 60 * 24 * 1000,
  22 +};
  23 +
  24 +export const intervalOption = [
  25 + {
  26 + id: 1,
  27 + unit: TimeUnit.SECOND,
  28 + linkage: [{ id: 1, unit: TimeUnit.SECOND }],
  29 + },
  30 + {
  31 + id: 5,
  32 + unit: TimeUnit.SECOND,
  33 + linkage: [{ id: 1, unit: TimeUnit.SECOND }],
  34 + },
  35 + {
  36 + id: 10,
  37 + unit: TimeUnit.SECOND,
  38 + linkage: [{ id: 1, unit: TimeUnit.SECOND }],
  39 + },
  40 + {
  41 + id: 15,
  42 + unit: TimeUnit.SECOND,
  43 + linkage: [{ id: 1, unit: TimeUnit.SECOND }],
  44 + },
  45 + {
  46 + id: 30,
  47 + unit: TimeUnit.SECOND,
  48 + linkage: [{ id: 1, unit: TimeUnit.SECOND }],
  49 + },
  50 + {
  51 + id: 1,
  52 + unit: TimeUnit.MINUTE,
  53 + linkage: [
  54 + { id: 1, unit: TimeUnit.SECOND },
  55 + { id: 5, unit: TimeUnit.SECOND },
  56 + ],
  57 + },
  58 + {
  59 + id: 2,
  60 + unit: TimeUnit.MINUTE,
  61 + linkage: [
  62 + { id: 1, unit: TimeUnit.SECOND },
  63 + { id: 5, unit: TimeUnit.SECOND },
  64 + { id: 10, unit: TimeUnit.SECOND },
  65 + { id: 15, unit: TimeUnit.SECOND },
  66 + ],
  67 + },
  68 + {
  69 + id: 5,
  70 + unit: TimeUnit.MINUTE,
  71 + linkage: [
  72 + { id: 1, unit: TimeUnit.SECOND },
  73 + { id: 5, unit: TimeUnit.SECOND },
  74 + { id: 10, unit: TimeUnit.SECOND },
  75 + { id: 15, unit: TimeUnit.SECOND },
  76 + { id: 30, unit: TimeUnit.SECOND },
  77 + ],
  78 + },
  79 + {
  80 + id: 10,
  81 + unit: TimeUnit.MINUTE,
  82 + linkage: [
  83 + { id: 5, unit: TimeUnit.SECOND },
  84 + { id: 10, unit: TimeUnit.SECOND },
  85 + { id: 15, unit: TimeUnit.SECOND },
  86 + { id: 30, unit: TimeUnit.SECOND },
  87 + { id: 1, unit: TimeUnit.MINUTE },
  88 + ],
  89 + },
  90 + {
  91 + id: 15,
  92 + unit: TimeUnit.MINUTE,
  93 + linkage: [
  94 + { id: 5, unit: TimeUnit.SECOND },
  95 + { id: 10, unit: TimeUnit.SECOND },
  96 + { id: 15, unit: TimeUnit.SECOND },
  97 + { id: 30, unit: TimeUnit.SECOND },
  98 + { id: 1, unit: TimeUnit.MINUTE },
  99 + { id: 2, unit: TimeUnit.MINUTE },
  100 + ],
  101 + },
  102 + {
  103 + id: 30,
  104 + unit: TimeUnit.MINUTE,
  105 + linkage: [
  106 + { id: 5, unit: TimeUnit.SECOND },
  107 + { id: 10, unit: TimeUnit.SECOND },
  108 + { id: 15, unit: TimeUnit.SECOND },
  109 + { id: 30, unit: TimeUnit.SECOND },
  110 + { id: 1, unit: TimeUnit.MINUTE },
  111 + { id: 2, unit: TimeUnit.MINUTE },
  112 + ],
  113 + },
  114 + {
  115 + id: 1,
  116 + unit: TimeUnit.HOUR,
  117 + linkage: [
  118 + { id: 10, unit: TimeUnit.SECOND },
  119 + { id: 15, unit: TimeUnit.SECOND },
  120 + { id: 30, unit: TimeUnit.SECOND },
  121 + { id: 1, unit: TimeUnit.MINUTE },
  122 + { id: 2, unit: TimeUnit.MINUTE },
  123 + { id: 5, unit: TimeUnit.MINUTE },
  124 + ],
  125 + },
  126 + {
  127 + id: 2,
  128 + unit: TimeUnit.HOUR,
  129 + linkage: [
  130 + { id: 15, unit: TimeUnit.SECOND },
  131 + { id: 30, unit: TimeUnit.SECOND },
  132 + { id: 1, unit: TimeUnit.MINUTE },
  133 + { id: 2, unit: TimeUnit.MINUTE },
  134 + { id: 5, unit: TimeUnit.MINUTE },
  135 + { id: 10, unit: TimeUnit.MINUTE },
  136 + { id: 15, unit: TimeUnit.MINUTE },
  137 + ],
  138 + },
  139 + {
  140 + id: 5,
  141 + unit: TimeUnit.HOUR,
  142 + linkage: [
  143 + { id: 1, unit: TimeUnit.MINUTE },
  144 + { id: 2, unit: TimeUnit.MINUTE },
  145 + { id: 5, unit: TimeUnit.MINUTE },
  146 + { id: 10, unit: TimeUnit.MINUTE },
  147 + { id: 15, unit: TimeUnit.MINUTE },
  148 + { id: 30, unit: TimeUnit.MINUTE },
  149 + ],
  150 + },
  151 + {
  152 + id: 10,
  153 + unit: TimeUnit.HOUR,
  154 + linkage: [
  155 + { id: 2, unit: TimeUnit.MINUTE },
  156 + { id: 5, unit: TimeUnit.MINUTE },
  157 + { id: 10, unit: TimeUnit.MINUTE },
  158 + { id: 15, unit: TimeUnit.MINUTE },
  159 + { id: 30, unit: TimeUnit.MINUTE },
  160 + { id: 1, unit: TimeUnit.HOUR },
  161 + ],
  162 + },
  163 + {
  164 + id: 12,
  165 + unit: TimeUnit.HOUR,
  166 + linkage: [
  167 + { id: 2, unit: TimeUnit.MINUTE },
  168 + { id: 5, unit: TimeUnit.MINUTE },
  169 + { id: 10, unit: TimeUnit.MINUTE },
  170 + { id: 15, unit: TimeUnit.MINUTE },
  171 + { id: 30, unit: TimeUnit.MINUTE },
  172 + { id: 1, unit: TimeUnit.HOUR },
  173 + ],
  174 + },
  175 + {
  176 + id: 1,
  177 + unit: TimeUnit.DAY,
  178 + linkage: [
  179 + { id: 5, unit: TimeUnit.MINUTE },
  180 + { id: 10, unit: TimeUnit.MINUTE },
  181 + { id: 15, unit: TimeUnit.MINUTE },
  182 + { id: 30, unit: TimeUnit.MINUTE },
  183 + { id: 1, unit: TimeUnit.HOUR },
  184 + { id: 2, unit: TimeUnit.HOUR },
  185 + ],
  186 + },
  187 + {
  188 + id: 7,
  189 + unit: TimeUnit.DAY,
  190 + linkage: [
  191 + { id: 30, unit: TimeUnit.MINUTE },
  192 + { id: 1, unit: TimeUnit.HOUR },
  193 + { id: 2, unit: TimeUnit.HOUR },
  194 + { id: 5, unit: TimeUnit.HOUR },
  195 + { id: 10, unit: TimeUnit.HOUR },
  196 + { id: 12, unit: TimeUnit.HOUR },
  197 + { id: 1, unit: TimeUnit.DAY },
  198 + ],
  199 + },
  200 + {
  201 + id: 30,
  202 + unit: TimeUnit.DAY,
  203 + linkage: [
  204 + { id: 2, unit: TimeUnit.HOUR },
  205 + { id: 5, unit: TimeUnit.HOUR },
  206 + { id: 10, unit: TimeUnit.HOUR },
  207 + { id: 12, unit: TimeUnit.HOUR },
  208 + { id: 1, unit: TimeUnit.DAY },
  209 + ],
  210 + },
  211 +].map((item) => {
  212 + return {
  213 + value: item.id * unitConversion[item.unit],
  214 + label: item.id + unitMapping[item.unit],
  215 + linkage: item.linkage.map((item) => {
  216 + return {
  217 + value: item.id * unitConversion[item.unit],
  218 + label: item.id + unitMapping[item.unit],
  219 + };
  220 + }),
  221 + };
  222 +});
  223 +
  224 +const rangeIntervalOption = [
  225 + {
  226 + id: 90,
  227 + unit: TimeUnit.DAY,
  228 + linkage: [
  229 + { id: 5, unit: TimeUnit.HOUR },
  230 + { id: 10, unit: TimeUnit.HOUR },
  231 + { id: 12, unit: TimeUnit.HOUR },
  232 + { id: 1, unit: TimeUnit.DAY },
  233 + { id: 7, unit: TimeUnit.DAY },
  234 + ],
  235 + },
  236 + {
  237 + id: 180,
  238 + unit: TimeUnit.DAY,
  239 + linkage: [
  240 + { id: 10, unit: TimeUnit.HOUR },
  241 + { id: 12, unit: TimeUnit.HOUR },
  242 + { id: 1, unit: TimeUnit.DAY },
  243 + { id: 7, unit: TimeUnit.DAY },
  244 + ],
  245 + },
  246 + {
  247 + id: 360,
  248 + unit: TimeUnit.DAY,
  249 + linkage: [
  250 + { id: 1, unit: TimeUnit.DAY },
  251 + { id: 7, unit: TimeUnit.DAY },
  252 + { id: 30, unit: TimeUnit.DAY },
  253 + ],
  254 + },
  255 +].map((item) => {
  256 + return {
  257 + value: item.id * unitConversion[item.unit],
  258 + label: item.id + unitMapping[item.unit],
  259 + linkage: item.linkage.map((item) => {
  260 + return {
  261 + value: item.id * unitConversion[item.unit],
  262 + label: item.id + unitMapping[item.unit],
  263 + };
  264 + }),
  265 + };
  266 +});
  267 +
  268 +/**
  269 + * @description
  270 + * @param {number} value
  271 + * @returns
  272 + */
  273 +export function getPacketIntervalByValue(value: number) {
  274 + return intervalOption.find((item) => item.value === value)?.linkage || [];
  275 +}
  276 +
  277 +export function getPacketIntervalByRange(
  278 + [start, end] = [null, null] as [Nullable<Dayjs>, Nullable<Dayjs>]
  279 +) {
  280 + start = typeof start === 'number' ? dayjs(start) : start
  281 + end = typeof end === 'number' ? dayjs(end) : end
  282 +
  283 + if (start && end) {
  284 + const value = end.diff(start, 'ms');
  285 + let options: { value: number; label: string }[] = [];
  286 + for (const item of [...intervalOption, ...rangeIntervalOption]) {
  287 + if (item.value <= value) continue;
  288 + if (item.value >= value) {
  289 + options = item.linkage;
  290 + break;
  291 + }
  292 + }
  293 + return options;
  294 + }
  295 + return [];
  296 +}
... ...
1 1 <template>
2 2 <div>
3 3 <n-space vertical>
4   - <n-space>
5   - <n-date-picker
6   - size="small"
7   - :to="true"
8   - clearable
9   - v-model:value="queryCondition.timeRange"
10   - type="datetimerange"
11   - :shortcuts="rangeShortcuts"
12   - />
13   - <n-select :style="`width:160px`" v-model:value="queryCondition.agg" :options="aggOptions" clearable />
14   - <n-input-number
15   - :min="7"
16   - :max="50000"
17   - :style="`width:160px`"
18   - v-if="queryCondition.agg === 'NONE'"
19   - v-model:value="queryCondition.limit"
20   - clearable
21   - />
22   - </n-space>
  4 + <div class="form">
  5 + <n-date-picker size="small" :to="true" clearable v-model:value="queryCondition.timeRange" type="datetimerange"
  6 + :shortcuts="rangeShortcuts" format="yyyy-MM-dd" @change="queryCondition.interval = null" />
  7 + <n-select v-model:value="queryCondition.agg" size="small" :options="aggOptions" clearable
  8 + @change="handleAggChange" />
  9 + <n-input-number :min="7" :max="50000" size="small" v-if="queryCondition.agg === 'NONE'"
  10 + v-model:value="queryCondition.limit" clearable />
  11 + <n-select v-if="queryCondition.agg !== 'NONE'" size="small" v-model:value="queryCondition.interval"
  12 + :options="getPacketIntervalByRange(queryCondition.timeRange)" />
  13 + </div>
23 14 </n-space>
24   - <v-chart
25   - ref="vChartRef"
26   - :init-options="initOptions"
27   - :theme="themeColor"
28   - :option="option"
29   - :manual-update="isPreview()"
  15 + <v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="option" :manual-update="isPreview()"
30 16 :update-options="{
31 17 replaceMerge: replaceMergeArr
32   - }"
33   - autoresize
34   - @mouseover="handleHighlight"
35   - @mouseout="handleDownplay"
36   - >
  18 + }" autoresize @mouseover="handleHighlight" @mouseout="handleDownplay">
37 19 </v-chart>
38 20 </div>
39 21 </template>
... ... @@ -58,6 +40,7 @@ import { useFullScreen } from '../../utls/fullScreen'
58 40 import { useAssembleDataHooks } from '@/hooks/external/useAssembleData.hook'
59 41 import { SocketReceiveMessageType } from '@/store/external/modules/socketStore.d'
60 42 import { useChartInteract } from '@/hooks/external/useChartSelectDeviceInteract.hook'
  43 +import { getPacketIntervalByRange } from './helper'
61 44
62 45 const props = defineProps({
63 46 themeSetting: {
... ... @@ -273,6 +256,10 @@ const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (n
273 256 updateVChart(newData)
274 257 })
275 258
  259 +const handleAggChange = (value: string) => {
  260 + if (value === 'NONE') queryCondition.value.interval = null
  261 +}
  262 +
276 263 onMounted(() => {
277 264 seriesDataMaxLength = dataJson.source.length
278 265 if (props.chartConfig.option.isCarousel) {
... ... @@ -287,7 +274,8 @@ watch(
287 274 startTs: newValue.timeRange.at(-2),
288 275 endTs: newValue.timeRange.at(-1),
289 276 limit: newValue.limit,
290   - agg: newValue.agg
  277 + agg: newValue.agg,
  278 + interval: newValue.interval
291 279 }
292 280 if (newValue.agg !== 'NONE') {
293 281 Reflect.deleteProperty(obj, 'limit')
... ... @@ -304,4 +292,13 @@ const onChange = (v: object) => {
304 292 // 存储到联动数据
305 293 useChartInteract(props.chartConfig, useChartEditStore, { data: v })
306 294 }
  295 +
307 296 </script>
  297 +
  298 +<style lang="scss" scoped>
  299 +.form {
  300 + display: grid;
  301 + grid-template-columns: 2fr 1fr 1fr;
  302 + gap: 8px;
  303 +}
  304 +</style>
... ...
... ... @@ -88,7 +88,6 @@ export const useSyncRemote = () => {
88 88 return
89 89 }
90 90 projectInfoStore.setSaveStatus(SyncEnum.START)
91   - console.log(dataViewContent)
92 91 // 保存数据
93 92 const saveContent = {
94 93 dataViewContent: {
... ...