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