feat:告警界面
This commit is contained in:
@@ -670,7 +670,7 @@ const local:any = {
|
|||||||
alert:'警告',
|
alert:'警告',
|
||||||
gateway:'网关',
|
gateway:'网关',
|
||||||
switches:'交换机',
|
switches:'交换机',
|
||||||
clients:'装置',
|
clients:'终端',
|
||||||
search:'输入站点名称',
|
search:'输入站点名称',
|
||||||
total:'共',
|
total:'共',
|
||||||
addsite:'添加站点',
|
addsite:'添加站点',
|
||||||
|
|||||||
@@ -514,6 +514,115 @@ export function getPaymentConfig() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取告警数据
|
||||||
|
export function fetchAlertList(siteId: string, params: {
|
||||||
|
pageNum: number;
|
||||||
|
pageSize: number;
|
||||||
|
filters: {
|
||||||
|
timeStart?: string;
|
||||||
|
timeEnd?: string;
|
||||||
|
module?: string;
|
||||||
|
resolved?: boolean;
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/log/alerts/${siteId}`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
pageNum: params.pageNum,
|
||||||
|
pageSize: params.pageSize,
|
||||||
|
'filters.timeStart': params.filters.timeStart,
|
||||||
|
'filters.timeEnd': params.filters.timeEnd,
|
||||||
|
'filters.module': params.filters.module,
|
||||||
|
'filters.resolved': params.filters.resolved,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 删除告警
|
||||||
|
export function deleteAlerts(siteId: string, data: {
|
||||||
|
selectType: 'unresolved' | 'resolved' | 'all';
|
||||||
|
startTime: number;
|
||||||
|
endTime: number;
|
||||||
|
logs: number[];
|
||||||
|
}) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/log/alerts/${siteId}`,
|
||||||
|
method: 'delete',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 标记告警为已解决
|
||||||
|
export function markAlertsResolved(siteId: string, data: {
|
||||||
|
selectType: 'unresolved' | 'resolved' | 'all';
|
||||||
|
startTime: number;
|
||||||
|
endTime: number;
|
||||||
|
logs: string[];
|
||||||
|
}) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/log/alerts/${siteId}`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取白名单配置
|
||||||
|
export function fetchAccessControl(siteId: string) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/access-control/${siteId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 更新白名单配置
|
||||||
|
export function updateAccessControl(siteId: string, data: {
|
||||||
|
preAuthAccessEnable: boolean;
|
||||||
|
freeAuthClientEnable: boolean;
|
||||||
|
preAuthAccessPolicies: Array<{
|
||||||
|
type: number;
|
||||||
|
ip?: string;
|
||||||
|
url?: string;
|
||||||
|
}>;
|
||||||
|
freeAuthClientPolicies: Array<{
|
||||||
|
type: number;
|
||||||
|
clientIp?: string;
|
||||||
|
clientMac?: string;
|
||||||
|
}>;
|
||||||
|
}) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/access-control/${siteId}`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 获取 Mesh 配置
|
||||||
|
export function getMeshConfig(siteId: string) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/site/${siteId}/mesh`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 更新 Mesh 配置
|
||||||
|
export function updateMeshConfig(siteId: string, data: { meshEnable: boolean; autoFailoverEnable?: boolean }) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/site/${siteId}/mesh`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取 Roaming 配置
|
||||||
|
export function getRoamingConfig(siteId: string) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/site/${siteId}/roaming`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 更新 Roaming 配置
|
||||||
|
export function updateRoamingConfig(siteId: string, data: { fastRoamingEnable: boolean; noStickRoamingEnable?: boolean; aiRoamingEnable?: boolean }) {
|
||||||
|
return request<any>({
|
||||||
|
url: `/system/site/${siteId}/roaming`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
9
src/typings/auto-imports.d.ts
vendored
9
src/typings/auto-imports.d.ts
vendored
@@ -66,6 +66,7 @@ declare global {
|
|||||||
const defineStore: typeof import('pinia')['defineStore']
|
const defineStore: typeof import('pinia')['defineStore']
|
||||||
const delData: typeof import('../service/api/dictData')['delData']
|
const delData: typeof import('../service/api/dictData')['delData']
|
||||||
const delJobLog: typeof import('../service/api/job')['delJobLog']
|
const delJobLog: typeof import('../service/api/job')['delJobLog']
|
||||||
|
const deleteAlerts: typeof import('../service/api/auth')['deleteAlerts']
|
||||||
const deleteApDevices: typeof import('../service/api/auth')['deleteApDevices']
|
const deleteApDevices: typeof import('../service/api/auth')['deleteApDevices']
|
||||||
const deletePackage: typeof import('../service/api/auth')['deletePackage']
|
const deletePackage: typeof import('../service/api/auth')['deletePackage']
|
||||||
const deletePortal: typeof import('../service/api/auth')['deletePortal']
|
const deletePortal: typeof import('../service/api/auth')['deletePortal']
|
||||||
@@ -133,6 +134,8 @@ declare global {
|
|||||||
const exportJobLog: typeof import('../service/api/jobLog')['exportJobLog']
|
const exportJobLog: typeof import('../service/api/jobLog')['exportJobLog']
|
||||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||||
const extractTabsByAllRoutes: typeof import('../store/modules/tab/shared')['extractTabsByAllRoutes']
|
const extractTabsByAllRoutes: typeof import('../store/modules/tab/shared')['extractTabsByAllRoutes']
|
||||||
|
const fetchAccessControl: typeof import('../service/api/auth')['fetchAccessControl']
|
||||||
|
const fetchAlertList: typeof import('../service/api/auth')['fetchAlertList']
|
||||||
const fetchApDeviceList: typeof import('../service/api/auth')['fetchApDeviceList']
|
const fetchApDeviceList: typeof import('../service/api/auth')['fetchApDeviceList']
|
||||||
const fetchBillList: typeof import('../service/api/auth')['fetchBillList']
|
const fetchBillList: typeof import('../service/api/auth')['fetchBillList']
|
||||||
const fetchBillRuleList: typeof import('../service/api/auth')['fetchBillRuleList']
|
const fetchBillRuleList: typeof import('../service/api/auth')['fetchBillRuleList']
|
||||||
@@ -183,8 +186,10 @@ declare global {
|
|||||||
const getFixedTabs: typeof import('../store/modules/tab/shared')['getFixedTabs']
|
const getFixedTabs: typeof import('../store/modules/tab/shared')['getFixedTabs']
|
||||||
const getGlobalMenusByAuthRoutes: typeof import('../store/modules/route/shared')['getGlobalMenusByAuthRoutes']
|
const getGlobalMenusByAuthRoutes: typeof import('../store/modules/route/shared')['getGlobalMenusByAuthRoutes']
|
||||||
const getLocalizedTimeUnit: typeof import('../utils/units')['getLocalizedTimeUnit']
|
const getLocalizedTimeUnit: typeof import('../utils/units')['getLocalizedTimeUnit']
|
||||||
|
const getMeshConfig: typeof import('../service/api/auth')['getMeshConfig']
|
||||||
const getPaymentConfig: typeof import('../service/api/auth')['getPaymentConfig']
|
const getPaymentConfig: typeof import('../service/api/auth')['getPaymentConfig']
|
||||||
const getPortalConfig: typeof import('../service/api/auth')['getPortalConfig']
|
const getPortalConfig: typeof import('../service/api/auth')['getPortalConfig']
|
||||||
|
const getRoamingConfig: typeof import('../service/api/auth')['getRoamingConfig']
|
||||||
const getRouteIcons: typeof import('../store/modules/tab/shared')['getRouteIcons']
|
const getRouteIcons: typeof import('../store/modules/tab/shared')['getRouteIcons']
|
||||||
const getSelectedMenuKeyPathByKey: typeof import('../store/modules/route/shared')['getSelectedMenuKeyPathByKey']
|
const getSelectedMenuKeyPathByKey: typeof import('../store/modules/route/shared')['getSelectedMenuKeyPathByKey']
|
||||||
const getServiceBaseURL: typeof import('../utils/service')['getServiceBaseURL']
|
const getServiceBaseURL: typeof import('../utils/service')['getServiceBaseURL']
|
||||||
@@ -216,6 +221,7 @@ declare global {
|
|||||||
const mapState: typeof import('pinia')['mapState']
|
const mapState: typeof import('pinia')['mapState']
|
||||||
const mapStores: typeof import('pinia')['mapStores']
|
const mapStores: typeof import('pinia')['mapStores']
|
||||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||||
|
const markAlertsResolved: typeof import('../service/api/auth')['markAlertsResolved']
|
||||||
const markRaw: typeof import('vue')['markRaw']
|
const markRaw: typeof import('vue')['markRaw']
|
||||||
const nextTick: typeof import('vue')['nextTick']
|
const nextTick: typeof import('vue')['nextTick']
|
||||||
const omit: typeof import('lodash-es')['omit']
|
const omit: typeof import('lodash-es')['omit']
|
||||||
@@ -307,15 +313,18 @@ declare global {
|
|||||||
const unref: typeof import('vue')['unref']
|
const unref: typeof import('vue')['unref']
|
||||||
const unrefElement: typeof import('@vueuse/core')['unrefElement']
|
const unrefElement: typeof import('@vueuse/core')['unrefElement']
|
||||||
const until: typeof import('@vueuse/core')['until']
|
const until: typeof import('@vueuse/core')['until']
|
||||||
|
const updateAccessControl: typeof import('../service/api/auth')['updateAccessControl']
|
||||||
const updateApDeviceConfig: typeof import('../service/api/auth')['updateApDeviceConfig']
|
const updateApDeviceConfig: typeof import('../service/api/auth')['updateApDeviceConfig']
|
||||||
const updateBillRule: typeof import('../service/api/auth')['updateBillRule']
|
const updateBillRule: typeof import('../service/api/auth')['updateBillRule']
|
||||||
const updateData: typeof import('../service/api/dictData')['updateData']
|
const updateData: typeof import('../service/api/dictData')['updateData']
|
||||||
const updateJob: typeof import('../service/api/job')['updateJob']
|
const updateJob: typeof import('../service/api/job')['updateJob']
|
||||||
const updateLocaleOfGlobalMenus: typeof import('../store/modules/route/shared')['updateLocaleOfGlobalMenus']
|
const updateLocaleOfGlobalMenus: typeof import('../store/modules/route/shared')['updateLocaleOfGlobalMenus']
|
||||||
|
const updateMeshConfig: typeof import('../service/api/auth')['updateMeshConfig']
|
||||||
const updatePackage: typeof import('../service/api/auth')['updatePackage']
|
const updatePackage: typeof import('../service/api/auth')['updatePackage']
|
||||||
const updatePasswordByOld: typeof import('../service/api/auth')['updatePasswordByOld']
|
const updatePasswordByOld: typeof import('../service/api/auth')['updatePasswordByOld']
|
||||||
const updatePaymentConfig: typeof import('../service/api/auth')['updatePaymentConfig']
|
const updatePaymentConfig: typeof import('../service/api/auth')['updatePaymentConfig']
|
||||||
const updatePortalConfig: typeof import('../service/api/auth')['updatePortalConfig']
|
const updatePortalConfig: typeof import('../service/api/auth')['updatePortalConfig']
|
||||||
|
const updateRoamingConfig: typeof import('../service/api/auth')['updateRoamingConfig']
|
||||||
const updateSite: typeof import('../service/api/auth')['updateSite']
|
const updateSite: typeof import('../service/api/auth')['updateSite']
|
||||||
const updateTabByI18nKey: typeof import('../store/modules/tab/shared')['updateTabByI18nKey']
|
const updateTabByI18nKey: typeof import('../store/modules/tab/shared')['updateTabByI18nKey']
|
||||||
const updateTabsByI18nKey: typeof import('../store/modules/tab/shared')['updateTabsByI18nKey']
|
const updateTabsByI18nKey: typeof import('../store/modules/tab/shared')['updateTabsByI18nKey']
|
||||||
|
|||||||
267
src/views/device/alerts/index.vue
Normal file
267
src/views/device/alerts/index.vue
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, watch, computed } from 'vue'
|
||||||
|
import { message, Modal } from 'ant-design-vue'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { DeleteOutlined, ToolOutlined } from '@ant-design/icons-vue'
|
||||||
|
// 假设API与portal页面一致
|
||||||
|
import { fetchSiteList, fetchAlertList, deleteAlerts, markAlertsResolved } from '@/service/api/auth'
|
||||||
|
|
||||||
|
const siteList = ref<{ siteId: string, name: string }[]>([])
|
||||||
|
const selectedSiteId = ref('')
|
||||||
|
const siteLoading = ref(false)
|
||||||
|
|
||||||
|
const getSiteList = async () => {
|
||||||
|
siteLoading.value = true
|
||||||
|
const { data, error } = await fetchSiteList({ pageNum: 1, pageSize: 100 })
|
||||||
|
if (!error) {
|
||||||
|
siteList.value = data.rows || []
|
||||||
|
selectedSiteId.value = siteList.value[0]?.siteId || ''
|
||||||
|
}
|
||||||
|
siteLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期选择器相关
|
||||||
|
const now = dayjs()
|
||||||
|
const startOfToday = now.startOf('day')
|
||||||
|
const dateRange = ref<[any, any]>([startOfToday, now])
|
||||||
|
|
||||||
|
// 告警相关
|
||||||
|
const activeMainTab = ref('Alerts')
|
||||||
|
// const activeSubTab = ref('Resolved') // 已不再需要
|
||||||
|
const statusTab = ref('Unresolved') // Unresolved/Resolved
|
||||||
|
const typeTab = ref('All') // All/System/Device
|
||||||
|
const alerts = ref<any[]>([])
|
||||||
|
const selectedRowKeys = ref<string[]>([])
|
||||||
|
const pageNum = ref(1)
|
||||||
|
const pageSize = ref(10)
|
||||||
|
const total = ref(0)
|
||||||
|
|
||||||
|
const getAlerts = async () => {
|
||||||
|
if (!selectedSiteId.value) return
|
||||||
|
const filters: any = {
|
||||||
|
timeStart: dateRange.value[0] ? dateRange.value[0].valueOf() : undefined,
|
||||||
|
timeEnd: dateRange.value[1] ? dateRange.value[1].valueOf() : undefined,
|
||||||
|
module: typeTab.value === 'All' ? undefined : typeTab.value,
|
||||||
|
resolved: statusTab.value === 'Resolved' ? true : false
|
||||||
|
}
|
||||||
|
const { data, error } = await fetchAlertList(selectedSiteId.value, {
|
||||||
|
pageNum: pageNum.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
filters
|
||||||
|
})
|
||||||
|
if (!error && data) {
|
||||||
|
alerts.value = (data.rows || []).map((item: any) => ({ ...item, id: String(item.id) }))
|
||||||
|
total.value = data.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSiteChange = async (value: string) => {
|
||||||
|
selectedSiteId.value = value
|
||||||
|
pageNum.value = 1
|
||||||
|
await getAlerts()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onResolve = async (id: string | number) => {
|
||||||
|
if (!selectedSiteId.value) {
|
||||||
|
message.warning('请先选择站点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { error } = await markAlertsResolved(selectedSiteId.value, {
|
||||||
|
selectType: 'all',
|
||||||
|
startTime: dateRange.value[0].valueOf(),
|
||||||
|
endTime: dateRange.value[1].valueOf(),
|
||||||
|
logs: [String(id)]
|
||||||
|
})
|
||||||
|
if (!error) {
|
||||||
|
await getAlerts()
|
||||||
|
message.success('已标记为已解决')
|
||||||
|
} else {
|
||||||
|
message.error('标记失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete = async (ids: number | number[]) => {
|
||||||
|
if (!selectedSiteId.value) {
|
||||||
|
message.warning('请先选择站点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = Array.isArray(ids) ? ids : [ids]
|
||||||
|
const deleteCount = deleteIds.length
|
||||||
|
|
||||||
|
const { error } = await deleteAlerts(selectedSiteId.value, {
|
||||||
|
selectType: 'all', // 固定传 all
|
||||||
|
startTime: dateRange.value[0].valueOf(),
|
||||||
|
endTime: dateRange.value[1].valueOf(),
|
||||||
|
logs: deleteIds
|
||||||
|
})
|
||||||
|
if (!error) {
|
||||||
|
await getAlerts()
|
||||||
|
message.success(`成功删除${deleteCount}条记录`)
|
||||||
|
} else {
|
||||||
|
message.error('删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onBatchDelete = () => {
|
||||||
|
if (selectedRowKeys.value.length === 0) {
|
||||||
|
message.warning('请先选择要删除的记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定要删除选中的 ${selectedRowKeys.value.length} 条记录吗?`,
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => onDelete(selectedRowKeys.value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch([dateRange, statusTab, typeTab, selectedSiteId], () => {
|
||||||
|
pageNum.value = 1
|
||||||
|
getAlerts()
|
||||||
|
})
|
||||||
|
|
||||||
|
const rowSelection = {
|
||||||
|
selectedRowKeys: selectedRowKeys,
|
||||||
|
onChange: (keys: string[]) => {
|
||||||
|
selectedRowKeys.value = keys
|
||||||
|
},
|
||||||
|
type: 'checkbox'
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getSiteList()
|
||||||
|
await getAlerts()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- 一级Tab + 时间控件 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||||
|
<div style="flex: 1; min-width: 0;">
|
||||||
|
<a-tabs v-model:activeKey="activeMainTab" style="margin-bottom: 0;">
|
||||||
|
<a-tab-pane key="Alerts" tab="Alerts" />
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
<a-range-picker
|
||||||
|
v-model:value="dateRange"
|
||||||
|
show-time
|
||||||
|
:allowClear="false"
|
||||||
|
style="margin-left: 16px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 二级分组 + 站点选择 + 操作按钮 -->
|
||||||
|
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px;">
|
||||||
|
<div style="display: flex; align-items: center;">
|
||||||
|
<a-radio-group v-model:value="statusTab" style="margin-right: 16px;">
|
||||||
|
<a-radio-button value="Unresolved">Unresolved</a-radio-button>
|
||||||
|
<a-radio-button value="Resolved">Resolved</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-radio-group v-model:value="typeTab" style="margin-right: 16px;">
|
||||||
|
<a-radio-button value="All">All</a-radio-button>
|
||||||
|
<a-radio-button value="System">System</a-radio-button>
|
||||||
|
<a-radio-button value="Device">Device</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-select
|
||||||
|
v-model:value="selectedSiteId"
|
||||||
|
:loading="siteLoading"
|
||||||
|
placeholder="请选择站点"
|
||||||
|
style="width: 200px; margin-right: 16px;"
|
||||||
|
@change="handleSiteChange"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="site in siteList" :key="site.siteId" :value="site.siteId">
|
||||||
|
{{ site.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a-button @click="onBatchDelete">Batch Delete</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<a-table
|
||||||
|
:dataSource="alerts"
|
||||||
|
:rowSelection="rowSelection"
|
||||||
|
:pagination="false"
|
||||||
|
:rowKey="record => record.id"
|
||||||
|
bordered
|
||||||
|
size="middle"
|
||||||
|
>
|
||||||
|
<a-table-column title="TYPE" dataIndex="key" key="key" />
|
||||||
|
<a-table-column title="LEVEL" dataIndex="level" key="level">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<span>
|
||||||
|
<span :style="{
|
||||||
|
color: record.level === 'Critical' ? 'red' :
|
||||||
|
record.level === 'Error' ? 'orange' :
|
||||||
|
record.level === 'Warning' ? '#faad14' :
|
||||||
|
record.level === 'Info' ? '#52c41a' : '#d9d9d9',
|
||||||
|
fontSize: '16px'
|
||||||
|
}">●</span>
|
||||||
|
<span style="margin-left: 4px;">{{ record.level }}</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="CONTENT" dataIndex="content" key="content" />
|
||||||
|
<a-table-column title="TIME" dataIndex="time" key="time">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<span>{{ record.time ? dayjs(record.time).format('YYYY-MM-DD HH:mm:ss') : '' }}</span>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="ACTION" key="action" width="120">
|
||||||
|
<template #default="{ record }">
|
||||||
|
<div style="display: flex; gap: 8px; justify-content: center;">
|
||||||
|
<!-- 未解决状态显示解决按钮 -->
|
||||||
|
<a-tooltip v-if="statusTab === 'Unresolved'" title="标记为已解决">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
style="color: #52c41a"
|
||||||
|
@click="onResolve(record.id)"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<ToolOutlined />
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<!-- 所有状态都显示删除按钮 -->
|
||||||
|
<a-tooltip title="删除">
|
||||||
|
<a-button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
style="color: #ff4d4f"
|
||||||
|
@click="() => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除该条告警记录吗?',
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => onDelete(record.id)
|
||||||
|
})
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<DeleteOutlined />
|
||||||
|
</template>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table-column>
|
||||||
|
</a-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div style="display: flex; justify-content: flex-end; margin-top: 16px;">
|
||||||
|
<a-pagination :total="total" :pageSize="pageSize" :current="pageNum" showQuickJumper @change="(p, ps) => { pageNum = p; pageSize = ps; getAlerts(); }" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 可根据实际需求自定义样式 */
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user