feat(filter): 将发件人黑白名单拆分为独立设置菜单并解耦日志页面
Some checks are pending
Security Checks / security (push) Waiting to run
Some checks are pending
Security Checks / security (push) Waiting to run
This commit is contained in:
parent
a717183e55
commit
946fdbbe55
@ -1,5 +1,5 @@
|
||||
import {EpMenu} from "vue-icons-plus/ep";
|
||||
import { Lock, Connection, Setting, FolderOpened, Filter, User, Grid, Document } from '@element-plus/icons-vue';
|
||||
import {EpMenu} from "vue-icons-plus/ep";
|
||||
import { Lock, Connection, Setting, FolderOpened, Filter, User, Grid, Document, Checked } from '@element-plus/icons-vue';
|
||||
|
||||
import {computed, ref, onMounted, onUnmounted, defineAsyncComponent} from 'vue'
|
||||
import SettingsPageStatus from '../SettingsPageStatus/SettingsPageStatus.vue'
|
||||
@ -25,6 +25,7 @@ const GroupSettings = lazySettings(() => import('../GroupSettings/GroupSettings.
|
||||
const RuleSettings = lazySettings(() => import('../RuleSettings/RuleSettings.vue'))
|
||||
const UserManagement = lazySettings(() => import('../UserManagement/UserManagement.vue'))
|
||||
const PluginSettings = lazySettings(() => import('../PluginSettings/PluginSettings.vue'))
|
||||
const SenderFilterManagement = lazySettings(() => import('../SenderFilterManagement/SenderFilterManagement.vue'))
|
||||
const LogSettings = lazySettings(() => import('../LogSettings/LogSettings.vue'))
|
||||
|
||||
export function usePage() {
|
||||
@ -54,6 +55,7 @@ export function usePage() {
|
||||
{ key: 'rule', label: lang.rule_setting, hint: '邮件处理规则', icon: Filter, component: RuleSettings, capability: 'user.read' },
|
||||
{ key: 'users', label: lang.user_management, hint: '账号与权限管理', icon: User, component: UserManagement, capability: 'user.manage' },
|
||||
{ key: 'plugins', label: lang.plugin_settings, hint: '扩展功能管理', icon: Grid, component: PluginSettings, capability: 'plugin.read' },
|
||||
{ key: 'sender-filter', label: '黑白名单', hint: '发件人信任与拦截', icon: Checked, component: SenderFilterManagement, capability: 'user.read' },
|
||||
{ key: 'logs', label: '日志', hint: '操作、收发信与运行记录', icon: Document, component: LogSettings, capability: 'audit.read' },
|
||||
].filter(item => {
|
||||
// 日志数据范围由服务端强制过滤;菜单只决定入口是否可见。
|
||||
@ -117,5 +119,6 @@ export {
|
||||
GroupSettings,
|
||||
RuleSettings,
|
||||
UserManagement,
|
||||
PluginSettings
|
||||
PluginSettings,
|
||||
SenderFilterManagement
|
||||
}
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="log-settings-container">
|
||||
<!-- 日志上方:发件人黑白名单管理(支持添加、删除、拉黑/转白,仅当前用户维护自身名单) -->
|
||||
<SenderFilterManagement />
|
||||
|
||||
<section class="log-settings">
|
||||
<header class="log-heading">
|
||||
<h2>日志记录</h2>
|
||||
@ -173,7 +170,6 @@
|
||||
|
||||
<script setup>
|
||||
import { useLogs } from './LogSettings.js'
|
||||
import SenderFilterManagement from '../SenderFilterManagement/SenderFilterManagement.vue'
|
||||
|
||||
const {
|
||||
category, categories, loading, error, items, offset,
|
||||
|
||||
@ -1,45 +1,58 @@
|
||||
.sender-filter-management {
|
||||
background: var(--el-bg-color-overlay, #ffffff);
|
||||
border: 1px solid var(--el-border-color-light, #e4e7ed);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
.sender-filter-card {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.sf-header {
|
||||
.settings-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sf-title-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.sf-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
.header-main h3 {
|
||||
margin: 0 0 6px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary, #303133);
|
||||
color: var(--pm-text-primary, #303133);
|
||||
}
|
||||
|
||||
.settings-desc {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--pm-text-secondary, #909399);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.sf-badges {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sf-badge {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sf-quick-add {
|
||||
.sf-quick-add-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
padding: 12px 16px;
|
||||
background-color: var(--el-fill-color-light, #f8fafc);
|
||||
border: 1px solid var(--el-border-color-lighter, #ebeef5);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.sf-input-email {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.sf-select-type {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.sf-toolbar {
|
||||
@ -47,7 +60,6 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@ -60,7 +72,9 @@
|
||||
}
|
||||
|
||||
.sf-table-wrapper {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid var(--el-border-color-lighter, #ebeef5);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sf-table {
|
||||
@ -69,6 +83,7 @@
|
||||
|
||||
.sf-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
@ -76,20 +91,21 @@
|
||||
.sf-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sf-header {
|
||||
.settings-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
gap: 8px;
|
||||
}
|
||||
.sf-quick-add {
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
.sf-quick-add-box {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.sf-quick-add .el-input {
|
||||
.sf-input-email,
|
||||
.sf-select-type {
|
||||
width: 100% !important;
|
||||
}
|
||||
.sf-toolbar {
|
||||
|
||||
@ -1,46 +1,50 @@
|
||||
<template>
|
||||
<div class="sender-filter-management" v-loading="loading">
|
||||
<!-- 面板标题与快捷操作栏 -->
|
||||
<div class="sf-header">
|
||||
<div class="sf-title-group">
|
||||
<h3 class="sf-title">发件人黑白名单管理</h3>
|
||||
<div class="sf-badges">
|
||||
<el-tag type="success" effect="plain" class="sf-badge">
|
||||
信任白名单: {{ whitelistCount }}
|
||||
</el-tag>
|
||||
<el-tag type="danger" effect="plain" class="sf-badge">
|
||||
拦截黑名单: {{ blacklistCount }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<template>
|
||||
<div class="settings-card sender-filter-card" v-loading="loading">
|
||||
<div class="settings-header">
|
||||
<div class="header-main">
|
||||
<h3>发件人黑白名单</h3>
|
||||
<p class="settings-desc">
|
||||
管理受信任的白名单与受拦截的黑名单发件人。白名单邮件不提示风险,黑名单发件人邮件将强行标记风险警示。
|
||||
</p>
|
||||
</div>
|
||||
<div class="sf-quick-add">
|
||||
<el-input
|
||||
v-model="addForm.email"
|
||||
placeholder="输入发件人邮箱 (如 friend@example.com)"
|
||||
clearable
|
||||
size="default"
|
||||
style="width: 280px"
|
||||
@keyup.enter="handleAdd"
|
||||
/>
|
||||
<el-select
|
||||
v-model="addForm.filter_type"
|
||||
size="default"
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-option label="信任白名单" value="whitelist" />
|
||||
<el-option label="拦截黑名单" value="blacklist" />
|
||||
</el-select>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="default"
|
||||
:loading="addLoading"
|
||||
@click="handleAdd"
|
||||
>
|
||||
添加名单
|
||||
</el-button>
|
||||
<div class="sf-badges">
|
||||
<el-tag type="success" effect="plain" class="sf-badge">
|
||||
信任白名单: {{ whitelistCount }}
|
||||
</el-tag>
|
||||
<el-tag type="danger" effect="plain" class="sf-badge">
|
||||
拦截黑名单: {{ blacklistCount }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 快捷添加区域 -->
|
||||
<div class="sf-quick-add-box">
|
||||
<el-input
|
||||
v-model="addForm.email"
|
||||
placeholder="输入发件人邮箱 (如 friend@example.com)"
|
||||
clearable
|
||||
size="default"
|
||||
class="sf-input-email"
|
||||
@keyup.enter="handleAdd"
|
||||
/>
|
||||
<el-select
|
||||
v-model="addForm.filter_type"
|
||||
size="default"
|
||||
class="sf-select-type"
|
||||
>
|
||||
<el-option label="信任白名单" value="whitelist" />
|
||||
<el-option label="拦截黑名单" value="blacklist" />
|
||||
</el-select>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="default"
|
||||
:loading="addLoading"
|
||||
@click="handleAdd"
|
||||
>
|
||||
添加名单
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 筛选与搜索工具条 -->
|
||||
<div class="sf-toolbar">
|
||||
<el-radio-group
|
||||
@ -75,12 +79,12 @@
|
||||
<el-table
|
||||
:data="filterList"
|
||||
stripe
|
||||
size="small"
|
||||
size="default"
|
||||
class="sf-table"
|
||||
empty-text="暂无匹配的发件人规则"
|
||||
empty-text="暂无匹配的发件人名单"
|
||||
>
|
||||
<el-table-column prop="email" label="发件人邮箱" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="名单类型" width="130" align="center">
|
||||
<el-table-column prop="email" label="发件人邮箱" min-width="220" show-overflow-tooltip />
|
||||
<el-table-column label="名单属性" width="130" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
v-if="row.filter_type === 'whitelist'"
|
||||
@ -100,7 +104,7 @@
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新/添加时间" width="160" align="center">
|
||||
<el-table-column label="更新时间" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<span>{{ formatDate(row.updated_at || row.created_at) }}</span>
|
||||
</template>
|
||||
@ -170,7 +174,6 @@ const {
|
||||
currentTab,
|
||||
addForm,
|
||||
addLoading,
|
||||
loadFilters,
|
||||
handleSearch,
|
||||
handleTabChange,
|
||||
handlePageChange,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user