2
0

feat:白名单和告警界面中英适配

This commit is contained in:
zhongzm
2025-06-19 12:27:23 +08:00
parent e8c98e77d3
commit abda1ebe54
4 changed files with 167 additions and 68 deletions

View File

@@ -893,6 +893,54 @@ const local: any = {
deleteConfirmContent: 'Sure to delete portal {name} ',
deleteSuccess: 'Delete success'
},
alerts:{
alerts:'Alerts',
choosesite: 'Please select a site',
deletesuccess: 'Delete successful',
deletefail: 'Delete failed',
choserecord: 'Please select the record to operate on',
deletetitle: 'Confirm deletion',
deletebody: 'record(s)?',
suredelete: 'Are you sure you want to delete this alarm record?',
sure: 'Confirm',
cancel: 'Cancel',
unresolved: 'Unresolved',
resolved: 'Resolved',
all: 'All',
system: 'System',
device: 'Device',
batchdelete: 'Batch delete',
resovetitle: 'Mark as resolved',
delete: 'Delete',
type:'TYPE',
level:'LEVEL',
content:'CONTENT',
time:'TIME',
action:'ACTION',
},
access:{
title:'Access Control',
plesite:'please select site',
authaccess:'Pre-Authentication Access',
enable:'Enable',
authaccesslist:'Pre-Authentication Access List',
delete:'Delete',
authclient:'Authentication-Free Client',
authclientlist:'Authentication-Free Client List',
apply:'Apply',
cancel:'Cancel',
type:'TYPE',
pleurl:'Please select URL',
addauth:'Add Pre-Authentication Access',
addclient:'Add Authentication-Free Client',
add:'Add',
info:'INFORMATION',
action:'ACTION',
deletetitle:'Delete',
deletebody:'Are you sure you want to delete this record?',
ok:'confirm',
},
terminal:{
title:'Terminal',
total:'Total',

View File

@@ -894,6 +894,53 @@ const local:any = {
deleteConfirmContent: '确定要删除门户 {name} 吗?',
deleteSuccess: '删除成功'
},
alerts:{
alerts:'告警',
chosesite:'请选择站点',
deletesuccess:'删除成功',
deletefail:'删除失败',
choserecord:'请选择需要操作的记录',
deletetitle:'确认删除',
deletebody:'条记录吗?',
suredelete:'确定要删除该条告警记录吗?',
sure:'确定',
cancel:'取消',
unresolved:'未解决',
resolved:'已解决',
all:'全部',
system:'系统',
device:'设备',
batchdelete:'批量删除',
resovetitle:'标记为已解决',
delete:'删除',
type:'类型',
level:'等级',
content:'说明',
time:'时间',
action:'操作',
},
access:{
title:'白名单控制',
plesite:'请选择站点',
authaccess:'预认证访问',
enable:'开启',
authaccesslist:'预认证访问列表',
delete:'删除',
authclient:'免认证客户端',
authclientlist:'免认证客户端列表',
apply:'提交',
cancel:'取消',
type:'类型',
pleurl:'请输入URL',
addauth:'添加预认证访问',
addclient:'添加免认证客户端',
add:'添加',
info:'信息',
action:'操作',
deletetitle:'确认删除',
deletebody:'确定要删除这条记录吗?',
ok:'确认',
},
terminal:{
title:'终端设备',
total:'共',

View File

@@ -6,13 +6,13 @@
>
<div>
<!-- 标题 -->
<h2 style="font-weight: bold; font-size: 22px; margin-bottom: 8px;">Access Control</h2>
<h2 style="font-weight: bold; font-size: 22px; margin-bottom: 8px;">{{ t('page.access.title') }}</h2>
<!-- 站点选择框 -->
<div style="display: flex; align-items: center; margin-bottom: 24px;">
<a-select
v-model:value="selectedSiteId"
:loading="siteLoading"
placeholder="请选择站点"
:placeholder="t('page.access.plesite')"
style="width: 200px; margin-right: 16px;"
@change="handleSiteChange"
>
@@ -24,17 +24,18 @@
<!-- Pre-Authentication Access -->
<div style="margin-bottom: 16px; display: flex; align-items: center; gap: 12px;">
<span>Pre-Authentication Access</span>
<span>{{ t('page.access.authaccess') }}</span>
<a-switch v-model:checked="preAuthEnabled" />
<span>Enable</span>
<span>{{ t('page.access.enable') }}</span>
<a-tooltip title="Pre-Authentication Access 说明">
<i class="anticon anticon-info-circle" style="color: #13c2c2; margin-left: 4px;"></i>
</a-tooltip>
</div>
<div v-if="preAuthEnabled">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
<span>Pre-Authentication Access List</span>
<a-button type="link" style="color: #13c2c2; font-weight: bold;" @click="onAddPreAuth"><i class="anticon anticon-plus-circle" /> Add</a-button>
<span>{{ t('page.access.authaccesslist') }}</span>
<a-button type="link" style="color: #13c2c2; font-weight: bold;" @click="onAddPreAuth"><i class="anticon anticon-plus-circle" />
{{ t('page.access.add') }}</a-button>
</div>
<a-table
:columns="preAuthColumns"
@@ -46,7 +47,7 @@
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-tooltip title="删除">
<a-tooltip :title="t('page.access.delete')">
<a-button
type="link"
size="small"
@@ -65,17 +66,18 @@
<!-- Authentication-Free Client -->
<div style="margin: 32px 0 16px 0; display: flex; align-items: center; gap: 12px;">
<span>Authentication-Free Client</span>
<span>{{ t('page.access.authclient') }}</span>
<a-switch v-model:checked="freeClientEnabled" />
<span>Enable</span>
<span>{{ t('page.access.enable') }}</span>
<a-tooltip title="Authentication-Free Client 说明">
<i class="anticon anticon-info-circle" style="color: #13c2c2; margin-left: 4px;"></i>
</a-tooltip>
</div>
<div v-if="freeClientEnabled">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
<span>Authentication-Free Client List</span>
<a-button type="link" style="color: #13c2c2; font-weight: bold;" @click="onAddFreeClient"><i class="anticon anticon-plus-circle" /> Add</a-button>
<span>{{ t('page.access.authclientlist') }}</span>
<a-button type="link" style="color: #13c2c2; font-weight: bold;" @click="onAddFreeClient"><i class="anticon anticon-plus-circle" />
{{ t('page.access.add') }}</a-button>
</div>
<a-table
:columns="freeClientColumns"
@@ -87,7 +89,7 @@
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-tooltip title="删除">
<a-tooltip :title="t('page.access.delete')">
<a-button
type="link"
size="small"
@@ -106,15 +108,15 @@
<!-- 操作按钮 -->
<div style="margin-top: 32px; display: flex; gap: 16px;">
<a-button type="primary" @click="handleApply">Apply</a-button>
<a-button @click="handleCancel">Cancel</a-button>
<a-button type="primary" @click="handleApply">{{ t('page.access.apply') }}</a-button>
<a-button @click="handleCancel">{{ t('page.access.cancel') }}</a-button>
</div>
</div>
</a-card>
<!-- 新增添加预认证白名单弹窗 -->
<a-modal
v-model:visible="addPreAuthVisible"
title="Add Pre-Authentication Access"
:title="t('page.access.addauth')"
@ok="handleAddPreAuthOk"
@cancel="() => addPreAuthVisible = false"
destroyOnClose
@@ -150,7 +152,7 @@
<!-- 新增添加免认证白名单弹窗 -->
<a-modal
v-model:visible="addFreeClientVisible"
title="Add Authentication-Free Client"
:title="t('page.access.addclient')"
@ok="handleAddFreeClientOk"
@cancel="() => addFreeClientVisible = false"
destroyOnClose
@@ -199,6 +201,8 @@ import { fetchSiteList, fetchAccessControl, updateAccessControl } from '@/servic
import { DeleteOutlined } from '@ant-design/icons-vue'
import { message, Modal } from 'ant-design-vue'
import { SimpleScrollbar } from '~/packages/materials/src';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const preAuthEnabled = ref(true)
const freeClientEnabled = ref(true)
const preAuthList = ref([]) // 预认证白名单列表
@@ -223,7 +227,7 @@ const addFreeClientMacParts = ref(['', '', '', '', '', ''])
// 定义表格列配置
const preAuthColumns = [
{
title: 'TYPE',
title: t('page.access.type'),
dataIndex: 'type',
key: 'type',
customRender: ({ record }: { record: any }) => {
@@ -233,7 +237,7 @@ const preAuthColumns = [
}
},
{
title: 'INFORMATION',
title: t('page.access.info'),
dataIndex: 'url',
key: 'url',
customRender: ({ record }: { record: any }) => {
@@ -243,7 +247,7 @@ const preAuthColumns = [
}
},
{
title: 'ACTION',
title: t('page.access.action'),
key: 'action',
width: 120,
fixed: 'right',
@@ -267,7 +271,7 @@ const preAuthColumns = [
const freeClientColumns = [
{
title: 'TYPE',
title: t('page.access.type'),
dataIndex: 'type',
key: 'type',
customRender: ({ record }: { record: any }) => {
@@ -277,7 +281,7 @@ const freeClientColumns = [
}
},
{
title: 'INFORMATION',
title: t('page.access.info'),
dataIndex: 'clientIp',
key: 'clientIp',
customRender: ({ record }: { record: any }) => {
@@ -287,7 +291,7 @@ const freeClientColumns = [
}
},
{
title: 'ACTION',
title: t('page.access.action'),
key: 'action',
width: 120,
fixed: 'right',
@@ -423,10 +427,10 @@ const handleAddFreeClientOk = () => {
const handleDeletePreAuth = (record: any) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该条记录吗?',
okText: '确认',
cancelText: '取消',
title: t('page.access.deletetitle'),
content: t('page.access.deletebody'),
okText: t('page.access.ok'),
cancelText: t('page.access.cancel'),
onOk: () => {
preAuthList.value = preAuthList.value.filter(item => item.key !== record.key)
}
@@ -435,10 +439,10 @@ const handleDeletePreAuth = (record: any) => {
const handleDeleteFreeClient = (record: any) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该条记录吗?',
okText: '确认',
cancelText: '取消',
title: t('page.access.deletetitle'),
content: t('page.access.deletebody'),
okText: t('page.access.ok'),
cancelText: t('page.access.cancel'),
onOk: () => {
freeClientList.value = freeClientList.value.filter(item => item.key !== record.key)
}
@@ -454,7 +458,7 @@ watch(selectedSiteId, (val) => {
// 在 script setup 中添加提交函数
const handleApply = async () => {
if (!selectedSiteId.value) {
message.warning('请先选择站点')
// message.warning('请先选择站点')
return
}
@@ -478,31 +482,31 @@ const handleApply = async () => {
// 调用更新接口
const { error } = await updateAccessControl(selectedSiteId.value, submitData)
if (error) {
message.error('提交失败')
// message.error('提交失败')
return
}
message.success('提交成功')
// message.success('提交成功')
// 重新获取最新数据
await getAccessControl()
} catch (e) {
console.error('提交出错:', e)
message.error('提交失败')
// message.error('提交失败')
}
}
// 在 script setup 中添加 Cancel 处理函数
const handleCancel = async () => {
if (!selectedSiteId.value) {
message.warning('请先选择站点')
// message.warning('请先选择站点')
return
}
try {
await getAccessControl()
message.success('已刷新数据')
// message.success('已刷新数据')
} catch (e) {
console.error('刷新数据出错:', e)
message.error('刷新数据失败')
// message.error('刷新数据失败')
}
}

View File

@@ -5,7 +5,8 @@ import dayjs from 'dayjs'
import { DeleteOutlined, ToolOutlined } from '@ant-design/icons-vue'
// 假设API与portal页面一致
import { fetchSiteList, fetchAlertList, deleteAlerts, markAlertsResolved } from '@/service/api/auth'
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const siteList = ref<{ siteId: string, name: string }[]>([])
const selectedSiteId = ref('')
const siteLoading = ref(false)
@@ -63,7 +64,7 @@ const handleSiteChange = async (value: string) => {
const onResolve = async (id: string | number) => {
if (!selectedSiteId.value) {
message.warning('请先选择站点')
message.warning(t('page.alerts.chosesite'))
return
}
const { error } = await markAlertsResolved(selectedSiteId.value, {
@@ -74,15 +75,14 @@ const onResolve = async (id: string | number) => {
})
if (!error) {
await getAlerts()
message.success('已标记为已解决')
} else {
message.error('标记失败')
// message.error('标记失败')
}
}
const onDelete = async (ids: number | number[]) => {
if (!selectedSiteId.value) {
message.warning('请先选择站点')
message.warning(t('page.alerts.chosesite'))
return
}
@@ -97,23 +97,23 @@ const onDelete = async (ids: number | number[]) => {
})
if (!error) {
await getAlerts()
message.success(`成功删除${deleteCount}条记录`)
// message.success(`成功删除${deleteCount}条记录`)
} else {
message.error('删除失败')
message.error(t('page.alerts.deletefail'))
}
}
const onBatchDelete = () => {
if (selectedRowKeys.value.length === 0) {
message.warning('请先选择要删除的记录')
message.warning(t('page.alerts.choserecord'))
return
}
Modal.confirm({
title: '确认删除',
content: `确定要删除选中的 ${selectedRowKeys.value.length} 条记录吗?`,
okText: '确认',
cancelText: '取消',
title: t('page.alerts.deletetitle'),
content: `${t('page.alerts.deletetitle')} ${selectedRowKeys.value.length} ${t('page.alerts.deletebody')}`,
okText: t('page.alerts.sure'),
cancelText: t('page.alerts.cancel'),
onOk: () => onDelete(selectedRowKeys.value)
})
}
@@ -143,7 +143,7 @@ onMounted(async () => {
<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-tab-pane key="Alerts" :tab="t('page.alerts.alerts')" />
</a-tabs>
</div>
<a-range-picker
@@ -158,18 +158,18 @@ onMounted(async () => {
<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-button value="Unresolved">{{ t('page.alerts.unresolved') }}</a-radio-button>
<a-radio-button value="Resolved">{{ t('page.alerts.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-button value="All">{{ t('page.alerts.all') }}</a-radio-button>
<a-radio-button value="System">{{ t('page.alerts.system') }}</a-radio-button>
<a-radio-button value="Device">{{ t('page.alerts.device') }}</a-radio-button>
</a-radio-group>
<a-select
v-model:value="selectedSiteId"
:loading="siteLoading"
placeholder="请选择站点"
:placeholder="t('page.alerts.chosesite')"
style="width: 200px; margin-right: 16px;"
@change="handleSiteChange"
>
@@ -179,7 +179,7 @@ onMounted(async () => {
</a-select>
</div>
<div>
<a-button @click="onBatchDelete">Batch Delete</a-button>
<a-button @click="onBatchDelete">{{ t('page.alerts.batchdelete') }}</a-button>
</div>
</div>
@@ -192,8 +192,8 @@ onMounted(async () => {
bordered
size="middle"
>
<a-table-column title="TYPE" dataIndex="key" key="key" />
<a-table-column title="LEVEL" dataIndex="level" key="level">
<a-table-column :title="t('page.alerts.type')" dataIndex="key" key="key" />
<a-table-column :title="t('page.alerts.level')" dataIndex="level" key="level">
<template #default="{ record }">
<span>
<span :style="{
@@ -207,17 +207,17 @@ onMounted(async () => {
</span>
</template>
</a-table-column>
<a-table-column title="CONTENT" dataIndex="content" key="content" />
<a-table-column title="TIME" dataIndex="time" key="time">
<a-table-column :title="t('page.alerts.content')" dataIndex="content" key="content" />
<a-table-column :title="t('page.alerts.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">
<a-table-column :title="t('page.alerts.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-tooltip v-if="statusTab === 'Unresolved'" :title="t('page.alerts.resovetitle')">
<a-button
type="link"
size="small"
@@ -230,17 +230,17 @@ onMounted(async () => {
</a-button>
</a-tooltip>
<!-- 所有状态都显示删除按钮 -->
<a-tooltip title="删除">
<a-tooltip :title="t('page.alerts.delete')">
<a-button
type="link"
size="small"
style="color: #ff4d4f"
@click="() => {
Modal.confirm({
title: '确认删除',
content: '确定要删除该条告警记录吗?',
okText: '确认',
cancelText: '取消',
title: t('page.alerts.deletetitle'),
content: t('page.alerts.suredelete'),
okText: t('page.alerts.sure'),
cancelText: t('page.alerts.cancel'),
onOk: () => onDelete(record.id)
})
}"