fix
This commit is contained in:
@@ -60,7 +60,12 @@
|
||||
:data="data"
|
||||
:bordered="bordered"
|
||||
:size="size"
|
||||
:row-selection="rowSelection"
|
||||
:scroll="scroll"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
@selection-change="onSelectionChange"
|
||||
@row-click="onRowClick"
|
||||
>
|
||||
<!-- 动态插槽:根据 columns 的 slotName 动态渲染 -->
|
||||
<template v-for="col in slotColumns" :key="col.dataIndex" #[String(col.slotName)]="slotProps">
|
||||
@@ -72,7 +77,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch, nextTick, onUnmounted, PropType } from 'vue'
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'
|
||||
import type { TableColumnData, TableRowSelection } from '@arco-design/web-vue/es/table/interface'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
@@ -107,6 +112,14 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
rowSelection: {
|
||||
type: Object as PropType<TableRowSelection | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
scroll: {
|
||||
type: Object as PropType<{ x?: number | string; y?: number | string } | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
showToolbar: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@@ -147,6 +160,9 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'page-change', current: number): void
|
||||
(e: 'page-size-change', pageSize: number): void
|
||||
(e: 'selection-change', rowKeys: (string | number)[]): void
|
||||
(e: 'row-click', record: any, ev: Event): void
|
||||
(e: 'refresh'): void
|
||||
(e: 'download'): void
|
||||
(e: 'density-change', size: SizeProps): void
|
||||
@@ -178,6 +194,18 @@ const onPageChange = (current: number) => {
|
||||
emit('page-change', current)
|
||||
}
|
||||
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
emit('page-size-change', pageSize)
|
||||
}
|
||||
|
||||
const onSelectionChange = (rowKeys: (string | number)[]) => {
|
||||
emit('selection-change', rowKeys)
|
||||
}
|
||||
|
||||
const onRowClick = (record: any, ev: Event) => {
|
||||
emit('row-click', record, ev)
|
||||
}
|
||||
|
||||
const handleRefresh = () => {
|
||||
emit('refresh')
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:bordered="bordered"
|
||||
:row-selection="rowSelection"
|
||||
:scroll="scroll"
|
||||
:show-toolbar="showToolbar"
|
||||
:show-download="showDownload"
|
||||
:show-refresh="showRefresh"
|
||||
@@ -36,6 +38,9 @@
|
||||
:density-tooltip-text="densityTooltipText"
|
||||
:column-setting-tooltip-text="columnSettingTooltipText"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-click="handleRowClick"
|
||||
@refresh="handleRefresh"
|
||||
@download="handleDownload"
|
||||
@density-change="handleDensityChange"
|
||||
@@ -61,7 +66,7 @@ import { computed, PropType } from 'vue'
|
||||
import SearchForm from '../search-form/index.vue'
|
||||
import type { FormItem } from '../search-form/types'
|
||||
import DataTable from '../data-table/index.vue'
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'
|
||||
import type { TableColumnData, TableRowSelection } from '@arco-design/web-vue/es/table/interface'
|
||||
|
||||
type SizeProps = 'mini' | 'small' | 'medium' | 'large'
|
||||
|
||||
@@ -115,6 +120,14 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
rowSelection: {
|
||||
type: Object as PropType<TableRowSelection | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
scroll: {
|
||||
type: Object as PropType<{ x?: number | string; y?: number | string } | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
// 工具栏相关
|
||||
showToolbar: {
|
||||
type: Boolean,
|
||||
@@ -164,6 +177,9 @@ const emit = defineEmits<{
|
||||
(e: 'search'): void
|
||||
(e: 'reset'): void
|
||||
(e: 'page-change', current: number): void
|
||||
(e: 'page-size-change', pageSize: number): void
|
||||
(e: 'selection-change', rowKeys: (string | number)[]): void
|
||||
(e: 'row-click', record: any, ev: Event): void
|
||||
(e: 'refresh'): void
|
||||
(e: 'download'): void
|
||||
(e: 'density-change', size: SizeProps): void
|
||||
@@ -192,6 +208,18 @@ const handlePageChange = (current: number) => {
|
||||
emit('page-change', current)
|
||||
}
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
emit('page-size-change', pageSize)
|
||||
}
|
||||
|
||||
const handleSelectionChange = (rowKeys: (string | number)[]) => {
|
||||
emit('selection-change', rowKeys)
|
||||
}
|
||||
|
||||
const handleRowClick = (record: any, ev: Event) => {
|
||||
emit('row-click', record, ev)
|
||||
}
|
||||
|
||||
const handleRefresh = () => {
|
||||
emit('refresh')
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="notice-channel-container">
|
||||
<SearchTable
|
||||
v-model:form-model="formModel"
|
||||
<div class="container">
|
||||
<search-table
|
||||
:form-model="formModel"
|
||||
:form-items="formItems"
|
||||
:data="tableData"
|
||||
:columns="columns"
|
||||
@@ -10,6 +10,10 @@
|
||||
title="通知渠道管理"
|
||||
search-button-text="查询"
|
||||
reset-button-text="重置"
|
||||
refresh-tooltip-text="刷新数据"
|
||||
density-tooltip-text="表格密度"
|
||||
column-setting-tooltip-text="列设置"
|
||||
@update:form-model="handleFormModelUpdate"
|
||||
@search="handleSearch"
|
||||
@reset="handleReset"
|
||||
@page-change="handlePageChange"
|
||||
@@ -56,7 +60,7 @@
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</SearchTable>
|
||||
</search-table>
|
||||
|
||||
<!-- 表单对话框 -->
|
||||
<channel-form-dialog
|
||||
@@ -95,12 +99,15 @@ const pagination = reactive({
|
||||
total: 0,
|
||||
})
|
||||
|
||||
// 搜索表单数据
|
||||
const formModel = ref<Record<string, any>>({
|
||||
name: '',
|
||||
type: '',
|
||||
})
|
||||
|
||||
const handleFormModelUpdate = (value: Record<string, any>) => {
|
||||
formModel.value = value
|
||||
}
|
||||
|
||||
// 表单项配置
|
||||
const formItems = computed<FormItem[]>(() => [
|
||||
{
|
||||
@@ -240,9 +247,9 @@ const handlePageChange = (current: number) => {
|
||||
fetchList()
|
||||
}
|
||||
|
||||
// 刷新
|
||||
const handleRefresh = () => {
|
||||
fetchList()
|
||||
Message.success('数据已刷新')
|
||||
}
|
||||
|
||||
// 新建
|
||||
@@ -292,7 +299,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.notice-channel-container {
|
||||
padding: 0 20px 20px 20px;
|
||||
.container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
:data="dispatchRuleData"
|
||||
:pagination="false"
|
||||
:bordered="true"
|
||||
size="small"
|
||||
size="medium"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="告警级别" data-index="severity" :width="150">
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
:loading="ruleLoading"
|
||||
:pagination="rulePagination"
|
||||
:bordered="true"
|
||||
size="small"
|
||||
size="medium"
|
||||
@page-change="handlePageChange"
|
||||
>
|
||||
<template #columns>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
:data="processRecords"
|
||||
:columns="processColumns"
|
||||
:pagination="false"
|
||||
size="small"
|
||||
size="medium"
|
||||
>
|
||||
<template #action="{ record }">
|
||||
<a-tag :color="getActionColor(record.action)">
|
||||
|
||||
@@ -1,188 +1,144 @@
|
||||
<template>
|
||||
<div class="alert-tackle-container">
|
||||
<a-card :bordered="false" class="general-card">
|
||||
<search-form
|
||||
v-model="searchParams"
|
||||
:form-items="searchFormConfig"
|
||||
:show-buttons="false"
|
||||
>
|
||||
<template #extra>
|
||||
<a-range-picker
|
||||
v-model="timeRange"
|
||||
:time-picker-props="{ defaultValue: '00:00:00' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
style="width: 380px; margin-right: 12px"
|
||||
/>
|
||||
<a-button type="primary" @click="handleSearch">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
查询
|
||||
</a-button>
|
||||
<a-button @click="handleReset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
</template>
|
||||
</search-form>
|
||||
|
||||
<a-divider style="margin: 0" />
|
||||
|
||||
<a-row class="toolbar">
|
||||
<a-col :span="12">
|
||||
<a-space>
|
||||
<a-button
|
||||
v-if="selectedRowKeys.length > 0"
|
||||
type="primary"
|
||||
status="danger"
|
||||
@click="handleBatchAck"
|
||||
>
|
||||
批量确认 ({{ selectedRowKeys.length }})
|
||||
</a-button>
|
||||
</a-space>
|
||||
<div class="container">
|
||||
<search-table
|
||||
:form-model="formModel"
|
||||
:form-items="formItems"
|
||||
:data="tableData"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
title="告警受理处理"
|
||||
search-button-text="查询"
|
||||
reset-button-text="重置"
|
||||
refresh-tooltip-text="刷新数据"
|
||||
density-tooltip-text="表格密度"
|
||||
column-setting-tooltip-text="列设置"
|
||||
@update:form-model="handleFormModelUpdate"
|
||||
@search="handleSearch"
|
||||
@reset="handleReset"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@row-click="handleRowClick"
|
||||
@refresh="handleRefresh"
|
||||
>
|
||||
<template #form-items>
|
||||
<a-col :span="16">
|
||||
<a-form-item
|
||||
label="时间范围"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 18 }"
|
||||
>
|
||||
<a-range-picker
|
||||
v-model="timeRange"
|
||||
:time-picker-props="{ defaultValue: '00:00:00' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
show-time
|
||||
style="width: 100%; max-width: 420px"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<a-table
|
||||
:data="tableData"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-selection="rowSelection"
|
||||
:scroll="{ x: 2000 }"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-click="handleRowClick"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 }}
|
||||
</template>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
|
||||
</template>
|
||||
|
||||
<template #status="{ record }">
|
||||
<a-tag :color="getStatusColor(record.status)">
|
||||
{{ getStatusText(record.status) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
<a-tag :color="getStatusColor(record.status)">
|
||||
{{ getStatusText(record.status) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template #severity="{ record }">
|
||||
<a-tag v-if="record.severity" :color="record.severity.color">
|
||||
{{ record.severity.name || record.severity.code }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #severity="{ record }">
|
||||
<a-tag v-if="record.severity" :color="record.severity.color">
|
||||
{{ record.severity.name || record.severity.code }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template #starts_at="{ record }">
|
||||
{{ formatDateTime(record.starts_at) }}
|
||||
</template>
|
||||
<template #starts_at="{ record }">
|
||||
{{ formatDateTime(record.starts_at) }}
|
||||
</template>
|
||||
|
||||
<template #duration="{ record }">
|
||||
{{ formatDuration(record.duration) }}
|
||||
</template>
|
||||
<template #duration="{ record }">
|
||||
{{ formatDuration(record.duration) }}
|
||||
</template>
|
||||
|
||||
<template #process_status="{ record }">
|
||||
<a-tag v-if="record.process_status" color="arcoblue">
|
||||
{{ record.process_status }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #process_status="{ record }">
|
||||
<a-tag v-if="record.process_status" color="arcoblue">
|
||||
{{ record.process_status }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #processed_at="{ record }">
|
||||
{{ record.processed_at ? formatDateTime(record.processed_at) : '-' }}
|
||||
</template>
|
||||
<template #processed_at="{ record }">
|
||||
{{ record.processed_at ? formatDateTime(record.processed_at) : '-' }}
|
||||
</template>
|
||||
|
||||
<template #notify_status="{ record }">
|
||||
<a-tag v-if="record.notify_status" :color="getNotifyStatusColor(record.notify_status)">
|
||||
{{ getNotifyStatusText(record.notify_status) }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #notify_status="{ record }">
|
||||
<a-tag v-if="record.notify_status" :color="getNotifyStatusColor(record.notify_status)">
|
||||
{{ getNotifyStatusText(record.notify_status) }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #labels="{ record }">
|
||||
<a-space v-if="parsedLabels(record.labels)" wrap>
|
||||
<a-tag
|
||||
v-for="(value, key) in parsedLabels(record.labels)"
|
||||
:key="key"
|
||||
size="small"
|
||||
>
|
||||
{{ key }}: {{ value }}
|
||||
</a-tag>
|
||||
</a-space>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #labels="{ record }">
|
||||
<a-tooltip v-if="formatLabelsLine(record.labels)" :content="formatLabelsLine(record.labels)">
|
||||
<span class="cell-ellipsis">{{ formatLabelsLine(record.labels) }}</span>
|
||||
</a-tooltip>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #actions="{ record }">
|
||||
<a-space>
|
||||
<a-button type="text" size="small" @click="handleAck(record)">
|
||||
<template #icon>
|
||||
<icon-check />
|
||||
</template>
|
||||
确认
|
||||
<template #actions="{ record }">
|
||||
<a-space size="small" :wrap="false">
|
||||
<a-button type="text" size="small" @click.stop="handleAck(record)">
|
||||
确认
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click.stop="handleResolve(record)">
|
||||
解决
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click.stop="handleSilence(record)">
|
||||
屏蔽
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click.stop="handleComment(record)">
|
||||
评论
|
||||
</a-button>
|
||||
<a-dropdown @select="(v) => handleMoreSelect(v, record)">
|
||||
<a-button type="text" size="small" @click.stop>
|
||||
更多
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="handleResolve(record)">
|
||||
<template #icon>
|
||||
<icon-check-circle />
|
||||
</template>
|
||||
解决
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="handleSilence(record)">
|
||||
<template #icon>
|
||||
<icon-eye-invisible />
|
||||
</template>
|
||||
屏蔽
|
||||
</a-button>
|
||||
<a-button type="text" size="small" @click="handleComment(record)">
|
||||
<template #icon>
|
||||
<icon-message />
|
||||
</template>
|
||||
评论
|
||||
</a-button>
|
||||
<a-dropdown @select="handleMoreAction($event, record)">
|
||||
<a-button type="text" size="small">
|
||||
更多
|
||||
<icon-down />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption value="detail">详情</a-doption>
|
||||
<a-doption value="process">处理记录</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
<template #content>
|
||||
<a-doption value="detail">详情</a-doption>
|
||||
<a-doption value="process">处理记录</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</template>
|
||||
</search-table>
|
||||
|
||||
<!-- 确认对话框 -->
|
||||
<ack-dialog
|
||||
v-model:visible="ackDialogVisible"
|
||||
:alert-record-id="currentRecord.id"
|
||||
@success="handleSuccess"
|
||||
/>
|
||||
|
||||
<!-- 解决对话框 -->
|
||||
<resolve-dialog
|
||||
v-model:visible="resolveDialogVisible"
|
||||
:alert-record-id="currentRecord.id"
|
||||
@success="handleSuccess"
|
||||
/>
|
||||
|
||||
<!-- 屏蔽对话框 -->
|
||||
<silence-dialog
|
||||
v-model:visible="silenceDialogVisible"
|
||||
:alert-record-id="currentRecord.id"
|
||||
@success="handleSuccess"
|
||||
/>
|
||||
|
||||
<!-- 评论对话框 -->
|
||||
<comment-dialog
|
||||
v-model:visible="commentDialogVisible"
|
||||
:alert-record-id="currentRecord.id"
|
||||
@success="handleSuccess"
|
||||
/>
|
||||
|
||||
<!-- 详情对话框 -->
|
||||
<detail-dialog
|
||||
v-model:visible="detailDialogVisible"
|
||||
:alert-record-id="currentRecord.id"
|
||||
@@ -193,21 +149,13 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import {
|
||||
IconSearch,
|
||||
IconRefresh,
|
||||
IconCheck,
|
||||
IconCheckCircle,
|
||||
IconEyeInvisible,
|
||||
IconMessage,
|
||||
IconDown,
|
||||
} from '@arco-design/web-vue/es/icon'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import SearchForm from '@/components/search-form/index.vue'
|
||||
import type { FormItem } from '@/components/search-form/types'
|
||||
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface'
|
||||
import SearchTable from '@/components/search-table/index.vue'
|
||||
import { searchFormConfig } from './config/search-form'
|
||||
import { columns } from './config/columns'
|
||||
import { fetchAlertRecords, createAlertProcess } from '@/api/ops/alertRecord'
|
||||
import { fetchAlertRecords } from '@/api/ops/alertRecord'
|
||||
import { fetchAlertLevelList } from '@/api/ops/alertLevel'
|
||||
|
||||
import AckDialog from './components/AckDialog.vue'
|
||||
@@ -218,21 +166,17 @@ import DetailDialog from './components/DetailDialog.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// 状态管理
|
||||
const loading = ref(false)
|
||||
const tableData = ref<any[]>([])
|
||||
const timeRange = ref<any[]>([])
|
||||
const selectedRowKeys = ref<number[]>([])
|
||||
const currentRecord = ref<any>({})
|
||||
|
||||
// 对话框状态
|
||||
const ackDialogVisible = ref(false)
|
||||
const resolveDialogVisible = ref(false)
|
||||
const silenceDialogVisible = ref(false)
|
||||
const commentDialogVisible = ref(false)
|
||||
const detailDialogVisible = ref(false)
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 20,
|
||||
@@ -242,16 +186,23 @@ const pagination = reactive({
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
})
|
||||
|
||||
// 行选择
|
||||
const rowSelection = computed(() => ({
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
}))
|
||||
const severityOptions = ref<SelectOptionData[]>([])
|
||||
|
||||
// 搜索参数
|
||||
const searchParams = ref<any>({})
|
||||
const formModel = ref<Record<string, any>>({
|
||||
keyword: '',
|
||||
status: '',
|
||||
severity_id: '',
|
||||
})
|
||||
|
||||
const formItems = computed<FormItem[]>(() =>
|
||||
searchFormConfig.map((item) => {
|
||||
if (item.field === 'severity_id') {
|
||||
return { ...item, options: severityOptions.value }
|
||||
}
|
||||
return item
|
||||
}),
|
||||
)
|
||||
|
||||
// 加载告警级别列表
|
||||
onMounted(async () => {
|
||||
await loadSeverityOptions()
|
||||
handleSearch()
|
||||
@@ -259,51 +210,58 @@ onMounted(async () => {
|
||||
|
||||
const loadSeverityOptions = async () => {
|
||||
try {
|
||||
const result = await fetchAlertLevelList({ page: 1, page_size: 100 })
|
||||
const severityConfig = searchFormConfig.find((item) => item.field === 'severity_id')
|
||||
if (severityConfig && result.details) {
|
||||
severityConfig.options = result.data.map((item: any) => ({
|
||||
label: item.name || item.code,
|
||||
value: item.id,
|
||||
}))
|
||||
}
|
||||
const res = await fetchAlertLevelList({ page: 1, page_size: 100 })
|
||||
const list = res.details?.data ?? (res as any).data ?? []
|
||||
severityOptions.value = list.map((item: any) => ({
|
||||
label: item.name || item.code,
|
||||
value: item.id,
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载告警级别失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleFormModelUpdate = (value: Record<string, any>) => {
|
||||
formModel.value = value
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
pagination.current = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
formModel.value = {
|
||||
keyword: '',
|
||||
status: '',
|
||||
severity_id: '',
|
||||
}
|
||||
timeRange.value = []
|
||||
searchParams.value = {}
|
||||
pagination.current = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params: any = {
|
||||
page: pagination.current,
|
||||
page_size: pagination.pageSize,
|
||||
...searchParams.value,
|
||||
keyword: formModel.value.keyword || undefined,
|
||||
status: formModel.value.status || undefined,
|
||||
}
|
||||
if (formModel.value.severity_id !== '' && formModel.value.severity_id != null) {
|
||||
params.severity_id = formModel.value.severity_id
|
||||
}
|
||||
|
||||
// 处理时间范围
|
||||
if (timeRange.value && timeRange.value.length === 2) {
|
||||
params.start_time = new Date(timeRange.value[0]).toISOString()
|
||||
params.end_time = new Date(timeRange.value[1]).toISOString()
|
||||
}
|
||||
|
||||
const result = await fetchAlertRecords(params)
|
||||
tableData.value = result.details.data || []
|
||||
pagination.total = result.details.total || 0
|
||||
tableData.value = result.details?.data || []
|
||||
pagination.total = result.details?.total || 0
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
Message.error('加载数据失败')
|
||||
@@ -312,30 +270,22 @@ const loadData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
const onPageChange = (page: number) => {
|
||||
const handlePageChange = (page: number) => {
|
||||
pagination.current = page
|
||||
loadData()
|
||||
}
|
||||
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.pageSize = pageSize
|
||||
pagination.current = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 行选择
|
||||
const handleSelectionChange = (rowKeys: number[]) => {
|
||||
selectedRowKeys.value = rowKeys
|
||||
}
|
||||
|
||||
// 行点击
|
||||
const handleRowClick = (record: any) => {
|
||||
const handleRowClick = (record: any, _ev: Event) => {
|
||||
currentRecord.value = record
|
||||
detailDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 处理操作
|
||||
const handleAck = (record: any) => {
|
||||
currentRecord.value = record
|
||||
ackDialogVisible.value = true
|
||||
@@ -356,28 +306,6 @@ const handleComment = (record: any) => {
|
||||
commentDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 批量确认
|
||||
const handleBatchAck = async () => {
|
||||
try {
|
||||
const promises = selectedRowKeys.value.map((id) =>
|
||||
createAlertProcess({
|
||||
alert_record_id: id,
|
||||
action: 'ack',
|
||||
operator: getCurrentUser(),
|
||||
comment: '批量确认',
|
||||
})
|
||||
)
|
||||
await Promise.all(promises)
|
||||
Message.success(`成功确认 ${selectedRowKeys.value.length} 条告警`)
|
||||
selectedRowKeys.value = []
|
||||
loadData()
|
||||
} catch (error) {
|
||||
console.error('批量确认失败:', error)
|
||||
Message.error('批量确认失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 更多操作
|
||||
const handleMoreAction = (action: string, record: any) => {
|
||||
currentRecord.value = record
|
||||
switch (action) {
|
||||
@@ -393,12 +321,22 @@ const handleMoreAction = (action: string, record: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 操作成功回调
|
||||
const handleMoreSelect = (
|
||||
value: string | number | Record<string, unknown> | undefined,
|
||||
record: any,
|
||||
) => {
|
||||
handleMoreAction(String(value), record)
|
||||
}
|
||||
|
||||
const handleSuccess = () => {
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 格式化函数
|
||||
const handleRefresh = () => {
|
||||
loadData()
|
||||
Message.success('数据已刷新')
|
||||
}
|
||||
|
||||
const formatDateTime = (datetime: string) => {
|
||||
if (!datetime) return '-'
|
||||
return new Date(datetime).toLocaleString('zh-CN')
|
||||
@@ -424,7 +362,15 @@ const parsedLabels = (labels: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 状态相关
|
||||
/** 单行展示,避免 a-space wrap + 多 tag 撑高整行 td(与其它告警列表页行高一致) */
|
||||
const formatLabelsLine = (labels: string) => {
|
||||
const obj = parsedLabels(labels)
|
||||
if (!obj || typeof obj !== 'object') return ''
|
||||
return Object.entries(obj as Record<string, unknown>)
|
||||
.map(([k, v]) => `${k}: ${v == null ? '' : String(v)}`)
|
||||
.join(', ')
|
||||
}
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
const colorMap: Record<string, string> = {
|
||||
firing: 'red',
|
||||
@@ -466,23 +412,35 @@ const getNotifyStatusText = (status: string) => {
|
||||
}
|
||||
return textMap[status] || status
|
||||
}
|
||||
</script>
|
||||
|
||||
function getCurrentUser() {
|
||||
// TODO: 从全局状态获取当前用户
|
||||
return 'admin'
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'AlertTackle',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.alert-tackle-container {
|
||||
padding: 20px;
|
||||
.container {
|
||||
margin-top: 20px;
|
||||
|
||||
.general-card {
|
||||
padding: 20px;
|
||||
/* 与未设置 table scroll 的告警列表页一致行高;宽表在表格外层横向滚动,避免 Arco scroll 模式改变单元格高度 */
|
||||
:deep(.search-table-container .data-table) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
padding: 16px 0;
|
||||
/* 标签列单行省略,与其它页纯文本单元格行高一致 */
|
||||
.cell-ellipsis {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
/* 与其它告警 SearchTable 页一致:正文单元格垂直居中 */
|
||||
:deep(.arco-table-size-medium .arco-table-td) {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user