<script lang="ts" setup>
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { DecisionAlertApi } from '#/api/bi/decision/alert';
|
|
import { onMounted, reactive, ref } from 'vue';
|
|
import { Page } from '@vben/common-ui';
|
|
import { message, Tag } from 'ant-design-vue';
|
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { confirmAlert, getAlertPage, getUnprocessedCount, handleAlert } from '#/api/bi/decision/alert';
|
|
defineOptions({ name: 'DecisionAlertCenter' });
|
|
const unprocessedCount = ref(0);
|
const queryParams = reactive<Record<string, unknown>>({});
|
|
const [Grid, gridApi] = useVbenVxeGrid({
|
formOptions: {
|
schema: [
|
{
|
fieldName: 'status',
|
label: '状态',
|
component: 'Select',
|
componentProps: {
|
options: [
|
{ label: '全部', value: '' },
|
{ label: '未处理', value: 0 },
|
{ label: '已确认', value: 1 },
|
{ label: '已处理', value: 2 },
|
],
|
allowClear: true,
|
},
|
},
|
{
|
fieldName: 'severity',
|
label: '严重级别',
|
component: 'Select',
|
componentProps: {
|
options: [
|
{ label: '全部', value: '' },
|
{ label: '警告', value: 1 },
|
{ label: '严重', value: 2 },
|
{ label: '紧急', value: 3 },
|
],
|
allowClear: true,
|
},
|
},
|
],
|
},
|
gridOptions: {
|
columns: [
|
{ field: 'id', title: 'ID', width: 60 },
|
{ field: 'kpiName', title: 'KPI名称', width: 140 },
|
{
|
field: 'severity', title: '严重级别', width: 90,
|
slots: { default: 'severitySlot' },
|
},
|
{
|
field: 'actualValue', title: '实际值', width: 100,
|
formatter: ({ cellValue }: any) => cellValue?.toLocaleString(),
|
},
|
{
|
field: 'thresholdValue', title: '阈值', width: 100,
|
formatter: ({ cellValue }: any) => cellValue?.toLocaleString(),
|
},
|
{ field: 'alertMessage', title: '预警消息', minWidth: 200 },
|
{
|
field: 'status', title: '状态', width: 80,
|
slots: { default: 'statusSlot' },
|
},
|
{ field: 'triggeredTime', title: '触发时间', width: 170 },
|
{ field: 'handleRemark', title: '处理备注', width: 140 },
|
{
|
title: '操作', width: 160,
|
slots: { default: 'actionSlot' },
|
fixed: 'right',
|
},
|
],
|
height: 'auto',
|
proxyConfig: {
|
ajax: {
|
query: async ({ page, form }: any) => {
|
const res = await getAlertPage({ ...page, ...form, ...queryParams });
|
return res;
|
},
|
},
|
},
|
} as VxeTableGridOptions<DecisionAlertApi.AlertRecord>,
|
});
|
|
async function loadUnprocessed() {
|
try {
|
unprocessedCount.value = await getUnprocessedCount();
|
} catch {
|
// ignore
|
}
|
}
|
|
async function handleConfirm(row: DecisionAlertApi.AlertRecord) {
|
const hide = message.loading('确认中...', 0);
|
try {
|
await confirmAlert(row.id);
|
message.success('已确认');
|
gridApi.query();
|
loadUnprocessed();
|
} finally {
|
hide();
|
}
|
}
|
|
async function handleProcess(row: DecisionAlertApi.AlertRecord) {
|
const hide = message.loading('处理中...', 0);
|
try {
|
await handleAlert(row.id, '已处理');
|
message.success('已处理');
|
gridApi.query();
|
loadUnprocessed();
|
} finally {
|
hide();
|
}
|
}
|
|
function severityColor(severity: number): string {
|
if (severity === 3) return 'red';
|
if (severity === 2) return 'orange';
|
return 'blue';
|
}
|
|
function severityText(severity: number): string {
|
if (severity === 3) return '紧急';
|
if (severity === 2) return '严重';
|
return '警告';
|
}
|
|
function statusColor(status: number): string {
|
if (status === 0) return 'red';
|
if (status === 1) return 'blue';
|
return 'green';
|
}
|
|
function statusText(status: number): string {
|
if (status === 0) return '未处理';
|
if (status === 1) return '已确认';
|
return '已处理';
|
}
|
|
onMounted(() => {
|
loadUnprocessed();
|
});
|
</script>
|
|
<template>
|
<Page :auto-content-height="true">
|
<div class="mb-3">
|
<span class="text-lg font-bold">预警中心</span>
|
<Tag v-if="unprocessedCount > 0" color="red" class="ml-2">
|
{{ unprocessedCount }} 条未处理
|
</Tag>
|
</div>
|
<Grid>
|
<template #severitySlot="{ row }">
|
<Tag :color="severityColor(row.severity)">{{ severityText(row.severity) }}</Tag>
|
</template>
|
<template #statusSlot="{ row }">
|
<Tag :color="statusColor(row.status)">{{ statusText(row.status) }}</Tag>
|
</template>
|
<template #actionSlot="{ row }">
|
<TableAction
|
:actions="[
|
{ label: '确认', type: 'link', icon: ACTION_ICON.AUDIT, ifShow: row.status === 0, onClick: handleConfirm.bind(null, row) },
|
{ label: '处理', type: 'link', icon: ACTION_ICON.EDIT, ifShow: row.status < 2, onClick: handleProcess.bind(null, row) },
|
]"
|
/>
|
</template>
|
</Grid>
|
</Page>
|
</template>
|