|
|
<template>
|
|
|
<el-card class="box-card" shadow="hover">
|
|
|
<div slot="header" class="clearfix">
|
|
|
<span style="border-left: 3px solid #338de3ff; padding-left: 6px"
|
|
|
>快捷菜单</span
|
|
|
>
|
|
|
<Button v-if="/^\/system+/.test($route.path)" style="float: right" size="small" type="primary" @click="isShow = true">新增菜单</Button>
|
|
|
</div>
|
|
|
|
|
|
<div class="menu-container">
|
|
|
<div v-for="(item, index) in myMenus" :key="item.id" class="menu-item">
|
|
|
<div style="display: flex;align-items: center;" @click="linkTo(item)">
|
|
|
<el-image v-if="item.image" style="max-width: 26px;margin-right: 6px;" fit="contain" :src="item.image ? item.image.url : ''">
|
|
|
<template #error>
|
|
|
<Icon type="ios-alert" />
|
|
|
</template>
|
|
|
</el-image>
|
|
|
{{ item.name }}
|
|
|
</div>
|
|
|
|
|
|
<div class="operate-btn" v-if="/^\/system+/.test($route.path)">
|
|
|
<Icon color="#4d8bdc" class="operate-btn__item" type="ios-create-outline" @click="editMenu(item)"/>
|
|
|
<Icon color="#4d8bdc" class="operate-btn__item" type="ios-trash-outline" @click="destroyMenu(item)"/>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<template v-if="/^\/system+/.test($route.path)">
|
|
|
<xy-dialog title="快捷菜单" type="form" :is-show.sync="isShow" :form="form" :rules="rule" @submit="submit">
|
|
|
<template #url>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
<span style="color: red; font-weight: 600; padding-right: 4px"
|
|
|
>*</span
|
|
|
>菜单 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-cascader :value="form.url"
|
|
|
:show-all-levels="false"
|
|
|
ref="cascaderInput"
|
|
|
:options="menus"
|
|
|
style="width: 300px;"
|
|
|
@change="cascaderPick"
|
|
|
:props="{ label: 'name',value: 'path' }">
|
|
|
</el-cascader>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #name>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
描述 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-input v-model="form.name" clearable style="width: 300px;">
|
|
|
</el-input>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #sort>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
排序 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-input-number :controls="false" :precision="0" v-model="form.sort" clearable style="width: 300px;">
|
|
|
</el-input-number>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #status>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
状态 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-switch style="width: 300px;" v-model="form.status" :inactive-value="0" :active-value="1" inactive-text="禁用" active-text="启用"></el-switch>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #method>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
打开方式 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-select v-model="form.method" style="width: 300px;">
|
|
|
<el-option v-for="(item) in [{ label: '跳转',value: 'self' },{ label: '新页面',value: 'blank' }]" :value="item.value" :label="item.label">
|
|
|
</el-option>
|
|
|
</el-select>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #image_id>
|
|
|
<div class="xy-table-item">
|
|
|
<div class="xy-table-item-label">
|
|
|
图标 :
|
|
|
</div>
|
|
|
<div class="xy-table-item-content">
|
|
|
<el-upload
|
|
|
style="width: 300px"
|
|
|
ref="upload"
|
|
|
:limit="1"
|
|
|
:on-success="successHandle"
|
|
|
:before-upload="uploadBefore"
|
|
|
accept=".jpg,.png,.gif"
|
|
|
:action="action"
|
|
|
:file-list="fileList"
|
|
|
:auto-upload="false"
|
|
|
:on-remove="removeHande"
|
|
|
>
|
|
|
<el-button slot="trigger" size="small" type="primary"
|
|
|
>选取文件</el-button
|
|
|
>
|
|
|
<el-button
|
|
|
style="margin-left: 10px"
|
|
|
size="small"
|
|
|
type="success"
|
|
|
@click="$refs['upload'].submit()"
|
|
|
>开始上传</el-button
|
|
|
>
|
|
|
<div slot="tip" class="el-upload__tip">
|
|
|
支持文件格式: .jpg .png .gif
|
|
|
<br />单个文件不能超过50M
|
|
|
</div>
|
|
|
</el-upload>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</xy-dialog>
|
|
|
</template>
|
|
|
</el-card>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { index, show, save, destroy } from "@/api/system/diyMenu";
|
|
|
import { listmenu } from "@/api/system/menu";
|
|
|
import { deepCopy } from '@/utils'
|
|
|
export default {
|
|
|
name: "card7",
|
|
|
layout: {
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
w: 4,
|
|
|
h: 5,
|
|
|
i: "8",
|
|
|
name: "快捷菜单",
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
fileList: [],
|
|
|
action: process.env.VUE_APP_UPLOAD_API,
|
|
|
myMenus: [],
|
|
|
isShow: false,
|
|
|
menus: [],
|
|
|
form: {
|
|
|
url: "",
|
|
|
name: "",
|
|
|
sort: "",
|
|
|
status: "",
|
|
|
method: "",
|
|
|
image_id: "",
|
|
|
fileList: [],
|
|
|
},
|
|
|
rule: {
|
|
|
url: [
|
|
|
{
|
|
|
required: true,
|
|
|
message: "请选择菜单",
|
|
|
},
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
linkTo (item) {
|
|
|
if (item.method === 'self') {
|
|
|
this.$router.push(item.url)
|
|
|
return
|
|
|
}
|
|
|
if (item.method === 'blank') {
|
|
|
window.open(this.$router.resolve({
|
|
|
path: item.url
|
|
|
}).href,'_blank')
|
|
|
}
|
|
|
},
|
|
|
//上传
|
|
|
successHandle(response, file, fileList) {
|
|
|
this.fileList = fileList;
|
|
|
},
|
|
|
removeHande(file, fileList) {
|
|
|
this.fileList = fileList;
|
|
|
},
|
|
|
uploadBefore(file) {
|
|
|
console.log(file);
|
|
|
if (file.size / 1000 > 50 * 1024) {
|
|
|
this.$message({
|
|
|
type: "warning",
|
|
|
message: "上传图片大小超过50M!",
|
|
|
});
|
|
|
return false;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
async getMenu () {
|
|
|
const formatMenu = (arr) => {
|
|
|
arr.forEach(item => {
|
|
|
if (item.children) {
|
|
|
item.children.length === 0 ? delete item.children : formatMenu(item.children)
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
this.menus = (await listmenu())
|
|
|
formatMenu(this.menus)
|
|
|
},
|
|
|
|
|
|
async getDiymenu () {
|
|
|
this.myMenus = (await index({
|
|
|
page: 1,
|
|
|
page_size: 999,
|
|
|
sort_name: "sort"
|
|
|
},true)).data
|
|
|
},
|
|
|
|
|
|
cascaderPick (e) {
|
|
|
const pathHandler = (path) => {
|
|
|
if(!path || path?.includes('#') || path == ''){
|
|
|
return '/'
|
|
|
}
|
|
|
if(/^\^/.test(path)){
|
|
|
return path.replace(/^\^+/g,"")
|
|
|
}
|
|
|
if(/^\$/.test(path)){
|
|
|
return path.replace(/^\$+/g,"")
|
|
|
}
|
|
|
return path
|
|
|
}
|
|
|
this.form.url = pathHandler(e?.at(-1)) || ''
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
this.form.name = this.$refs['cascaderInput']?.presentText
|
|
|
})
|
|
|
},
|
|
|
|
|
|
async submit () {
|
|
|
this.form.image_id = this.fileList[0]?.response?.id
|
|
|
await save(this.form)
|
|
|
this.$message({
|
|
|
type: "success",
|
|
|
message: "保存成功"
|
|
|
})
|
|
|
await this.getDiymenu()
|
|
|
this.isShow = false;
|
|
|
this.form = {
|
|
|
url: "",
|
|
|
name: "",
|
|
|
sort: "",
|
|
|
status: "",
|
|
|
method: ""
|
|
|
}
|
|
|
},
|
|
|
|
|
|
destroyMenu (item) {
|
|
|
this.$confirm('确认要删除, 是否继续?', '提示', {
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning'
|
|
|
}).then(() => {
|
|
|
destroy({
|
|
|
id: item.id
|
|
|
}).then(res => {
|
|
|
this.$message({
|
|
|
type: 'success',
|
|
|
message: '删除成功!'
|
|
|
});
|
|
|
this.getDiymenu()
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
|
|
|
async editMenu (item) {
|
|
|
const res = deepCopy(item)
|
|
|
this.form = Object.assign({
|
|
|
url: "",
|
|
|
name: "",
|
|
|
sort: "",
|
|
|
status: "",
|
|
|
method: ""
|
|
|
},res)
|
|
|
this.isShow = true;
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
},
|
|
|
created() {
|
|
|
this.getMenu()
|
|
|
this.getDiymenu()
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
::v-deep .el-input__inner {
|
|
|
text-align: left;
|
|
|
}
|
|
|
.xy-table-item-label {
|
|
|
width: 158px;
|
|
|
}
|
|
|
|
|
|
.menu-container {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
.menu-item {
|
|
|
background: $primaryColor;
|
|
|
color: #fff;
|
|
|
border-radius: 5px;
|
|
|
|
|
|
padding: 10px 20px;
|
|
|
position: relative;
|
|
|
margin: 5px;
|
|
|
|
|
|
.operate-btn {
|
|
|
display: flex;
|
|
|
|
|
|
position: absolute;
|
|
|
top: -10px;
|
|
|
left: 8%;
|
|
|
&__item {
|
|
|
background: #fff;
|
|
|
zoom: .95;
|
|
|
border: 1px $primaryColor solid;
|
|
|
padding: 3px;
|
|
|
border-radius: 100%;
|
|
|
cursor: pointer;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style>
|