474 lines
15 KiB
Vue
474 lines
15 KiB
Vue
<template>
|
||
<div class="content-height system-menu-manager">
|
||
<div class="title">
|
||
<span>菜单管理</span>
|
||
</div>
|
||
<div class="search">
|
||
<el-row>
|
||
<el-col :span="24">
|
||
<div class="operate-box">
|
||
<el-button @click="addMenu(null, 0)">新增菜单</el-button>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
<div class="table">
|
||
<vxe-table :data="tableData" :empty-render="{name: 'NotData'}" align="left" border
|
||
:tree-config="{transform: true, rowField: 'id', parentField: 'parentId', expandAll: true }"
|
||
v-table-min-height="'calc(100vh - 320px + 44px + 42px)'">
|
||
<vxe-column show-overflow show-header-overflow type="seq" title="序号" width="77"></vxe-column>
|
||
<vxe-column show-overflow show-header-overflow title="名称" width="300" align="center" tree-node>
|
||
<template #default="{ row, level }">
|
||
<div class="menu-image">
|
||
<el-image v-if="level === 0 || level === 2" :src="row.iconHref"></el-image>
|
||
<span>{{row.name}}</span>
|
||
</div>
|
||
</template>
|
||
</vxe-column>
|
||
<vxe-column show-overflow show-header-overflow field="href" title="路径" align="center"></vxe-column>
|
||
<vxe-column show-overflow show-header-overflow field="sort" title="排序" width="60"
|
||
align="center"></vxe-column>
|
||
<vxe-column show-overflow show-header-overflow field="remarks" title="描述" align="center"></vxe-column>
|
||
<vxe-column show-overflow show-header-overflow title="操作" width="200" fixed="right" align="center">
|
||
<template #default="{ row, level }">
|
||
<el-button type="text" @click="addMenu(row, level)">添加子菜单</el-button>
|
||
<el-button type="text" @click="modifyRow(row, level)">编辑</el-button>
|
||
<el-button type="text" class="del-btn" @click="deleteRow(row)">删除</el-button>
|
||
</template>
|
||
</vxe-column>
|
||
</vxe-table>
|
||
</div>
|
||
<!-- 新增/编辑/查看 菜单 -->
|
||
<el-dialog :title="dialogTitle + '菜单'" :visible.sync="dialogMenu" width="750px" :close-on-click-modal="false"
|
||
:close-on-press-escape="false" modal-append-to-body append-to-body>
|
||
<div class="menu-form">
|
||
<el-form :model="form" label-width="186px" :disabled="mode === 'view'">
|
||
<el-form-item label="菜单名称:" required>
|
||
<el-input v-model="form.name" maxlength="20" placeholder="请输入菜单名称" show-word-limit></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="菜单路径:">
|
||
|
||
<el-input v-model="form.href" placeholder="请输入菜单路径" show-word-limit></el-input>
|
||
|
||
<!--<el-select v-model="form.href" filterable placeholder="请选择菜单路径">-->
|
||
<!--<el-option label="-" value=""></el-option>-->
|
||
<!--<template v-for="item in pathList">-->
|
||
<!--<el-option :label="item" :value="item" :key="item"></el-option>-->
|
||
<!--</template>-->
|
||
<!--</el-select>-->
|
||
</el-form-item>
|
||
<el-form-item label="菜单图标:" class="icon-menu-item" v-if="level === 0 || level === 2">
|
||
<el-upload action="#" :http-request="(params)=>uploadFile(params)"
|
||
:show-file-list="false" :before-upload="beforeUploadFile">
|
||
<span class="icon-menu-text">
|
||
<img v-if="form.icon" :src="form.iconHref" alt="" class="icon-menu">
|
||
<i v-else class="el-icon-plus"></i>
|
||
</span>
|
||
</el-upload>
|
||
</el-form-item>
|
||
<el-form-item label="菜单排序:" required>
|
||
<el-input-number v-model="form.sort" controls-position="right" :min="1" :step="1"
|
||
step-strictly></el-input-number>
|
||
</el-form-item>
|
||
<el-form-item label="菜单描述:">
|
||
<el-input v-model="form.remarks" maxlength="500" type="textarea" placeholder="请填写"
|
||
show-word-limit></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="跳转网页:" class="jumpClass">
|
||
<el-checkbox v-model="form.isUrl" true-label="1" false-label="0"></el-checkbox>
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="done">
|
||
<el-button v-if="mode !== 'view'" type="primary" @click="postOrPutSysMenu">确定</el-button>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { fileType } from '@/utils/fileType'
|
||
|
||
export default {
|
||
name: 'MenuManager',
|
||
data () {
|
||
return {
|
||
form: {
|
||
name: '', // 名称
|
||
href: '', // 路径
|
||
icon: '', // 图标
|
||
iconHref: '', // 图标路径
|
||
sort: '', // 排序
|
||
remarks: '', // 描述
|
||
id: '',
|
||
parentId: '',
|
||
isUrl: 0
|
||
},
|
||
tableData: [],
|
||
dialogMenu: false,
|
||
mode: '',
|
||
pathList: [],
|
||
level: 0
|
||
}
|
||
},
|
||
methods: {
|
||
init () {
|
||
this.sysMenuFindAllMenus()
|
||
this.getRouterPath()
|
||
},
|
||
// 菜单
|
||
sysMenuFindAllMenus () {
|
||
this.$api.menu.sysMenuFindAllMenus().then(({ data }) => {
|
||
this.tableData = data.filter(item => item.id !== '6f6fafb4a7' && item.isButton=='0').sort((a, b) => {
|
||
return a.sort - b.sort
|
||
})
|
||
})
|
||
},
|
||
// 新增弹窗
|
||
addMenu (row, level) {
|
||
this.mode = 'add'
|
||
this.level = level + 1
|
||
this.form = {
|
||
name: '', // 名称
|
||
href: '', // 路径
|
||
icon: '', // 图标
|
||
iconHref: '', // 图标路径
|
||
sort: '', // 排序
|
||
remarks: '', // 描述
|
||
id: '',
|
||
parentId: '',
|
||
isUrl: 0
|
||
}
|
||
this.form.parentId = row ? row.id : '6f6fafb4a7'
|
||
this.dialogMenu = true
|
||
},
|
||
// 新增 修改
|
||
postOrPutSysMenu () {
|
||
if (!this.form.name) {
|
||
return this.$message.warning('请输入菜单名称')
|
||
}
|
||
if (this.level === 0 || this.level === 2) {
|
||
// if (!this.form.icon) {
|
||
// return this.$message.warning('请上传菜单图标');
|
||
// }
|
||
}
|
||
if (this.mode === 'add') {
|
||
this.$api.menu.postSysMenu(this.form).then(_ => {
|
||
this.$message.success('操作成功')
|
||
this.dialogMenu = false
|
||
this.sysMenuFindAllMenus()
|
||
})
|
||
}
|
||
if (this.mode === 'modify') {
|
||
this.$api.menu.putSysMenu(this.form).then(_ => {
|
||
this.$message.success('操作成功')
|
||
this.dialogMenu = false
|
||
this.sysMenuFindAllMenus()
|
||
})
|
||
}
|
||
},
|
||
// 图标上传
|
||
uploadFile (params) {
|
||
const fd = new FormData()
|
||
fd.append('file', params.file)
|
||
this.$api.report.reportUploadPicFile(fd).then(({ data }) => {
|
||
this.form.icon = data.key
|
||
this.form.iconHref = data.value
|
||
})
|
||
},
|
||
beforeUploadFile (file) {
|
||
const isType = (file.type === fileType.png || file.type === fileType.jpg)
|
||
const isSize = file.size / 1024 / 1024 < 2
|
||
if (!isType) {
|
||
this.$message.error('仅能上传 png|jpg 格式文件')
|
||
}
|
||
if (!isSize) {
|
||
this.$message.error('您最大可上传2M文件')
|
||
}
|
||
return isType && isSize
|
||
},
|
||
// 删除
|
||
deleteRow (row) {
|
||
this.$confirm('此操作将删除所选数据, 是否继续?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
this.$api.menu.sysMenuDeleteId({ ids: row.id }).then(_ => {
|
||
this.$message.success('操作成功')
|
||
this.sysMenuFindAllMenus()
|
||
})
|
||
})
|
||
},
|
||
// 编辑
|
||
modifyRow (row, level) {
|
||
this.level = level
|
||
this.mode = 'modify'
|
||
this.form = JSON.parse(JSON.stringify(row))
|
||
this.dialogMenu = true
|
||
},
|
||
// 获取存在路径
|
||
getRouterPath () {
|
||
const pathList = []
|
||
const pathFun = (data, url) => {
|
||
data.forEach(item => {
|
||
if (item.children) {
|
||
pathFun(item.children, item.path)
|
||
} else {
|
||
pathList.push(`${url ? (url + '/') : ''}${item.path}`)
|
||
}
|
||
})
|
||
}
|
||
pathFun(this.$router.options.routes)
|
||
this.pathList = pathList
|
||
}
|
||
},
|
||
computed: {
|
||
dialogTitle () {
|
||
switch (this.mode) {
|
||
case 'add':
|
||
return '新增'
|
||
case 'modify':
|
||
return '编辑'
|
||
case 'view':
|
||
return '查看'
|
||
}
|
||
}
|
||
},
|
||
created () {
|
||
this.init()
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.jumpClass .el-checkbox {
|
||
line-height: 36px;
|
||
}
|
||
|
||
.system-menu-manager {
|
||
.title {
|
||
border-bottom: 1px solid #EBEEF5;
|
||
height: 42px;
|
||
line-height: 42px;
|
||
margin: 0 18px 0 22px;
|
||
|
||
span {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #262626;
|
||
}
|
||
}
|
||
|
||
.search {
|
||
.search-box-left {
|
||
padding-top: 20px;
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
|
||
label {
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: #595959;
|
||
margin-right: 5px;
|
||
padding-left: 22px;
|
||
}
|
||
|
||
.year {
|
||
::v-deep .el-input__inner {
|
||
padding: 0 15px !important;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-input {
|
||
width: 167px;
|
||
margin-right: 5px;
|
||
}
|
||
|
||
@media screen and (max-width: 1366px) {
|
||
::v-deep .el-input {
|
||
width: 135px;
|
||
margin-right: 5px;
|
||
}
|
||
}
|
||
|
||
::v-deep .el-button {
|
||
float: right;
|
||
}
|
||
}
|
||
|
||
.search-box-right {
|
||
padding-top: 20px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
padding-right: 14px;
|
||
}
|
||
|
||
.operate-box {
|
||
padding-left: 13px;
|
||
padding-bottom: 11px;
|
||
padding-top: 18px;
|
||
}
|
||
}
|
||
|
||
.table {
|
||
margin: 0 14px 0 13px;
|
||
padding-bottom: 10px;
|
||
|
||
// ::v-deep .el-icon-circle-plus,
|
||
// ::v-deep .el-icon-remove{
|
||
// font-size: 18px;
|
||
// margin-top: -4px;
|
||
// margin-left: -1.5px;
|
||
// }
|
||
|
||
.menu-image {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
position: relative;
|
||
z-index: 10;
|
||
|
||
::v-deep .el-image {
|
||
width: 30px;
|
||
height: 30px;
|
||
margin: 0 5px;
|
||
|
||
.el-image__error {
|
||
font-size: 12px;
|
||
line-height: 12px;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
::v-deep .el-pagination {
|
||
margin-top: 13px;
|
||
padding-left: 20px;
|
||
padding-bottom: 10px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.menu-form {
|
||
padding-top: 26px;
|
||
|
||
::v-deep .el-form {
|
||
padding-right: 79px;
|
||
|
||
.icon-menu-item .el-form-item__content > div:first-child {
|
||
display: flex !important;
|
||
}
|
||
|
||
.el-form-item {
|
||
margin-bottom: 10px;
|
||
|
||
.el-form-item__label {
|
||
height: 36px;
|
||
line-height: 36px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #262626;
|
||
}
|
||
|
||
.el-input__inner {
|
||
min-height: 36px;
|
||
}
|
||
|
||
.el-input__inner,
|
||
.el-textarea__inner {
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: #434343;
|
||
}
|
||
|
||
.el-select {
|
||
width: 100%;
|
||
}
|
||
|
||
.el-date-editor {
|
||
width: 100%;
|
||
|
||
.el-input__inner {
|
||
padding-left: 15px;
|
||
}
|
||
|
||
.el-input__suffix {
|
||
font-size: 16px;
|
||
margin-top: 2px;
|
||
}
|
||
}
|
||
|
||
.icon-auth {
|
||
.el-icon-arrow-up {
|
||
margin-top: 2px;
|
||
transform: rotateZ(0) !important;
|
||
}
|
||
|
||
.el-icon-arrow-up:before {
|
||
content: '';
|
||
background: url("../../assets/imgs/icon-user.png") no-repeat center center;
|
||
display: inline-block;
|
||
width: 12px;
|
||
height: 14px;
|
||
background-size: 100% 100%;
|
||
}
|
||
}
|
||
|
||
.el-input-number {
|
||
width: 100%;
|
||
|
||
input {
|
||
text-align: left;
|
||
}
|
||
|
||
.el-input-number__decrease,
|
||
.el-input-number__increase {
|
||
height: 18px;
|
||
line-height: 18px;
|
||
font-size: 14px;
|
||
width: 30px;
|
||
}
|
||
}
|
||
|
||
.icon-menu-text {
|
||
display: flex;
|
||
width: 36px;
|
||
height: 36px;
|
||
overflow: hidden;
|
||
border: 1px dashed #8C8C8C;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #8C8C8C;
|
||
font-size: 18px;
|
||
|
||
.icon-menu {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.el-button {
|
||
width: 80px;
|
||
height: 36px;
|
||
padding: 0;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
.done {
|
||
text-align: center;
|
||
padding: 40px 0;
|
||
|
||
::v-deep .el-button {
|
||
width: 80px;
|
||
height: 36px;
|
||
padding: 0;
|
||
}
|
||
}
|
||
}
|
||
</style>
|