菜单管理基本完成
This commit is contained in:
@@ -3,10 +3,10 @@
|
|||||||
<ku-layout :title="$options.label">
|
<ku-layout :title="$options.label">
|
||||||
<ku-search-bar>
|
<ku-search-bar>
|
||||||
<template #left>
|
<template #left>
|
||||||
<el-button type="primary" :icon="CirclePlus">新增一级菜单</el-button>
|
<el-button type="primary" @click="dialog=true">新增一级菜单</el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<el-input v-model="search.name" placeholder="搜索菜单名称" @click="page.current=1,getTableData()" clearable/>
|
<el-input v-model="search.name" placeholder="搜索菜单名称" @click="getTableData()" clearable/>
|
||||||
</template>
|
</template>
|
||||||
</ku-search-bar>
|
</ku-search-bar>
|
||||||
<ku-table :data="tableData" :columns="columns" @list="getTableData()">
|
<ku-table :data="tableData" :columns="columns" @list="getTableData()">
|
||||||
@@ -17,22 +17,61 @@
|
|||||||
</template>
|
</template>
|
||||||
</ku-table>
|
</ku-table>
|
||||||
</ku-layout>
|
</ku-layout>
|
||||||
|
<el-dialog title="编辑菜单" v-model="dialog" draggable @close="form={}" width="500">
|
||||||
|
<el-form ref="MenuForm" :model="form" label-width="80px" :rules="rules">
|
||||||
|
<el-form-item label="菜单名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="菜单类型" prop="type">
|
||||||
|
<ku-select v-model="form.type" clearable :selectList="$dict.getDict('menuType')"/>
|
||||||
|
</el-form-item>
|
||||||
|
<template v-if="form.type==0">
|
||||||
|
<el-form-item label="菜单图标" prop="style">
|
||||||
|
<el-input v-model="form.style" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-if="form.type==1">
|
||||||
|
<el-form-item label="菜单图标" prop="style">
|
||||||
|
<el-input v-model="form.style" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="路由名" prop="route">
|
||||||
|
<span v-text="form.route||'提交保存后会自动生成'"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="菜单应用" prop="component">
|
||||||
|
<el-input v-model="form.component" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="路径(path)" prop="path">
|
||||||
|
<el-input v-model="form.path" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-if="form.type==2">
|
||||||
|
<el-form-item label="权限码" prop="permission">
|
||||||
|
<el-input v-model="form.permission" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<el-form-item label="显示菜单" prop="status">
|
||||||
|
<ku-select v-model="form.status" clearable :selectList="$dict.getDict('yesOrNo')"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="form.type<2" label="排序" prop="showIndex">
|
||||||
|
<el-input v-model="form.showIndex" placeholder="请输入" clearable/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-dialog>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import KuLayout from "../components/KuLayout";
|
import KuLayout from "../components/KuLayout";
|
||||||
import KuSearchBar from "../components/KuSearchBar";
|
import KuSearchBar from "../components/KuSearchBar";
|
||||||
import {CirclePlus} from "@element-plus/icons-vue";
|
|
||||||
import KuTable from "../components/KuTable";
|
import KuTable from "../components/KuTable";
|
||||||
|
import KuSelect from "../components/KuSelect";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "AppMenu",
|
name: "AppMenu",
|
||||||
components: {KuTable, KuSearchBar, KuLayout},
|
components: {KuSelect, KuTable, KuSearchBar, KuLayout},
|
||||||
label: "菜单管理",
|
label: "菜单管理",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
CirclePlus,
|
|
||||||
search: {name: null},
|
search: {name: null},
|
||||||
tableData: [
|
tableData: [
|
||||||
{
|
{
|
||||||
@@ -49,7 +88,16 @@ export default {
|
|||||||
{label: "应用模块", prop: "component"},
|
{label: "应用模块", prop: "component"},
|
||||||
{label: "是否显示", prop: "status", dict: "yesOrNo"},
|
{label: "是否显示", prop: "status", dict: "yesOrNo"},
|
||||||
{label: "排序", prop: "showIndex"},
|
{label: "排序", prop: "showIndex"},
|
||||||
]
|
],
|
||||||
|
dialog: false,
|
||||||
|
form: {},
|
||||||
|
rules: {
|
||||||
|
name: [{required: true, message: "请输入 菜单名称"}],
|
||||||
|
type: [{required: true, message: "请选择 菜单类型"}],
|
||||||
|
status: [{required: true, message: "请选择 显示菜单"}],
|
||||||
|
showIndex: [{required: true, message: "请输入 排序"}],
|
||||||
|
permission: [{required: true, message: "请输入 权限码"}],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
85
web/src/components/KuSelect.vue
Normal file
85
web/src/components/KuSelect.vue
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<div class="KuSelect">
|
||||||
|
<el-select clearable :modelValue="modelValue" :filterable="isAction" v-bind="$attrs"
|
||||||
|
@change="v=>$emit('update:modelValue',v)">
|
||||||
|
<template v-if="isAction">
|
||||||
|
<el-option v-for="op in actionOps" :key="op.id" :label="op[actionProp.label]" :value="op[actionProp.value]"/>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-option v-for="(item, index) in ops" :key="index" :label="item.dictName" :value="item.dictValue"/>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'KuSelect',
|
||||||
|
watch: {
|
||||||
|
instance: {
|
||||||
|
deep: true,
|
||||||
|
handler(v) {
|
||||||
|
v && this.isAction && !this.options.toString() && this.getOptions()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modelValue(v) {
|
||||||
|
this.$emit("select", this.isAction ? this.options.find(e => e[this.actionProp.value] == v) :
|
||||||
|
this.selectList.find(e => e.dictValue == v))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {default: null},
|
||||||
|
selectList: {default: () => []},
|
||||||
|
instance: Function,
|
||||||
|
action: {default: ""},
|
||||||
|
prop: {default: () => ({})},
|
||||||
|
dict: String
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: [],
|
||||||
|
filter: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isAction: v => !!v.action,
|
||||||
|
actionOps() {
|
||||||
|
return this.options.filter(e => !this.filter || e[this.actionProp.label].indexOf(this.filter) > -1)
|
||||||
|
},
|
||||||
|
actionProp() {
|
||||||
|
return {
|
||||||
|
label: 'label',
|
||||||
|
value: 'id',
|
||||||
|
...this.prop
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ops: v => v.dict ? v.$dict.getDict(v.dict) : v.selectList
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getOptions() {
|
||||||
|
this.instance?.post(this.action, null, {
|
||||||
|
params: {size: 999}
|
||||||
|
}).then(res => {
|
||||||
|
if (res?.data) {
|
||||||
|
this.options = res.data.records || res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getOptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.KuSelect {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.el-select) {
|
||||||
|
width: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
web/src/utils/dict.js
Normal file
74
web/src/utils/dict.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import http from "./axios";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装字典工具类
|
||||||
|
*/
|
||||||
|
const $dict = {
|
||||||
|
url: "/api/dict/listByCodes",
|
||||||
|
loading: [],
|
||||||
|
resolves: [],
|
||||||
|
getStorage() {
|
||||||
|
const dicts = JSON.parse(localStorage.getItem('dicts') || null)
|
||||||
|
return dicts?.data || dicts || [];
|
||||||
|
},
|
||||||
|
getData(codeList) {
|
||||||
|
codeList = [codeList].flat().filter(Boolean).toString()
|
||||||
|
return http.post(this.url, null, {
|
||||||
|
withoutToken: true, params: {codeList}
|
||||||
|
}).then(res => res?.data && this.setStorage(res.data))
|
||||||
|
},
|
||||||
|
load(...code) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.resolves.push(resolve)
|
||||||
|
if (this.loading.length == 2) {
|
||||||
|
const [timer, codes] = this.loading;
|
||||||
|
clearTimeout(timer)
|
||||||
|
code = Array.from(new Set([codes, code].flat()))
|
||||||
|
}
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
this.getData(code).then(() => Promise.all(this.resolves.map(e => e())).then(() => this.resolves = []))
|
||||||
|
}, 500)
|
||||||
|
this.loading = [timer, code]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setStorage(data) {
|
||||||
|
let ds = this.getStorage()
|
||||||
|
data.map(p => {
|
||||||
|
if (ds.some(d => d.key == p.key)) {
|
||||||
|
const index = ds.findIndex(d => d.key == p.key)
|
||||||
|
ds.splice(index, 1, p)
|
||||||
|
} else {
|
||||||
|
ds.push(p)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
localStorage.setItem("dicts", JSON.stringify([ds].flat()))
|
||||||
|
},
|
||||||
|
getDict(key) {
|
||||||
|
let dict = this.getStorage().find(e => e.key == key)
|
||||||
|
!dict && console.warn("字典%s缺少加载...", key)
|
||||||
|
return dict ? dict.values : []
|
||||||
|
},
|
||||||
|
getValue(key, label) {
|
||||||
|
let dict = this.getDict(key)
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.find(v => v.dictName == label)
|
||||||
|
return item ? item.dictValue : label
|
||||||
|
} else return label
|
||||||
|
},
|
||||||
|
getLabel(key, value) {
|
||||||
|
let dict = this.getDict(key)
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.find(v => v.dictValue == value)
|
||||||
|
return item ? item.dictName : value
|
||||||
|
} else return value
|
||||||
|
},
|
||||||
|
getColor(key, value) {
|
||||||
|
let dict = this.getDict(key)
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.find(v => v.dictValue == value)
|
||||||
|
return item ? item.dictColor : value
|
||||||
|
} else return value
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default $dict
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import {mainStore} from "./store";
|
import {mainStore} from "./store";
|
||||||
|
import $dict from "./dict";
|
||||||
|
|
||||||
export const getToken = () => mainStore()?.token
|
export const getToken = () => mainStore()?.token
|
||||||
export const $confirm = () => {
|
export const $confirm = () => {
|
||||||
@@ -28,5 +29,5 @@ const $arr2tree = (list, config = {}) => {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
getToken, $confirm, $arr2tree
|
getToken, $confirm, $arr2tree, $dict
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user