This commit is contained in:
zxr
2026-03-21 17:39:39 +08:00
parent 6ac9550133
commit 2c3195b903
7 changed files with 265 additions and 244 deletions

View File

@@ -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')
} }

View File

@@ -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')
} }

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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)">

View File

@@ -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>