菜单管理基本完成
This commit is contained in:
@@ -3,10 +3,10 @@
|
||||
<ku-layout :title="$options.label">
|
||||
<ku-search-bar>
|
||||
<template #left>
|
||||
<el-button type="primary" :icon="CirclePlus">新增一级菜单</el-button>
|
||||
<el-button type="primary" @click="dialog=true">新增一级菜单</el-button>
|
||||
</template>
|
||||
<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>
|
||||
</ku-search-bar>
|
||||
<ku-table :data="tableData" :columns="columns" @list="getTableData()">
|
||||
@@ -17,22 +17,61 @@
|
||||
</template>
|
||||
</ku-table>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import KuLayout from "../components/KuLayout";
|
||||
import KuSearchBar from "../components/KuSearchBar";
|
||||
import {CirclePlus} from "@element-plus/icons-vue";
|
||||
import KuTable from "../components/KuTable";
|
||||
import KuSelect from "../components/KuSelect";
|
||||
|
||||
export default {
|
||||
name: "AppMenu",
|
||||
components: {KuTable, KuSearchBar, KuLayout},
|
||||
components: {KuSelect, KuTable, KuSearchBar, KuLayout},
|
||||
label: "菜单管理",
|
||||
data() {
|
||||
return {
|
||||
CirclePlus,
|
||||
search: {name: null},
|
||||
tableData: [
|
||||
{
|
||||
@@ -49,7 +88,16 @@ export default {
|
||||
{label: "应用模块", prop: "component"},
|
||||
{label: "是否显示", prop: "status", dict: "yesOrNo"},
|
||||
{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: {
|
||||
|
||||
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 $dict from "./dict";
|
||||
|
||||
export const getToken = () => mainStore()?.token
|
||||
export const $confirm = () => {
|
||||
@@ -28,5 +29,5 @@ const $arr2tree = (list, config = {}) => {
|
||||
return result
|
||||
}
|
||||
export default {
|
||||
getToken, $confirm, $arr2tree
|
||||
getToken, $confirm, $arr2tree, $dict
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user