菜单管理基本完成

This commit is contained in:
2023-02-08 23:53:08 +08:00
parent 0655e21a7d
commit a79902651a
4 changed files with 215 additions and 7 deletions

View File

@@ -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: {

View 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
View 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

View File

@@ -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
}