新增字典并完善菜单模块
This commit is contained in:
		
							
								
								
									
										120
									
								
								web/src/apps/core/AppDictionary/AppDictionary.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								web/src/apps/core/AppDictionary/AppDictionary.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| <template> | ||||
|   <section class="AppDictionary"> | ||||
|     <ku-layout v-if="!showDetail" :title="$options.label"> | ||||
|       <ku-search-bar> | ||||
|         <template #left> | ||||
|           <el-button type="primary" size="small" icon="iconfont iconAdd" @click="addDict">添加</el-button> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <el-input size="small" v-model="search.condition" placeholder="数据项" clearable | ||||
|                     @change="page.current=1,getDicts()" prefix-icon="iconfont iconSearch"/> | ||||
|         </template> | ||||
|       </ku-search-bar> | ||||
|       <el-table :data="dictList" header-cell-class-name="table-header" tooltip-effect="light" | ||||
|                 row-class-name="table-row" cell-class-name="table-cell" @expand-change="getDictInfo"> | ||||
|         <el-table-column type="expand"> | ||||
|           <el-row slot-scope="{row}" type="flex" align="middle" style="flex-wrap: wrap"> | ||||
|             <el-tag v-for="(op,i) in row.children||[]" :key="i" style="margin: 4px">{{ op.dictKey }}|{{ | ||||
|                 op.dictValue | ||||
|               }} | ||||
|               {{ op.color ? '| ' + op.color : '' }} | ||||
|             </el-tag> | ||||
|           </el-row> | ||||
|         </el-table-column> | ||||
|         <el-table-column align="center" label="数据项" prop="code"/> | ||||
|         <el-table-column align="center" label="数据项名称" prop="dictValue"/> | ||||
|         <el-table-column align="center" label="操作"> | ||||
|           <div slot-scope="{row}"> | ||||
|             <el-button type="text" @click="openDetail(row.code)" v-text="'编辑'"/> | ||||
|             <el-button type="text" @click="handleDelete(row.id)" v-text="'删除'"/> | ||||
|           </div> | ||||
|         </el-table-column> | ||||
|         <div slot="empty" class="no-data"/> | ||||
|       </el-table> | ||||
|     </ku-layout> | ||||
|     <dict-detail v-else :permissions="permissions"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import DictDetail from "./dictDetail"; | ||||
| import KuLayout from "../../../components/KuLayout"; | ||||
| import KuSearchBar from "../../../components/KuSearchBar"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppDictionary", | ||||
|   components: {KuSearchBar, KuLayout, DictDetail}, | ||||
|   label: "数据字典", | ||||
|   props: { | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     showDetail() { | ||||
|       return this.$route.hash == "#add" | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       page: {current: 1, total: 0, size: 10}, | ||||
|       search: {condition: ""}, | ||||
|       dictList: [] | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getDicts() { | ||||
|       this.$http.post("/api/dict/list").then(res => { | ||||
|         this.dictList = res.data | ||||
|       }) | ||||
|     }, | ||||
|     addDict() { | ||||
|       this.$router.push({hash: "#add"}) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       this.$confirm("确定要删除该数据项吗?", { | ||||
|         type: "error" | ||||
|       }).then(() => { | ||||
|         this.$http.post("/api/dict/remove", null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.getDicts(); | ||||
|             this.$message.success("删除成功!") | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     openDetail(code) { | ||||
|       this.$router.push({query: {code}, hash: "#add"}) | ||||
|     }, | ||||
|     handleSizeChange(val) { | ||||
|       this.page.size = val; | ||||
|       this.getDicts(); | ||||
|     }, | ||||
|     getDictInfo(row) { | ||||
|       if (row.detail.length) { | ||||
|         row.detail = [] | ||||
|       } else { | ||||
|         this.getDict(row.id).then(res => { | ||||
|           if (res && res.data) { | ||||
|             row.detail = res.data.dictionaryDetails || [] | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|     getDict(dictionaryId) { | ||||
|       return this.$http.post("/admin/dictionary/queryDictDetail", null, { | ||||
|         params: {dictionaryId} | ||||
|       }) | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDicts() | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .AppDictionary { | ||||
|   height: 100%; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										170
									
								
								web/src/apps/core/AppDictionary/dictDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								web/src/apps/core/AppDictionary/dictDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| <template> | ||||
|   <section class="dictDetail"> | ||||
|     <ku-layout title="字典信息" @back="$router.push({})"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <el-form ref="DictForm" :model="form" :rules="rules" size="small" label-width="110px"> | ||||
|           <el-form-item required label="字典:" prop="code"> | ||||
|             <el-input v-model="form.code" clearable placeholder="请输入..."/> | ||||
|           </el-form-item> | ||||
|           <el-form-item required label="备注:" prop="name"> | ||||
|             <el-input v-model="form.name" clearable placeholder="请输入..."/> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-card> | ||||
|       <ai-card title="数据值"> | ||||
|         <template #right> | ||||
|           <el-button type="text" icon="iconfont iconAdd" @click="form.children.push({name:'',value:'',editable:true})"> | ||||
|             添加 | ||||
|           </el-button> | ||||
|         </template> | ||||
|         <template #content> | ||||
|           <el-table border :data="form.children" header-cell-class-name="table-header" cell-class-name="table-cell"> | ||||
|             <el-table-column align="center" label="值"> | ||||
|               <div slot-scope="{row}"> | ||||
|                 <el-input size="small" v-if="row.editable" v-model="row.value" clearable/> | ||||
|                 <span v-else>{{ row.dictKey }}</span> | ||||
|               </div> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="描述"> | ||||
|               <div slot-scope="{row}"> | ||||
|                 <el-input size="small" v-if="row.editable" v-model="row.name" clearable/> | ||||
|                 <span v-else>{{ row.dictValue }}</span> | ||||
|               </div> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="颜色"> | ||||
|               <div slot-scope="{row}"> | ||||
|                 <el-color-picker v-if="row.editable" v-model="row.dictColor"/> | ||||
|                 <span v-else>{{ row.dictColor || '未设置' }}</span> | ||||
|               </div> | ||||
|             </el-table-column> | ||||
|             <el-table-column align="center" label="操作" width="109px"> | ||||
|               <div slot-scope="{row,$index}"> | ||||
|                 <section v-if="row.editable"> | ||||
|                   <el-button type="text" icon="iconfont iconCorrect" @click="handleAdd(row)"/> | ||||
|                   <el-button type="text" icon="iconfont iconClean" @click="cancelEdit(row,$index)"/> | ||||
|                 </section> | ||||
|                 <section v-else> | ||||
|                   <el-button class="dict-detail-operation" type="text" icon="iconfont iconEdit" | ||||
|                              @click="editDetail(row)"/> | ||||
|                   <el-button class="dict-detail-operation" type="text" icon="iconfont iconDelete" | ||||
|                              @click="handleDelete(row.id)"/> | ||||
|                 </section> | ||||
|               </div> | ||||
|             </el-table-column> | ||||
|           </el-table> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <template #footer> | ||||
|         <el-button @click="$router.push({})">返回</el-button> | ||||
|         <el-button type="primary" @click="submit">保存</el-button> | ||||
|       </template> | ||||
|     </ku-layout> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import KuLayout from "../../../components/KuLayout"; | ||||
|  | ||||
| export default { | ||||
|   name: "dictDetail", | ||||
|   components: {KuLayout}, | ||||
|   props: { | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     rules() { | ||||
|       return { | ||||
|         code: [{required: true, message: "请填写数据项"}], | ||||
|         name: [{required: true, message: "请填写数据项名称"}], | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       form: {} | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDict() | ||||
|   }, | ||||
|   methods: { | ||||
|     getDict() { | ||||
|       const {code} = this.$route.query | ||||
|       this.$http.post("/api/dict/list", {params: {code}}).then(res => { | ||||
|         if (res?.data) { | ||||
|           const info = res.data?.[0] | ||||
|           info.children?.map(e => { | ||||
|             e.editable = false | ||||
|             e.name = "" | ||||
|             e.value = "" | ||||
|           }) | ||||
|           this.form = {...info, name: info.dictValue} | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       this.$confirm("是否要删除该字典值", { | ||||
|         type: 'error' | ||||
|       }).then(() => { | ||||
|         this.$http.post("/dict/remove", null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!") | ||||
|             this.getDict() | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     editDetail(row) { | ||||
|       row.editable = true | ||||
|       row.name = row.dictValue | ||||
|       row.value = row.dictKey | ||||
|     }, | ||||
|     handleAdd(row) { | ||||
|       row.dictKey = row.value | ||||
|       row.dictValue = row.name | ||||
|       this.$http.post("/dict/submit", {parentId: this.form.id, ...row}).then(res => { | ||||
|         row.editable = false | ||||
|         row = res.data.data | ||||
|         this.$message.success("提交成功!") | ||||
|       }) | ||||
|     }, | ||||
|     cancelEdit(row, index) { | ||||
|       if (row.id) { | ||||
|         row.editable = false | ||||
|       } else { | ||||
|         this.form.children?.splice(index, 1) | ||||
|       } | ||||
|     }, | ||||
|     submit() { | ||||
|       this.$refs.DictForm.validate().then(() => { | ||||
|         this.$http.post("/dict/submit", this.form).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("提交成功!") | ||||
|             this.$router.push({}) | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .dictDetail { | ||||
|   height: 100%; | ||||
|  | ||||
|   :deep( .el-table__row ) { | ||||
|  | ||||
|     .el-input__inner { | ||||
|       padding: 0 30px; | ||||
|       border: none; | ||||
|       text-align: center; | ||||
|       background: #ddd; | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| </style> | ||||
| @@ -23,7 +23,7 @@ | ||||
|           <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')"/> | ||||
|           <ku-select v-model="form.type" clearable :selectList="menuTypes"/> | ||||
|         </el-form-item> | ||||
|         <template v-if="form.type==0"> | ||||
|           <el-form-item label="菜单图标" prop="style"> | ||||
| @@ -50,7 +50,7 @@ | ||||
|           </el-form-item> | ||||
|         </template> | ||||
|         <el-form-item label="显示菜单" prop="status"> | ||||
|           <ku-select v-model="form.status" clearable :selectList="$dict.getDict('yesOrNo')"/> | ||||
|           <ku-select v-model="form.status" clearable dict="yesOrNo"/> | ||||
|         </el-form-item> | ||||
|         <el-form-item v-if="form.type<2" label="排序" prop="showIndex"> | ||||
|           <el-input v-model="form.showIndex" placeholder="请输入" clearable/> | ||||
| @@ -61,19 +61,29 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import KuLayout from "../components/KuLayout"; | ||||
| import KuSearchBar from "../components/KuSearchBar"; | ||||
| import KuTable from "../components/KuTable"; | ||||
| import KuSelect from "../components/KuSelect"; | ||||
| import KuDialog from "../components/KuDialog"; | ||||
| import KuLayout from "../../components/KuLayout"; | ||||
| import KuSearchBar from "../../components/KuSearchBar"; | ||||
| import KuTable from "../../components/KuTable"; | ||||
| import KuSelect from "../../components/KuSelect"; | ||||
| import KuDialog from "../../components/KuDialog"; | ||||
| 
 | ||||
| export default { | ||||
|   name: "AppMenu", | ||||
|   components: {KuDialog, KuSelect, KuTable, KuSearchBar, KuLayout}, | ||||
|   label: "菜单管理", | ||||
|   computed: { | ||||
|     columns: v => [ | ||||
|       {label: "菜单名称", prop: "menuName"}, | ||||
|       {label: "菜单类型", prop: "type", render: (h, {row}) => h(v.menuTypes[row.type])}, | ||||
|       {label: "应用模块", prop: "component"}, | ||||
|       {label: "是否显示", prop: "status", dict: "yesOrNo"}, | ||||
|       {label: "排序", prop: "showIndex"}, | ||||
|     ] | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       search: {name: null}, | ||||
|       menuTypes: {0: "菜单", 1: "应用", 2: "权限"}, | ||||
|       tableData: [ | ||||
|         { | ||||
|           id: 1, menuName: "测试", type: "菜单", status: 1, showIndex: 1, | ||||
| @@ -83,13 +93,6 @@ export default { | ||||
|           ] | ||||
|         } | ||||
|       ], | ||||
|       columns: [ | ||||
|         {label: "菜单名称", prop: "menuName"}, | ||||
|         {label: "菜单类型", prop: "type"}, | ||||
|         {label: "应用模块", prop: "component"}, | ||||
|         {label: "是否显示", prop: "status", dict: "yesOrNo"}, | ||||
|         {label: "排序", prop: "showIndex"}, | ||||
|       ], | ||||
|       dialog: false, | ||||
|       form: {}, | ||||
|       rules: { | ||||
| @@ -121,11 +124,19 @@ export default { | ||||
| 
 | ||||
|     }, | ||||
|     submit() { | ||||
| 
 | ||||
|       this.$refs.MenuForm.validate() | ||||
|           .then(() => this.$http.post("/api/menu/submit", this.form)) | ||||
|           .then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.$message.success("提交成功!") | ||||
|               this.dialog = false | ||||
|             } | ||||
|           }) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTableData() | ||||
|     this.$dict.load("yesOrNo") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @@ -6,7 +6,7 @@ | ||||
|         <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"/> | ||||
|         <el-option v-for="(v, k) in ops" :key="k" :label="v" :value="k"/> | ||||
|       </template> | ||||
|     </el-select> | ||||
|   </div> | ||||
| @@ -54,7 +54,13 @@ export default { | ||||
|         ...this.prop | ||||
|       } | ||||
|     }, | ||||
|     ops: v => v.dict ? v.$dict.getDict(v.dict) : v.selectList | ||||
|     ops: v => { | ||||
|       if (v.dict) { | ||||
|         const options = {} | ||||
|         v.$dict.getDict(v.dict).map(e => options[e.dictValue] = e.dictName) | ||||
|         return options | ||||
|       } else return v.selectList | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     getOptions() { | ||||
|   | ||||
| @@ -14,7 +14,8 @@ | ||||
|             </el-icon> | ||||
|           </el-row> | ||||
|           <template v-if="menu.expand"> | ||||
|             <div class="app mar-h8" v-for="app in menu.children" :key="app.id" v-text="app.label" :class="{active:app.id==12}" @click="handleGoto(app.route)"/> | ||||
|             <div class="app mar-h8" v-for="app in menu.children" :key="app.id" v-text="app.label" | ||||
|                  :class="{active:app.id==12}" @click="handleGoto(app.route)"/> | ||||
|           </template> | ||||
|         </template> | ||||
|         <div v-else class="flex pad-h8 center" @click="handleGoto(menu.route)"> | ||||
| @@ -59,8 +60,12 @@ export default { | ||||
|           this.menus = this.$arr2tree(menus, {parent: "parent"}) | ||||
|         } | ||||
|       }).finally(() => { | ||||
|         //超管才有的初始化菜单 | ||||
|         if (this.menus.length == 0 && this.user.level == 1) { | ||||
|           this.menus = [{id: '202302071139', label: "菜单管理", route: "AppMenu"}] | ||||
|           this.menus = [ | ||||
|             {id: '202302071139', label: "菜单管理", route: "AppMenu"}, | ||||
|             {id: '202302102232', label: "字典管理", route: "AppDictionary"}, | ||||
|           ] | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import http from "./axios"; | ||||
|  * 封装字典工具类 | ||||
|  */ | ||||
| const $dict = { | ||||
|   url: "/api/dict/listByCodes", | ||||
|   loading: [], | ||||
|   resolves: [], | ||||
|   getStorage() { | ||||
| @@ -13,9 +12,15 @@ const $dict = { | ||||
|   }, | ||||
|   getData(codeList) { | ||||
|     codeList = [codeList].flat().filter(Boolean).toString() | ||||
|     return http.post(this.url, null, { | ||||
|     return http.post("/api/dict/listByCodes", null, { | ||||
|       withoutToken: true, params: {codeList} | ||||
|     }).then(res => res?.data && this.setStorage(res.data)) | ||||
|       .finally(() => this.setStorage({ | ||||
|         key: "yesOrNo", values: [ | ||||
|           {dictValue: '0', dictName: "否"}, | ||||
|           {dictValue: '1', dictName: "是"} | ||||
|         ] | ||||
|       })) | ||||
|   }, | ||||
|   load(...code) { | ||||
|     return new Promise(resolve => { | ||||
| @@ -32,8 +37,8 @@ const $dict = { | ||||
|     }) | ||||
|   }, | ||||
|   setStorage(data) { | ||||
|     let ds = this.getStorage() | ||||
|     data.map(p => { | ||||
|     let ds = this.getStorage(); | ||||
|     [data].flat().map(p => { | ||||
|       if (ds.some(d => d.key == p.key)) { | ||||
|         const index = ds.findIndex(d => d.key == p.key) | ||||
|         ds.splice(index, 1, p) | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import {mainStore} from "./store"; | ||||
| let home = {name: "工作台", path: "/", component: () => import('../views/home')}, | ||||
|   routes = [{name: "登录", path: "/login", component: () => import('../views/login')}] | ||||
| const loadApps = () => { | ||||
|   const files = import.meta.glob('../apps/App*.vue'), apps = [] | ||||
|   const files = import.meta.glob('../apps/**/App*.vue'), apps = [] | ||||
|   return Promise.all(Object.keys(files).map(path => { | ||||
|     return files?.[path]()?.then(file => { | ||||
|       if (file.default) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user