'admin-21.02.27:新增菜单管理的新增,编辑页面、样式优化、弹窗适配移动端等'

This commit is contained in:
lyt-Top 2021-02-27 18:35:04 +08:00
parent 956aed0c2b
commit c9cdbb2f49
9 changed files with 449 additions and 39 deletions

View File

@ -472,34 +472,38 @@ const router = createRouter({
})
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
export function getBackEndControlRoutes() {
export function getBackEndControlRoutes(callback: any) {
const token = getSession('token')
if (!token) return false
store.dispatch('setUserInfos')
const auth = store.state.userInfos.authPageList[0] // 模拟 admin 与 test
if (auth === 'admin') {
return new Promise((resolve, reject) => {
getMenuAdmin().then((res: any) => {
setBackEndControlRoutesFun(res)
if (res.data) resolve(res)
else reject('请求错误')
})
callback(res)
})
} else {
return new Promise((resolve, reject) => {
setTimeout(() => {
getMenuTest().then((res: any) => {
setBackEndControlRoutesFun(res)
if (res.data) resolve(res)
else reject('请求错误')
})
}, 1000)
callback(res)
})
}
}
// 后端控制路由,模拟执行路由数据初始化
export function setBackEndControlRoutesFun(res: any) {
export function setBackEndControlRoutesFun(res: any, callback?: any) {
initBackEndControlRoutesFun(res)
window.location.href = window.location.href // 防止页面刷新时出现空白或404
callback(res)
}
// 后端控制路由,动态添加菜单时(刷新菜单)
export function setBackEndControlRefreshRoutes() {
getBackEndControlRoutes((res: any) => {
initBackEndControlRoutesFun(res)
})
}
// 后端控制路由,模拟执行路由数据初始化
const initBackEndControlRoutesFun = (res: any) => {
const oldRoutes = JSON.parse(JSON.stringify(res.data))
store.dispatch('setBackEndControlRoutes', oldRoutes)
dynamicRoutes[0].children = backEndRouter(res.data)
@ -508,7 +512,6 @@ export function setBackEndControlRoutesFun(res: any) {
setAddRoute() // 添加动态路由
setFilterMenu() // 过滤权限菜单
setCacheTagsViewRoutes() // 添加 keepAlive 缓存
window.location.href = window.location.href // 防止页面刷新时出现空白或404
}
// 后端控制路由,后端路由 component 转换
@ -654,9 +657,10 @@ export function initAllFun() {
}
// 初始化方法执行
if (!store.state.themeConfig.isRequestRoutes) initAllFun()
const requestRoutes = store.state.themeConfig.isRequestRoutes
if (!requestRoutes) initAllFun()
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
if (store.state.themeConfig.isRequestRoutes) getBackEndControlRoutes()
if (requestRoutes) getBackEndControlRoutes((res: any) => { setBackEndControlRoutesFun(res) })
// 路由加载前
router.beforeEach((to, from, next) => {

View File

@ -879,6 +879,16 @@
.el-dialog__headerbtn:hover .el-dialog__close {
color: set-color(primary);
}
.el-overlay {
display: flex;
align-items: center;
.el-dialog {
margin: 0 auto !important;
.el-dialog__body {
padding: 20px !important;
}
}
}
/* Card 卡片
------------------------------- */

View File

@ -0,0 +1,9 @@
@import './index.scss';
/* 页面宽度小于800px
------------------------------- */
@media screen and (max-width: 800px) {
.el-dialog {
width: 90% !important;
}
}

View File

@ -8,3 +8,4 @@
@import './form.scss';
@import './scrollbar.scss';
@import './pagination.scss';
@import './dialog.scss';

View File

@ -40,6 +40,7 @@ import {
setFilterMenu,
setCacheTagsViewRoutes,
getBackEndControlRoutes,
setBackEndControlRoutesFun,
} from "/@/router/index.ts";
import { useStore } from "/@/store/index.ts";
import { setSession } from "/@/utils/storage.ts";
@ -115,9 +116,11 @@ export default defineComponent({
}
// isRequestRoutes true
else {
getBackEndControlRoutes().then((res) => {
getBackEndControlRoutes((res) => {
setBackEndControlRoutesFun(res, (cb) => {
signInSuccess();
});
});
}
};
//

View File

@ -84,7 +84,7 @@
<el-col :span="24">
<el-card shadow="hover" class="mt15 personal-edit" header="更新信息">
<div class="personal-edit-title">基本信息</div>
<el-form :model="personalForm" size="small" label-width="40px" class="personal-edit-form mt35 mb35">
<el-form :model="personalForm" size="small" label-width="40px" class="mt35 mb35">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="昵称">

View File

@ -1,16 +1,192 @@
<template>
<div class="system-menu-add-container"></div>
<div class="system-menu-container">
<el-dialog title="新增菜单" v-model="isShowDialog" width="769px">
<div class="system-menu-form">
<el-form :model="ruleForm" size="small" label-width="80px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单名称">
<el-input v-model="ruleForm.meta.title" placeholder="请输入菜单名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="路由名称">
<el-input v-model="ruleForm.name" placeholder="路由名称路由中的name值" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单图标">
<el-input v-model="ruleForm.meta.icon" placeholder="请输入菜单图标" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="组件地址">
<el-input v-model="ruleForm.component" placeholder="组件地址" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否隐藏">
<el-select v-model="ruleForm.meta.isHide" placeholder="请选择是否隐藏" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否缓存">
<el-select v-model="ruleForm.meta.isKeepAlive" placeholder="请选择是否缓存" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否固定">
<el-select v-model="ruleForm.meta.isAffix" placeholder="请选择是否固定" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否外链">
<el-select v-model="ruleForm.isLink" placeholder="请选择是否外链" clearable class="w100"
:disabled="ruleForm.meta.isIframe === 'true'">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否内嵌">
<el-select v-model="ruleForm.meta.isIframe" placeholder="请选择是否iframe" clearable class="w100"
@change="onSelectIframeChange">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="链接地址">
<el-input v-model="ruleForm.meta.isLink" placeholder="外链/内嵌时链接地址http:xxx.com" clearable
:disabled="ruleForm.isLink === '' || ruleForm.isLink === 'false'">
</el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="权限标识">
<el-input v-model="ruleForm.meta.auth" placeholder="路由权限标识(多个请用逗号隔开)" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单排序">
<el-input v-model="ruleForm.menuSort" placeholder="菜单排序" clearable></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="small"> </el-button>
<el-button type="primary" @click="onSubmit" size="small"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs } from "vue";
// import { setBackEndControlRefreshRoutes } from "/@/router/index.ts";
export default {
name: "systemAddMenu",
setup() {
const state = reactive({});
const state = reactive({
isShowDialog: false,
/**
* 参数请参考 `/src/router/index.ts` 中的 `dynamicRoutes` 路由菜单格式请注意参数类型
* 受到 `element plus` 类型 `string/number/object` 影响不可使用 `:value="true"`
* 的写法所以传值到后台时需要转换成布尔值否则页面可能出现玄学
* 路由权限标识为数组格式基本都需要自行转换类型
*/
ruleForm: {
name: "", //
component: "", //
isLink: "", //
menuSort: "", //
meta: {
title: "", //
icon: "", //
isHide: "", //
isKeepAlive: "", //
isAffix: "", //
isLink: "", // `1isLink:true 2`
isIframe: "", // `1isIframe:true 2`
auth: "", //
},
},
});
//
const openDialog = (row) => {
state.isShowDialog = true;
};
//
const closeDialog = (row) => {
state.isShowDialog = false;
};
//
const onSelectIframeChange = () => {
if (state.ruleForm.meta.isIframe === "true") {
state.ruleForm.isLink = "true";
} else {
state.ruleForm.isLink = "";
}
};
//
const onCancel = () => {
closeDialog();
initForm();
};
//
const onSubmit = () => {
console.log(state.ruleForm); //
closeDialog(); //
// setBackEndControlRefreshRoutes() //
};
// `resetFields()` 使
const initForm = () => {
state.ruleForm.name = "";
state.ruleForm.component = "";
state.ruleForm.isLink = "";
state.ruleForm.menuSort = "";
state.ruleForm.meta.title = "";
state.ruleForm.meta.icon = "";
state.ruleForm.meta.isHide = "";
state.ruleForm.meta.isKeepAlive = "";
state.ruleForm.meta.isAffix = "";
state.ruleForm.meta.isLink = "";
state.ruleForm.meta.isIframe = "";
state.ruleForm.meta.auth = "";
};
return {
openDialog,
closeDialog,
onSelectIframeChange,
onCancel,
onSubmit,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.system-menu-container {
.system-menu-form {
max-height: 70vh !important;
overflow-y: auto;
overflow-x: hidden;
}
}
</style>

View File

@ -1,16 +1,204 @@
<template>
<div class="system-menu-edit-container"></div>
<div class="system-menu-container">
<el-dialog title="编辑菜单" v-model="isShowDialog" width="769px">
<div class="system-menu-form">
<el-form :model="ruleForm" size="small" label-width="80px">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单名称">
<el-input v-model="ruleForm.meta.title" placeholder="请输入菜单名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="路由名称">
<el-input v-model="ruleForm.name" placeholder="路由名称路由中的name值" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单图标">
<el-input v-model="ruleForm.meta.icon" placeholder="请输入菜单图标" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="组件地址">
<el-input v-model="ruleForm.component" placeholder="组件地址" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否隐藏">
<el-select v-model="ruleForm.meta.isHide" placeholder="请选择是否隐藏" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否缓存">
<el-select v-model="ruleForm.meta.isKeepAlive" placeholder="请选择是否缓存" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否固定">
<el-select v-model="ruleForm.meta.isAffix" placeholder="请选择是否固定" clearable class="w100">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否外链">
<el-select v-model="ruleForm.isLink" placeholder="请选择是否外链" clearable class="w100"
:disabled="ruleForm.meta.isIframe === 'true'">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="是否内嵌">
<el-select v-model="ruleForm.meta.isIframe" placeholder="请选择是否iframe" clearable class="w100"
@change="onSelectIframeChange">
<el-option label="是" value="true"></el-option>
<el-option label="否" value="false"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="链接地址">
<el-input v-model="ruleForm.meta.isLink" placeholder="外链/内嵌时链接地址http:xxx.com" clearable
:disabled="ruleForm.isLink === '' || ruleForm.isLink === 'false'">
</el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="权限标识">
<el-input v-model="ruleForm.meta.auth" placeholder="路由权限标识(多个请用逗号隔开)" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8" class="mb20">
<el-form-item label="菜单排序">
<el-input v-model="ruleForm.menuSort" placeholder="菜单排序" clearable></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="small"> </el-button>
<el-button type="primary" @click="onSubmit" size="small"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs } from "vue";
// import { setBackEndControlRefreshRoutes } from "/@/router/index.ts";
export default {
name: "systemEditMenu",
setup() {
const state = reactive({});
const state = reactive({
isShowDialog: false,
/**
* 参数请参考 `/src/router/index.ts` 中的 `dynamicRoutes` 路由菜单格式请注意参数类型
* 受到 `element plus` 类型 `string/number/object` 影响不可使用 `:value="true"`
* 的写法所以传值到后台时需要转换成布尔值否则页面可能出现玄学
* 路由权限标识为数组格式基本都需要自行转换类型
*/
ruleForm: {
name: "", //
component: "", //
isLink: "", //
menuSort: "", //
meta: {
title: "", //
icon: "", //
isHide: "", //
isKeepAlive: "", //
isAffix: "", //
isLink: "", // `1isLink:true 2`
isIframe: "", // `1isIframe:true 2`
auth: "", //
},
},
});
//
const openDialog = (row) => {
state.ruleForm.name = row.name;
state.ruleForm.component = "";
state.ruleForm.isLink = row.meta.isLink ? "true" : "";
state.ruleForm.menuSort = "";
state.ruleForm.meta.title = row.meta.title;
state.ruleForm.meta.icon = row.meta.icon;
state.ruleForm.meta.isHide = row.meta.isHide ? "true" : "false";
state.ruleForm.meta.isKeepAlive = row.meta.isKeepAlive ? "true" : "false";
state.ruleForm.meta.isAffix = row.meta.isAffix ? "true" : "false";
state.ruleForm.meta.isLink = row.meta.isLink ? row.meta.isLink : "";
state.ruleForm.meta.isIframe = row.meta.isIframe ? "true" : "";
state.ruleForm.meta.auth = row.meta.auth ? row.meta.auth.join(",") : "";
state.isShowDialog = true;
};
//
const closeDialog = (row) => {
state.isShowDialog = false;
};
//
const onSelectIframeChange = () => {
if (state.ruleForm.meta.isIframe === "true") {
state.ruleForm.isLink = "true";
} else {
state.ruleForm.isLink = "";
}
};
//
const onCancel = () => {
closeDialog();
initForm();
};
//
const onSubmit = () => {
console.log(state.ruleForm); //
closeDialog(); //
// setBackEndControlRefreshRoutes() //
};
// `resetFields()` 使
const initForm = () => {
state.ruleForm.name = "";
state.ruleForm.component = "";
state.ruleForm.isLink = "";
state.ruleForm.menuSort = "";
state.ruleForm.meta.title = "";
state.ruleForm.meta.icon = "";
state.ruleForm.meta.isHide = "";
state.ruleForm.meta.isKeepAlive = "";
state.ruleForm.meta.isAffix = "";
state.ruleForm.meta.isLink = "";
state.ruleForm.meta.isIframe = "";
state.ruleForm.meta.auth = "";
};
return {
openDialog,
closeDialog,
onSelectIframeChange,
onCancel,
onSubmit,
...toRefs(state),
};
},
};
</script>
<style scoped lang="scss">
.system-menu-container {
.system-menu-form {
max-height: 70vh !important;
overflow-y: auto;
overflow-x: hidden;
}
}
</style>

View File

@ -9,14 +9,8 @@
<span class="ml10">{{ scope.row.meta.title }}</span>
</template>
</el-table-column>
<el-table-column prop="path" label="路由" show-overflow-tooltip width="150"></el-table-column>
<el-table-column prop="component" label="组件" show-overflow-tooltip></el-table-column>
<el-table-column label="外链" show-overflow-tooltip width="70">
<template #default="scope">
<span v-if="scope.row.meta.isLink && !scope.row.meta.isIframe" class="color-primary"></span>
<span v-else class="color-info"></span>
</template>
</el-table-column>
<el-table-column prop="path" label="路由名称" show-overflow-tooltip width="150"></el-table-column>
<el-table-column prop="component" label="组件地址" show-overflow-tooltip></el-table-column>
<el-table-column label="隐藏" show-overflow-tooltip width="70">
<template #default="scope">
<span v-if="scope.row.meta.isHide" class="color-primary"></span>
@ -35,6 +29,12 @@
<span v-else class="color-info"></span>
</template>
</el-table-column>
<el-table-column label="外链" show-overflow-tooltip width="70">
<template #default="scope">
<span v-if="scope.row.meta.isLink && !scope.row.meta.isIframe" class="color-primary"></span>
<span v-else class="color-info"></span>
</template>
</el-table-column>
<el-table-column label="iframe" show-overflow-tooltip width="70">
<template #default="scope">
<span v-if="scope.row.meta.isLink && scope.row.meta.isIframe" class="color-primary"></span>
@ -48,29 +48,44 @@
</el-table-column>
<el-table-column label="操作" show-overflow-tooltip width="125">
<template #default="scope">
<el-button size="mini" type="text">新增</el-button>
<el-button size="mini" type="text">修改</el-button>
<el-button size="mini" type="text" @click="onOpenAddMenu(scope.row)">新增</el-button>
<el-button size="mini" type="text" @click="onOpenEditMenu(scope.row)">修改</el-button>
<el-button size="mini" type="text" @click="onTabelRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<AddMenu ref="addMenuRef" />
<EditMenu ref="editMenuRef" />
</div>
</template>
<script lang="ts">
import { toRefs, reactive, computed } from "vue";
import { ref, toRefs, reactive, computed } from "vue";
import { ElMessageBox } from "element-plus";
import { useStore } from "/@/store/index.ts";
import AddMenu from "/@/views/system/menu/component/addMenu.vue";
import EditMenu from "/@/views/system/menu/component/editMenu.vue";
export default {
name: "systemMenu",
components: { AddMenu, EditMenu },
setup() {
const store = useStore();
const addMenuRef = ref();
const editMenuRef = ref();
const state = reactive({});
// vuex
const menuTableData = computed(() => {
return store.state.routes;
});
//
const onOpenAddMenu = (row) => {
addMenuRef.value.openDialog(row);
};
//
const onOpenEditMenu = (row) => {
editMenuRef.value.openDialog(row);
};
//
const onTabelRowDel = (row) => {
ElMessageBox.confirm("此操作将永久删除路由, 是否继续?", "提示", {
@ -82,6 +97,10 @@ export default {
.catch(() => {});
};
return {
addMenuRef,
editMenuRef,
onOpenAddMenu,
onOpenEditMenu,
menuTableData,
onTabelRowDel,
...toRefs(state),