refactor: 系统权限模块重构,迁移至PostgreSQL并对齐新设计

- 切换数据库为PostgreSQL,更新依赖与配置
- 重构权限体系,使用sys_user/sys_role/sys_menu等新实体替代旧模型
- 移除旧的用户角色/权限/系统设置相关代码与实体
- 新增字典、菜单管理模块与基础CRUD接口
- 优化鉴权逻辑,基于菜单权限标识进行接口校验
- 前端同步更新API、路由与权限控制逻辑
- 删除冗余的v-permission指令与相关代码
This commit is contained in:
andyesfly committed 2026-08-19 14:11:34 +08:00
1 parent 98c22f6afb
commit 0a8103f33d
67 files changed
+3263 -1924

No files matched your search

+83 -56
View File
@@ -91,24 +91,29 @@
</template>
<script setup lang="ts">
import { ref, computed, watch, h } from 'vue'
import { ref, computed, watch, h, type Component, type VNode } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import {
DashboardOutlined,
SettingOutlined,
UserOutlined,
SafetyCertificateOutlined,
ToolOutlined,
InfoCircleOutlined,
LockOutlined,
MenuOutlined,
TeamOutlined,
ProjectOutlined,
ScheduleOutlined,
MonitorOutlined,
BarChartOutlined,
BookOutlined,
FileTextOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
HomeOutlined,
DownOutlined,
LogoutOutlined,
LockOutlined,
} from '@ant-design/icons-vue'
import { usePermissionStore } from '@/stores/permission'
import { usePermissionStore, type MenuNode } from '@/stores/permission'
const router = useRouter()
const route = useRoute()
@@ -119,57 +124,79 @@ const collapsed = ref(false)
const selectedKeys = ref<string[]>([])
const openKeys = ref<string[]>([])
// 菜单配置
const menuItems = computed(() => [
// 菜单图标映射:菜单 icon 字符串 → 图标组件,未知图标显示默认图标
const iconMap: Record<string, Component> = {
TeamOutlined,
ProjectOutlined,
ScheduleOutlined,
MonitorOutlined,
BarChartOutlined,
SettingOutlined,
UserOutlined,
SafetyCertificateOutlined,
MenuOutlined,
BookOutlined,
FileTextOutlined,
DashboardOutlined,
}
function resolveIcon(icon?: string | null) {
const iconComponent = icon ? iconMap[icon] : undefined
return () => h(iconComponent || MenuOutlined)
}
// 侧边栏菜单项结构(与 a-menu items 兼容)
interface MenuItem {
key: string
icon: () => VNode
label: string
children?: MenuItem[]
}
// 由后端菜单树构建侧边栏菜单:menuType=1 目录 → 子菜单组,menuType=2 菜单 → 菜单项
function buildMenuItems(nodes: MenuNode[]): MenuItem[] {
const items: MenuItem[] = []
for (const node of nodes) {
if (node.menuType === 1) {
const children = (node.children || [])
.filter(child => child.menuType === 2 && child.menuPath)
.map(child => ({
key: child.menuPath as string,
icon: resolveIcon(child.icon),
label: child.menuName,
}))
if (children.length) {
items.push({
key: node.menuPath || `dir-${node.id}`,
icon: resolveIcon(node.icon),
label: node.menuName,
children,
})
}
} else if (node.menuType === 2 && node.menuPath) {
items.push({
key: node.menuPath,
icon: resolveIcon(node.icon),
label: node.menuName,
})
}
}
return items
}
// 菜单配置:仪表盘固定展示在最前 + 后端菜单树动态渲染
const menuItems = computed<MenuItem[]>(() => [
{
key: '/dashboard',
icon: () => h(DashboardOutlined),
label: '仪表盘',
},
{
key: '/system',
icon: () => h(SettingOutlined),
label: '系统管理',
children: [
{
key: '/system/user',
icon: () => h(UserOutlined),
label: '用户管理',
},
{
key: '/system/role',
icon: () => h(SafetyCertificateOutlined),
label: '角色权限',
},
],
},
{
key: '/settings',
icon: () => h(ToolOutlined),
label: '系统设置',
children: [
{
key: '/settings/basic',
icon: () => h(InfoCircleOutlined),
label: '基本设置',
},
{
key: '/settings/security',
icon: () => h(LockOutlined),
label: '安全设置',
},
],
},
{
key: '/log/operation',
icon: () => h(FileTextOutlined),
label: '操作日志',
},
...buildMenuItems(permissionStore.menus),
])
// 计算属性
const userInfo = computed(() => permissionStore.userInfo)
const displayName = computed(() => userInfo.value?.nickname || userInfo.value?.username || '管理员')
const displayName = computed(() => userInfo.value?.realName || userInfo.value?.username || '管理员')
const userInitial = computed(() => (displayName.value?.charAt(0) || 'A').toUpperCase())
// 面包屑列表
@@ -381,15 +408,15 @@ function handleUserMenuClick({ key }: { key: string }) {
}
.content {
margin: 16px;
min-height: calc(100vh - 64px - 32px);
margin: 0;
min-height: calc(100vh - 64px);
.view-wrapper {
background: #fff;
padding: 24px;
border-radius: 8px;
min-height: calc(100vh - 64px - 32px - 48px); // 减去header、margin和padding
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
padding: 0;
border-radius: 0;
min-height: calc(100vh - 64px);
box-shadow: none;
}
}
}
@@ -435,11 +462,11 @@ function handleUserMenuClick({ key }: { key: string }) {
}
.content {
margin: 12px;
margin: 0;
.view-wrapper {
padding: 16px;
border-radius: 4px;
padding: 0;
border-radius: 0;
}
}
}