foreign-admin-ui/src/views/system/menuManagement/index.vue

234 lines
8.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="menu-list">
<!-- 缺少通配搜索组件 -->
<div class="menu-action">
<h4>菜单列表</h4>
<el-button type="primary" :icon="Plus" @click="handleAddMenu">新增菜单</el-button>
</div>
<div class="table-container">
<el-table :data="menuTree" row-key="id" :tree-props="{ children: 'son' }" border highlight-current-row>
<el-table-column prop="name" label="菜单名称" />
<el-table-column prop="path" label="路由路径" />
<el-table-column prop="icon" label="图标">
<template #default="{ row }">
<el-icon v-if="row.icon && iconMap[row.icon]">
<component :is="iconMap[row.icon]" />
</el-icon>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="type" label="类型">
<template #default="{ row }">
{{ row.type === 1 ? '目录' : '按钮' }}
</template>
</el-table-column>
<!-- 新增:状态列 -->
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag size="small" :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="handleEditMenu(row)">
编辑
</el-button>
<el-button link type="danger" size="small" @click="handleDeleteMenu(row)">
删除
</el-button>
<el-button link size="small" :type="row.status === 1 ? 'warning' : 'success'"
@click="handleToggleStatus(row)">
{{ row.status === 1 ? '禁用' : '启用' }}
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增菜单' : '编辑菜单'" width="600px" destroy-on-close>
<el-form label-width="100px">
<el-form-item label="菜单名称">
<el-input v-model="menuForm.name" placeholder="请输入菜单名称" />
</el-form-item>
<el-form-item label="父级菜单">
<el-select v-model="menuForm.parentId" placeholder="请选择父级菜单" style="width:100%">
<el-option label="一级菜单" value="0" />
<el-option v-for="item in menuTree" :key="item.id" :label="item.name" :value="item.id + ''" />
</el-select>
</el-form-item>
<el-form-item label="路由路径">
<el-input v-model="menuForm.path" placeholder="例如:/system/menuList" />
</el-form-item>
<el-form-item label="后端路由">
<el-input v-model="menuForm.api" placeholder="例如:/api/system/menu/list可选" />
</el-form-item>
<el-form-item label="图标名称">
<el-input v-model="menuForm.icon" placeholder="例如Tools、List" />
<div style="margin-top:8px;font-size:12px;color:#909399;">
支持的图标Tools、List、HomeFilled、UserFilled、Platform、BellFilled、GoodsFilled、WarningFilled
</div>
</el-form-item>
<el-form-item label="排序">
<el-input-number v-model="menuForm.sort" :min="0" placeholder="数字越小越靠前默认1" />
</el-form-item>
<el-form-item label="菜单类型">
<el-radio-group v-model="menuForm.type">
<el-radio :value="1">菜单(显示在侧边栏)</el-radio>
<el-radio :value="2">按钮权限控制</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmitMenu">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { Tools, List, HomeFilled, UserFilled, Platform, BellFilled, GoodsFilled, WarningFilled, Plus } from '@element-plus/icons-vue'
import { getMenuApi, addMenuApi, deleteMenuApi, editMenuApi } from '@/api/modules/menu'
//menu数据
const menuTree = ref<any[]>([])
// 定义菜单表单数据
const menuForm = ref({
name: '', // 菜单名称
parentId: 0, // 默认一级菜单
path: '', // 路由路径
api: '', // 后端路由
icon: '', // 图标名称
sort: 1, // 排序默认1
type: 1 // 默认是菜单类型
})
// 定义图标映射表(和侧边栏逻辑一致)
const iconMap: Record<string, any> = {
Tools,
List,
HomeFilled,
UserFilled,
Platform,
BellFilled,
GoodsFilled,
WarningFilled
}
// 定义弹窗显示状态
const dialogVisible = ref(false)
// 新增:区分新增/编辑模式
const dialogType = ref<'add' | 'edit'>('add')
// 编辑菜单ID
const currentEditId = ref(null)
//所有的方法
// 获取菜单列表
onMounted(async () => {
try {
const res = await getMenuApi()
menuTree.value = filterEnabledMenus(res)
} catch (err) {
ElMessage.error('获取菜单列表失败')
}
})
// 处理菜单状态,只保留 status=1 的菜单
const filterEnabledMenus = (menuList: any[]) => {
const enabledMenus = menuList.filter(menu => menu.status === 1)
enabledMenus.forEach(menu => {
if (menu.son && menu.son.length) {
menu.son = filterEnabledMenus(menu.son)
}
})
return enabledMenus
}
// 打开新增弹窗
const handleAddMenu = () => {
// 清空表单
menuForm.value = {
name: '',
parentId: '',
path: '',
api: '',
icon: '',
sort: 1,
type: 1
}
dialogVisible.value = true
}
//打开编辑弹窗
const handleEditMenu = (row: any) => {
dialogType.value = 'edit'
currentEditId.value = row.id
menuForm.value = {
name: row.name,
parentId: row.parentId,
path: row.path,
api: row.api,
icon: row.icon,
sort: row.sort,
type: row.type
}
dialogVisible.value = true
}
// 提交表单(新增/编辑)
const handleSubmitMenu = async () => {
//添加校验,校验通过后提交表单
try {
if (dialogType.value === 'add') {
await addMenuApi({
...menuForm.value,
parent_id: menuForm.value.parentId
})
} else {
await editMenuApi({
id: currentEditId.value || 0,
status: menuForm.value.type === 2 ? 0 : 1, // 按钮默认禁用
parent_id: menuForm.value.parentId,
...menuForm.value
})
}
dialogVisible.value = false
} catch (err) {
ElMessage.error('操作失败')
}
}
//删除菜单
const handleDeleteMenu = async (row: any) => {
try {
await deleteMenuApi({ id: row.id })
} catch (err) {
console.log('删除菜单失败', err)
}
}
// 切换状态
const handleToggleStatus = async (row: any) => {
row.status = row.status === 1 ? 0 : 1
ElMessage.success(`${row.status === 1 ? '启用' : '禁用'}`)
}
</script>
<style scoped lang="scss">
.menu-list {
.menu-action {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
}
</style>