权限监控与管理界面全面美化
重新设计权限系统所有 UI 组件的视觉风格,统一配色、圆角、阴影和交互动效: - 实时概览:统计卡片加图标和渐变色条,健康评分改为环形进度,告警改为卡片式 - 趋势分析:图表卡片加彩色图标标识,ECharts 配色升级为渐变面积填充 - 访问日志:指标卡片带图标,日志审计改为卡片式入口,IP排行前三高亮 - IP属地:工具栏重设计,排行列表前三渐变高亮,指标卡片统一新风格 - 系统级权限:从 el-table 改为自定义卡片列表,模块块独立圆角卡片 - 项目权限配置:空状态引导优化,成员表格加头像,工具栏加背景容器 - 角色概览卡片:加进度条可视化,hover 微动效 - 接口权限矩阵:工具栏分离布局,表格圆角包裹 - 角色管理抽屉:侧边栏选中态渐变,操作行 hover 高亮 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,41 +1,40 @@
|
||||
<template>
|
||||
<div class="api-permissions">
|
||||
<!-- 搜索和筛选 -->
|
||||
<div class="api-permissions-toolbar">
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
placeholder="搜索权限..."
|
||||
clearable
|
||||
style="width: 250px"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-select v-model="filterModule" placeholder="筛选模块" clearable style="width: 150px">
|
||||
<el-option label="全部模块" value="" />
|
||||
<el-option
|
||||
v-for="module in uniqueModules"
|
||||
:key="module"
|
||||
:label="moduleLabel(module)"
|
||||
:value="module"
|
||||
<div class="toolbar-left">
|
||||
<span class="toolbar-title">接口权限矩阵</span>
|
||||
<span class="toolbar-desc">为各角色配置 API 接口的访问权限</span>
|
||||
</div>
|
||||
<div class="toolbar-filters">
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
placeholder="搜索权限..."
|
||||
clearable
|
||||
style="width: 220px"
|
||||
:prefix-icon="Search"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="filterAction" placeholder="筛选操作" clearable style="width: 120px">
|
||||
<el-option label="全部操作" value="" />
|
||||
<el-option label="创建" value="create" />
|
||||
<el-option label="读取" value="read" />
|
||||
<el-option label="更新" value="update" />
|
||||
<el-option label="删除" value="delete" />
|
||||
<el-option label="导出" value="export" />
|
||||
</el-select>
|
||||
<el-select v-model="filterModule" placeholder="筛选模块" clearable style="width: 150px">
|
||||
<el-option label="全部模块" value="" />
|
||||
<el-option
|
||||
v-for="module in uniqueModules"
|
||||
:key="module"
|
||||
:label="moduleLabel(module)"
|
||||
:value="module"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="filterAction" placeholder="筛选操作" clearable style="width: 120px">
|
||||
<el-option label="全部操作" value="" />
|
||||
<el-option label="创建" value="create" />
|
||||
<el-option label="读取" value="read" />
|
||||
<el-option label="更新" value="update" />
|
||||
<el-option label="删除" value="delete" />
|
||||
<el-option label="导出" value="export" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 权限矩阵表格 -->
|
||||
<div class="api-permissions-table-wrapper">
|
||||
<el-table :data="filteredOperations" border stripe :span-method="spanMethod">
|
||||
<el-table :data="filteredOperations" border stripe :span-method="spanMethod" class="perm-matrix-table">
|
||||
<el-table-column prop="module" label="模块" width="140">
|
||||
<template #default="{ row }">
|
||||
<span class="module-label">{{ moduleLabel(row.module) }}</span>
|
||||
@@ -45,7 +44,7 @@
|
||||
<el-table-column prop="operation_key" label="权限操作" width="200">
|
||||
<template #default="{ row }">
|
||||
<div class="operation-cell">
|
||||
<el-tag :type="getActionType(row)" size="small">
|
||||
<el-tag :type="getActionType(row)" size="small" class="action-tag">
|
||||
{{ getActionLabel(row) }}
|
||||
</el-tag>
|
||||
<span class="operation-name">{{ row.description || row.operation_key }}</span>
|
||||
@@ -78,6 +77,7 @@ import { Search } from "@element-plus/icons-vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { ApiEndpointPermissionsResponse } from "@/types/api";
|
||||
import { fetchApiOperations } from "@/api/projectPermissions";
|
||||
import { isApiPermissionAllowed } from "@/utils/apiPermissionValue";
|
||||
|
||||
interface Operation {
|
||||
operation_key: string;
|
||||
@@ -195,9 +195,7 @@ const spanMethod = ({ row, rowIndex, columnIndex }: { row: Operation; rowIndex:
|
||||
// 检查操作是否允许
|
||||
const isOperationAllowed = (operation_key: string, role: string): boolean => {
|
||||
if (!props.matrix || !props.matrix[role]) return false;
|
||||
const perm = props.matrix[role][operation_key];
|
||||
if (!perm) return false;
|
||||
return typeof perm === "boolean" ? perm : perm.allowed;
|
||||
return isApiPermissionAllowed(props.matrix[role][operation_key]);
|
||||
};
|
||||
|
||||
// 从 operation_key 提取操作类型
|
||||
@@ -258,38 +256,82 @@ const onPermissionChange = (operation_key: string, role: string, allowed: boolea
|
||||
onMounted(() => {
|
||||
loadOperations();
|
||||
});
|
||||
|
||||
defineExpose({ searchText });
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
<style scoped>
|
||||
.api-permissions {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.api-permissions-toolbar {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 18px;
|
||||
padding: 14px 18px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.toolbar-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.toolbar-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #1a2332;
|
||||
}
|
||||
|
||||
.toolbar-desc {
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.toolbar-filters {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.api-permissions-table-wrapper {
|
||||
overflow-x: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.perm-matrix-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.module-label {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
color: #1a2332;
|
||||
}
|
||||
|
||||
.operation-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.operation-name {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
.action-tag {
|
||||
flex-shrink: 0;
|
||||
min-width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.operation-name {
|
||||
font-size: 13px;
|
||||
color: #475569;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user