<template>
|
<div class="inquire">
|
<el-form :model="queryFormdata" :inline="true">
|
<el-form-item label="菜单名称">
|
<el-input v-model="queryFormdata.name" />
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="queryInfo()" icon="el-icon-search"
|
>查询
|
</el-button>
|
</el-form-item>
|
<br />
|
</el-form>
|
</div>
|
<div class="header_nox">
|
<el-button type="primary" @click="handleAdd('all', 1)">新增菜单</el-button>
|
</div>
|
<div>
|
<el-table
|
:data="menuTable"
|
style="width: 100%"
|
row-key="id"
|
border
|
height="75vh"
|
stripe
|
fixed
|
fit
|
>
|
<el-table-column prop="name" label="菜单名称" />
|
<el-table-column
|
prop="menuType"
|
:formatter="stateFormat"
|
label="菜单类型"
|
/>
|
<el-table-column prop="component" label="组件" />
|
<el-table-column prop="url" label="路径" />
|
<el-table-column prop="sortNo" label="顺序" />
|
<el-table-column prop="hidden" label="是否显示" align="center">
|
<template #default="scope">
|
<el-switch
|
v-model="scope.row.hidden"
|
:active-value="false"
|
:inactive-value="true"
|
active-text="显示"
|
inactive-text="隐藏"
|
@change="handleStatusChange(scope.row)"
|
></el-switch>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作">
|
<template #default="scope">
|
<el-link type="primary" @click="handleEdit(scope.row)">编辑</el-link>
|
<el-divider direction="vertical" />
|
<el-link type="primary" @click="handleAdd(scope.row, 2)"
|
>添加下级</el-link
|
>
|
<el-divider direction="vertical" />
|
<el-popconfirm
|
width="160px"
|
confirm-button-text="确认"
|
cancel-button-text="取消"
|
:icon="InfoFilled"
|
icon-color="#eebe59"
|
title="确认是否删除"
|
@confirm="confirmDelete(scope.row)"
|
>
|
<template #reference>
|
<el-link type="primary">删除</el-link>
|
</template>
|
</el-popconfirm>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
<el-drawer
|
ref="drawerRef"
|
v-model="dialog"
|
:title="drawertitle"
|
:before-close="handleClose"
|
direction="rtl"
|
class="demo-drawer"
|
:destroy-on-close="true"
|
>
|
<div class="demo-drawer__content">
|
<el-form
|
ref="ruleFormRef"
|
:model="ruleForm.FormInfo"
|
status-icon
|
label-width="120px"
|
class="demo-ruleForm"
|
:rules="rules"
|
>
|
<el-form-item label="菜单类型" prop="orgCategory">
|
<el-radio-group v-model="ruleForm.FormInfo.menuType">
|
<el-radio-button :label="0">一级菜单</el-radio-button>
|
<el-radio-button :label="1">子菜单</el-radio-button>
|
<el-radio-button :label="2">按钮/权限</el-radio-button>
|
</el-radio-group>
|
</el-form-item>
|
<div v-if="ruleForm.FormInfo.menuType == '2'">
|
<el-form-item label="按钮/权限" prop="name">
|
<el-input
|
placeholder="请输入按钮/权限"
|
v-model="ruleForm.FormInfo.name"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item label="上级菜单" prop="parentId">
|
<el-tree-select
|
placeholder="请选择上级菜单"
|
v-model="ruleForm.FormInfo.parentId"
|
:props="{ value: 'id', label: 'title' }"
|
:data="menuOptions"
|
node-key="id"
|
:render-after-expand="false"
|
check-strictly
|
check-on-click-node
|
/>
|
</el-form-item>
|
<el-form-item label="授权标识">
|
<el-input
|
placeholder="请输入授权标识"
|
v-model="ruleForm.FormInfo.perms"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<template #label>
|
<span
|
>授权策略
|
<el-tooltip placement="top">
|
<template #content>
|
可见/可访问(授权后可见/可访问)<br />
|
可编辑(未授权时禁用)
|
</template>
|
<el-icon><Warning /></el-icon>
|
</el-tooltip>
|
</span>
|
</template>
|
<el-radio-group v-model="ruleForm.FormInfo.permsType">
|
<el-radio label="1">可见/可访问</el-radio>
|
<el-radio label="2">可编辑</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item label="状态">
|
<el-radio-group v-model="ruleForm.FormInfo.status">
|
<el-radio label="1">有效 </el-radio>
|
<el-radio label="2">无效</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</div>
|
<div v-else>
|
<el-form-item label="菜单名称" prop="name">
|
<el-input
|
placeholder="请输入菜单名称"
|
v-model="ruleForm.FormInfo.name"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
|
<el-form-item label="访问路径" prop="url">
|
<el-input
|
placeholder="请输入访问路径"
|
v-model="ruleForm.FormInfo.url"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item label="前端组件" prop="component">
|
<el-input
|
placeholder="请输入前端组件"
|
v-model="ruleForm.FormInfo.component"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<template #label>
|
<span
|
>组件名称
|
<el-tooltip placement="top">
|
<template #content>
|
此处名称应和vue组件的name属性保持一致。<br />
|
组件名称不能重复,主要用于路由缓存功能。<br />
|
如果组件名称和vue组件的name属性不一致,则会导致路由缓存失效。<br />
|
非必填,留空则会根据访问路径自动生成。
|
</template>
|
<el-icon><Warning /></el-icon>
|
</el-tooltip>
|
</span>
|
</template>
|
<el-input
|
:placeholder="
|
ruleForm.FormInfo.url == ''
|
? '请输入组件名称'
|
: ruleForm.FormInfo.url
|
"
|
v-model="ruleForm.FormInfo.componentName"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item
|
label="默认跳转地址"
|
v-if="ruleForm.FormInfo.menuType == '0'"
|
>
|
<el-input
|
placeholder="访问路径"
|
v-model="ruleForm.FormInfo.redirect"
|
autocomplete="off"
|
/>
|
</el-form-item>
|
<el-form-item label="排序">
|
<el-input-number
|
v-model="ruleForm.FormInfo.sortNo"
|
:min="0"
|
:max="100"
|
controls-position="right"
|
/>
|
</el-form-item>
|
<el-form-item label="是否是路由菜单">
|
<el-switch
|
v-model="ruleForm.FormInfo.route"
|
inline-prompt
|
active-text="是"
|
inactive-text="否"
|
/>
|
</el-form-item>
|
<el-form-item label="隐藏路由">
|
<el-switch
|
v-model="ruleForm.FormInfo.hidden"
|
inline-prompt
|
active-text="是"
|
inactive-text="否"
|
:active-value="1"
|
:inactive-value="0"
|
/>
|
</el-form-item>
|
<el-form-item label="隐藏Tab">
|
<el-switch
|
v-model="ruleForm.FormInfo.hideTab"
|
inline-prompt
|
active-text="是"
|
inactive-text="否"
|
:active-value="1"
|
:inactive-value="0"
|
/>
|
</el-form-item>
|
<el-form-item label="是否缓存路由">
|
<el-switch
|
v-model="ruleForm.FormInfo.keepAlive"
|
inline-prompt
|
active-text="是"
|
inactive-text="否"
|
/>
|
</el-form-item>
|
<el-form-item label="聚合路由">
|
<el-switch
|
v-model="ruleForm.FormInfo.alwaysShow"
|
inline-prompt
|
active-text="是"
|
inactive-text="否"
|
/>
|
</el-form-item>
|
<el-form-item label="打开方式">
|
<el-switch
|
v-model="ruleForm.FormInfo.internalOrExternal"
|
inline-prompt
|
active-text="外部"
|
inactive-text="内部"
|
/>
|
</el-form-item>
|
</div>
|
</el-form>
|
<div class="demo-drawer__footer" v-if="isAdd">
|
<el-button @click="handleClose()">取消</el-button>
|
<el-button type="primary" @click="addMenu(ruleFormRef)">新增</el-button>
|
</div>
|
<div class="demo-drawer__footer" v-if="isEdit">
|
<el-button @click="handleClose()">取消</el-button>
|
<el-button type="primary" @click="editRole(ruleFormRef)">
|
编辑
|
</el-button>
|
</div>
|
</div>
|
</el-drawer>
|
</template>
|
|
<script>
|
import { ref, reactive, getCurrentInstance } from "vue";
|
import {
|
MenuListTree,
|
MenuUpdate,
|
MenuAdd,
|
checkPermDuplication,
|
deleteMenu,
|
} from "@/api/menu";
|
import { InfoFilled } from "@element-plus/icons-vue";
|
|
export default {
|
name: "Menu",
|
setup() {
|
const { proxy } = getCurrentInstance();
|
//控制显隐
|
const handleStatusChange = async (row) => {
|
MenuUpdate(row)
|
.then((data) => {
|
proxy.$message({
|
message: data.message,
|
type: "success",
|
});
|
queryInfo();
|
})
|
.catch((err) => {
|
proxy.$message({
|
message: err.status,
|
type: "error",
|
});
|
});
|
};
|
const menuTable = ref([]);
|
const queryFormdata = reactive({
|
name: "",
|
});
|
const queryInfo = async () => {
|
let name = queryFormdata.name.trim();
|
let searchData = reactive({});
|
if (name != "") {
|
searchData = {
|
column: "createTime",
|
order: "desc",
|
name: queryFormdata.name.trim(),
|
_t: new Date().getTime(),
|
};
|
} else {
|
searchData = {
|
column: "createTime",
|
order: "desc",
|
_t: new Date().getTime(),
|
};
|
}
|
const data = await MenuListTree(searchData);
|
menuTable.value = data.result;
|
};
|
const stateFormat = (row) => {
|
if (row.menuType == 0) {
|
return "一级菜单";
|
} else {
|
return "子菜单";
|
}
|
};
|
// 定义弹框
|
const dialog = ref(false);
|
const isEdit = ref(false);
|
const isAdd = ref(false);
|
const drawerRef = ref();
|
const url = (rule, value, callback) => {
|
if (value === "" || value === null || value === undefined) {
|
callback(new Error("请输入访问路径"));
|
} else {
|
if (isAdd.value) {
|
checkPermDuplication({
|
url: value,
|
alwaysShow: ruleForm.FormInfo.alwaysShow,
|
_t: new Date().getTime(),
|
})
|
.then((res) => {
|
callback();
|
})
|
.catch((err) => {
|
callback(new Error("该值不可用,系统中已存在!"));
|
});
|
} else if (isEdit.value) {
|
checkPermDuplication({
|
id: ruleForm.FormInfo.id,
|
url: value,
|
alwaysShow: ruleForm.FormInfo.alwaysShow,
|
_t: new Date().getTime(),
|
})
|
.then((res) => {
|
callback();
|
})
|
.catch((err) => {
|
callback(new Error("该值不可用,系统中已存在!"));
|
});
|
}
|
}
|
};
|
const rules = ref({
|
name: [
|
{
|
required: true,
|
message: "请输入菜单名称",
|
trigger: "blur",
|
},
|
],
|
parentId: [
|
{
|
required: true,
|
message: "请选择上级菜单",
|
trigger: "change",
|
},
|
],
|
url: [
|
{
|
required: true,
|
validator: url,
|
trigger: "change",
|
},
|
],
|
component: [
|
{
|
required: true,
|
message: "请输入前端组件",
|
trigger: "blur",
|
},
|
],
|
});
|
const ruleFormRef = ref();
|
const editForm = ref();
|
const drawertitle = ref("");
|
const ruleForm = reactive({
|
FormInfo: {
|
menuType: 0,
|
name: "",
|
url: "",
|
component: "",
|
componentName: "",
|
redirect: "",
|
sortNo: 1,
|
route: true,
|
hidden: 0,
|
hideTab: 0,
|
keepAlive: false,
|
alwaysShow: false,
|
internalOrExternal: false,
|
id: "",
|
parentId: "",
|
icon: "",
|
perms: "",
|
permsType: "1",
|
status: "1",
|
},
|
});
|
// 请求菜单列表
|
const menuOptions = ref([]);
|
const getMenuList = async () => {
|
const menuData = await MenuListTree({ _t: new Date().getTime() });
|
menuOptions.value = menuData.result;
|
};
|
//新增菜单
|
const handleAdd = (val, index) => {
|
ruleForm.FormInfo.parentId = "";
|
ruleForm.FormInfo.menuType = 0;
|
// 添加下级
|
if (index == 2) {
|
ruleForm.FormInfo.parentId = val.id;
|
ruleForm.FormInfo.menuType = 1;
|
}
|
getMenuList(); //请求菜单列表
|
drawertitle.value = "新增菜单";
|
isEdit.value = false;
|
isAdd.value = true;
|
dialog.value = true;
|
};
|
|
const addMenu = (formEl) => {
|
if (!formEl) return;
|
formEl.validate((valid) => {
|
if (valid) {
|
let newMenuData = JSON.parse(JSON.stringify(ruleForm.FormInfo));
|
delete newMenuData.id;
|
delete newMenuData.icon;
|
if (newMenuData.menuType == 0) {
|
delete newMenuData.parentId;
|
delete newMenuData.perms;
|
delete newMenuData.permsType;
|
delete newMenuData.status;
|
} else if (newMenuData.menuType == 1) {
|
delete newMenuData.permsType;
|
delete newMenuData.perms;
|
delete newMenuData.status;
|
} else {
|
delete newMenuData.url;
|
delete newMenuData.component;
|
delete newMenuData.componentName;
|
delete newMenuData.redirect;
|
delete newMenuData.sortNo;
|
delete newMenuData.route;
|
delete newMenuData.hidden;
|
delete newMenuData.hideTab;
|
delete newMenuData.keepAlive;
|
delete newMenuData.alwaysShow;
|
delete newMenuData.internalOrExternal;
|
}
|
// console.log(newMenuData);
|
MenuAdd(newMenuData).then((res) => {
|
if (res.success) {
|
proxy.$message({
|
message: "注册成功",
|
type: "success",
|
});
|
}
|
queryInfo();
|
handleClose();
|
});
|
} else {
|
return false;
|
}
|
});
|
};
|
//编辑
|
const handleEdit = async (val) => {
|
getMenuList(); //请求菜单列表
|
drawertitle.value = "编辑用户";
|
isAdd.value = false;
|
isEdit.value = true;
|
ruleForm.FormInfo.menuType = val.menuType;
|
ruleForm.FormInfo.name = val.name;
|
ruleForm.FormInfo.url = val.url;
|
ruleForm.FormInfo.component = val.component;
|
ruleForm.FormInfo.componentName = val.componentName;
|
ruleForm.FormInfo.redirect = val.redirect;
|
ruleForm.FormInfo.sortNo = val.sortNo;
|
ruleForm.FormInfo.route = val.route;
|
ruleForm.FormInfo.hidden = val.hidden;
|
ruleForm.FormInfo.hideTab = val.hideTab;
|
ruleForm.FormInfo.keepAlive = val.keepAlive;
|
ruleForm.FormInfo.alwaysShow = val.alwaysShow;
|
ruleForm.FormInfo.internalOrExternal = val.internalOrExternal;
|
ruleForm.FormInfo.id = val.id;
|
ruleForm.FormInfo.parentId = val.parentId;
|
ruleForm.FormInfo.icon = val.icon;
|
ruleForm.FormInfo.perms = val.perms;
|
ruleForm.FormInfo.permsType = val.permsType;
|
ruleForm.FormInfo.status = val.status;
|
dialog.value = true;
|
};
|
const editRole = (formEl) => {
|
if (!formEl) return;
|
formEl.validate((valid) => {
|
if (valid) {
|
if (ruleForm.FormInfo.menuType == 0) {
|
delete ruleForm.FormInfo.parentId;
|
delete ruleForm.FormInfo.perms;
|
delete ruleForm.FormInfo.permsType;
|
delete ruleForm.FormInfo.status;
|
} else if (ruleForm.FormInfo.menuType == 1) {
|
delete ruleForm.FormInfo.permsType;
|
delete ruleForm.FormInfo.perms;
|
delete ruleForm.FormInfo.status;
|
} else {
|
delete ruleForm.FormInfo.url;
|
delete ruleForm.FormInfo.component;
|
delete ruleForm.FormInfo.componentName;
|
delete ruleForm.FormInfo.redirect;
|
delete ruleForm.FormInfo.sortNo;
|
delete ruleForm.FormInfo.route;
|
delete ruleForm.FormInfo.hidden;
|
delete ruleForm.FormInfo.hideTab;
|
delete ruleForm.FormInfo.keepAlive;
|
delete ruleForm.FormInfo.alwaysShow;
|
delete ruleForm.FormInfo.internalOrExternal;
|
}
|
// console.log(ruleForm.FormInfo);
|
MenuUpdate(ruleForm.FormInfo).then((res) => {
|
if (res.success) {
|
proxy.$message({
|
message: res.message,
|
type: "success",
|
});
|
}
|
handleClose();
|
queryInfo();
|
});
|
} else {
|
return false;
|
}
|
});
|
};
|
// 删除
|
const confirmDelete = (val) => {
|
deleteMenu({
|
id: val.id,
|
})
|
.then((res) => {
|
if (res.success) {
|
proxy.$message({
|
message: res.message,
|
type: "success",
|
});
|
}
|
queryInfo();
|
})
|
.catch((res) => {
|
proxy.$message({
|
message: res.message,
|
type: "error",
|
});
|
queryInfo();
|
});
|
};
|
|
//关闭弹框
|
const handleClose = () => {
|
dialog.value = false;
|
drawertitle.value = "";
|
ruleForm.FormInfo = {
|
id: "",
|
menuType: 0,
|
name: "",
|
url: "",
|
component: "",
|
componentName: "",
|
redirect: "",
|
sortNo: 1,
|
route: true,
|
hidden: false,
|
hideTab: false,
|
keepAlive: false,
|
alwaysShow: false,
|
internalOrExternal: false,
|
parentId: "",
|
icon: null,
|
};
|
};
|
|
queryInfo();
|
return {
|
queryFormdata,
|
queryInfo,
|
menuTable,
|
stateFormat,
|
handleStatusChange,
|
rules,
|
addMenu,
|
dialog,
|
isEdit,
|
isAdd,
|
drawerRef,
|
ruleFormRef,
|
editForm,
|
drawertitle,
|
ruleForm,
|
handleEdit,
|
handleClose,
|
handleAdd,
|
menuOptions,
|
InfoFilled,
|
confirmDelete,
|
editRole,
|
};
|
},
|
};
|
</script>
|
|
<style scoped>
|
.el-switch /deep/ .is-active {
|
background-color: transparent !important;
|
}
|
|
.demo-drawer__footer {
|
display: flex;
|
justify-content: flex-end;
|
}
|
</style>
|