<script lang="ts" setup>
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { MesDvTelemetryApi } from '#/api/mes/dv/telemetry';
|
|
import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';
|
|
import { Page } from '@vben/common-ui';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
import { Button, Card, Select, Statistic, Tag } from 'ant-design-vue';
|
|
import {
|
getTelemetryCheckList,
|
getTelemetryCheckSummary,
|
getTelemetryDeviceList,
|
} from '#/api/mes/dv/telemetry';
|
|
/** MES 供电参数比对校验(各设备最新参数 vs 标准值) */
|
defineOptions({ name: 'MesDvTelemetryCheck' });
|
|
const devices = ref<MesDvTelemetryApi.DeviceItem[]>([]);
|
const selectedDeviceId = ref<string>();
|
const summaryList = ref<MesDvTelemetryApi.CheckSummary[]>([]);
|
|
const contentRef = useTemplateRef('contentRef');
|
let resizeObserver: ResizeObserver | undefined;
|
|
/** 计算表格高度:内容区可用高度 - 设备选择行/统计卡片/工具栏等固定开销 */
|
function calcTableHeight() {
|
const el = contentRef.value;
|
if (!el) return;
|
const height = Math.max(el.clientHeight - 230, 240);
|
checkGridApi.setGridOptions({ height });
|
}
|
|
onMounted(async () => {
|
calcTableHeight();
|
resizeObserver = new ResizeObserver(calcTableHeight);
|
if (contentRef.value) resizeObserver.observe(contentRef.value);
|
devices.value = await getTelemetryDeviceList();
|
await loadSummary();
|
});
|
|
onBeforeUnmount(() => resizeObserver?.disconnect());
|
|
async function loadSummary() {
|
summaryList.value = await getTelemetryCheckSummary({
|
tbDeviceId: selectedDeviceId.value,
|
});
|
}
|
|
/** 选设备或刷新:重载统计卡片 + 明细表 */
|
async function refreshAll() {
|
await loadSummary();
|
checkGridApi.query();
|
}
|
|
/** 选中设备的统计;未选择则汇总全部设备 */
|
const currentSummary = computed(() => {
|
if (selectedDeviceId.value) {
|
return (
|
summaryList.value.find((s) => s.tbDeviceId === selectedDeviceId.value) ??
|
{}
|
);
|
}
|
return summaryList.value.reduce(
|
(acc, s) => {
|
acc.totalCount = (acc.totalCount ?? 0) + (s.totalCount ?? 0);
|
acc.normalCount = (acc.normalCount ?? 0) + (s.normalCount ?? 0);
|
acc.anomalyCount = (acc.anomalyCount ?? 0) + (s.anomalyCount ?? 0);
|
return acc;
|
},
|
{ totalCount: 0, normalCount: 0, anomalyCount: 0 } as MesDvTelemetryApi.CheckSummary,
|
);
|
});
|
|
const anomalyRate = computed(() => {
|
const total = currentSummary.value.totalCount ?? 0;
|
if (total <= 0) return 0;
|
return Number(
|
(((currentSummary.value.anomalyCount ?? 0) * 100) / total).toFixed(1),
|
);
|
});
|
|
const [CheckGrid, checkGridApi] = useVbenVxeGrid({
|
gridOptions: {
|
columns: [
|
{ field: 'deviceName', title: '设备名称', minWidth: 150 },
|
{ field: 'paramName', title: '信号名称', minWidth: 140 },
|
{ field: 'paramKeyName', title: '设备KEY名称', minWidth: 130 },
|
{ field: 'standardValue', title: '标准值', width: 110 },
|
{ field: 'timelyValue', title: '实时值', width: 110 },
|
{ field: 'avgValue', title: '均值', width: 110 },
|
{ field: 'maxValue', title: '最大值', width: 110 },
|
{ field: 'minValue', title: '最小值', width: 110 },
|
{
|
field: 'whetherAnomaly',
|
title: '是否异常',
|
width: 100,
|
slots: { default: 'anomaly' },
|
},
|
],
|
height: 400,
|
keepSource: true,
|
// /check 返回裸数组,需关闭分页
|
pagerConfig: { enabled: false },
|
proxyConfig: {
|
ajax: {
|
query: async () =>
|
await getTelemetryCheckList({
|
tbDeviceId: selectedDeviceId.value,
|
}),
|
},
|
},
|
rowConfig: { keyField: 'id', isHover: true },
|
toolbarConfig: { refresh: true },
|
} as VxeTableGridOptions<MesDvTelemetryApi.Telemetry>,
|
});
|
</script>
|
|
<template>
|
<Page auto-content-height>
|
<div ref="contentRef" class="flex h-full w-full flex-col p-4">
|
<div class="mb-4 flex flex-wrap items-center gap-4">
|
<Select
|
v-model:value="selectedDeviceId"
|
class="w-72"
|
allow-clear
|
placeholder="请选择设备(不选则展示全部设备)"
|
:options="
|
devices.map((d) => ({ label: d.deviceName, value: d.tbDeviceId }))
|
"
|
@change="refreshAll"
|
/>
|
<Button @click="refreshAll">刷新</Button>
|
</div>
|
<div class="mb-4 grid grid-cols-2 gap-4 lg:grid-cols-4">
|
<Card>
|
<Statistic title="参数总数" :value="currentSummary.totalCount ?? 0" />
|
</Card>
|
<Card>
|
<Statistic
|
title="正常"
|
:value="currentSummary.normalCount ?? 0"
|
:value-style="{ color: '#52c41a' }"
|
/>
|
</Card>
|
<Card>
|
<Statistic
|
title="异常"
|
:value="currentSummary.anomalyCount ?? 0"
|
:value-style="{ color: '#ff4d4f' }"
|
/>
|
</Card>
|
<Card>
|
<Statistic title="异常率" :value="anomalyRate" suffix="%" />
|
</Card>
|
</div>
|
<CheckGrid table-title="供电参数比对明细" class="min-h-0 flex-1">
|
<template #anomaly="{ row }">
|
<Tag :color="row.whetherAnomaly ? 'red' : 'green'">
|
{{ row.whetherAnomaly ? '异常' : '正常' }}
|
</Tag>
|
</template>
|
</CheckGrid>
|
</div>
|
</Page>
|
</template>
|