日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

SpringBoot mybatis 實現多級樹形菜單的示例代碼

瀏覽:19日期:2023-03-13 09:10:25
一、前言

iview-admin中提供了 v-org-tree 這么一個vue組件可以實現樹形菜單,下面小編來提供一下在element-ui中的使用教程(項目見:https://github.com/lison16/v-org-tree)

小編集成了el-dropdown下拉菜單(鼠標左擊顯示菜單),和右擊自定義菜單,兩種方式,效果圖如下:

SpringBoot mybatis 實現多級樹形菜單的示例代碼

二、使用教程

(1)安裝依賴

npm install clipboardnpm install v-click-outside-xnpm install v-org-tree

(2)引入組件

在main.js文件中引入

import TreeTable from ’tree-table-vue’import VOrgTree from ’v-org-tree’

(3)引入部分js工具方法

在項目目錄下 -> src -> directive文件夾中引入如下4個js文件

SpringBoot mybatis 實現多級樹形菜單的示例代碼

clipboard.js

import Clipboard from ’clipboard’export default { bind: (el, binding) => { const clipboard = new Clipboard(el, { text: () => binding.value.value }) el.__success_callback__ = binding.value.success el.__error_callback__ = binding.value.error clipboard.on(’success’, e => { const callback = el.__success_callback__ callback && callback(e) }) clipboard.on(’error’, e => { const callback = el.__error_callback__ callback && callback(e) }) el.__clipboard__ = clipboard }, update: (el, binding) => { el.__clipboard__.text = () => binding.value.value el.__success_callback__ = binding.value.success el.__error_callback__ = binding.value.error }, unbind: (el, binding) => { delete el.__success_callback__ delete el.__error_callback__ el.__clipboard__.destroy() delete el.__clipboard__ }}

draggable.js

import { on } from ’@/libs/tools’export default { inserted: (el, binding, vnode) => { const triggerDom = document.querySelector(binding.value.trigger) triggerDom.style.cursor = ’move’ const bodyDom = document.querySelector(binding.value.body) let pageX = 0 let pageY = 0 let transformX = 0 let transformY = 0 let canMove = false const handleMousedown = e => { let transform = /(.*)/.exec(bodyDom.style.transform) if (transform) {transform = transform[0].slice(1, transform[0].length - 1)const splitxy = transform.split(’px, ’)transformX = parseFloat(splitxy[0])transformY = parseFloat(splitxy[1].split(’px’)[0]) } pageX = e.pageX pageY = e.pageY canMove = true } const handleMousemove = e => { const xOffset = e.pageX - pageX + transformX const yOffset = e.pageY - pageY + transformY if (canMove) bodyDom.style.transform = `translate(${xOffset}px, ${yOffset}px)` } const handleMouseup = e => { canMove = false } on(triggerDom, ’mousedown’, handleMousedown) on(document, ’mousemove’, handleMousemove) on(document, ’mouseup’, handleMouseup) }, update: (el, binding, vnode) => { if (!binding.value.recover) return const bodyDom = document.querySelector(binding.value.body) bodyDom.style.transform = ’’ }}

directives.js

import draggable from ’./module/draggable’import clipboard from ’./module/clipboard’ const directives = { draggable, clipboard} export default directives

index.js

import directive from ’./directives’ const importDirective = Vue => { /** * 拖拽指令 v-draggable='options' * options = { * trigger: /這里傳入作為拖拽觸發器的CSS選擇器/, * body: /這里傳入需要移動容器的CSS選擇器/, * recover: /拖動結束之后是否恢復到原來的位置/ * } */ Vue.directive(’draggable’, directive.draggable) /** * clipboard指令 v-draggable='options' * options = { * value: /在輸入框中使用v-model綁定的值/, * success: /復制成功后的回調/, * error: /復制失敗后的回調/ * } */ Vue.directive(’clipboard’, directive.clipboard)} export default importDirective

(4)正式使用v-org-tree組件

在所要使用的地方新增如下幾個文件,比如我要寫在user-group文件夾中

SpringBoot mybatis 實現多級樹形菜單的示例代碼

項目srccomponentsorg-view下面建立二個文件:

index.js

import OrgView from ’./org-view.vue’export default OrgView

org-view.vue

<template> <div ref='dragWrapper' @mousedown='mousedownView' @contextmenu='handleDocumentContextmenu' > <div :style='orgTreeStyle'> <v-org-treev-if='data':data='data':node-render='nodeRender':expand-all='true'@on-node-click='handleNodeClick'collapsable ></v-org-tree> </div> </div></template> <script>import { on, off } from ’@/directive/module/tools’ export default { name: ’OrgView’, props: { zoomHandled: { type: Number, default: 1 }, data: Object, menuList: { type: Array, default: function () {return [ { key: ’edit’, label: ’編輯公司’ }, { key: ’detail’, label: ’查看公司’ }, { key: ’add’, label: ’新增子公司’ }, { key: ’delete’, label: ’刪除公司’ }] } } }, data () { return { currentContextMenuId: ’’, orgTreeOffsetLeft: 0, orgTreeOffsetTop: 0, initPageX: 0, initPageY: 0, oldMarginLeft: 0, oldMarginTop: 0, canMove: false } }, computed: { orgTreeStyle () { return {transform: `translate(-50%, -50%) scale(${this.zoomHandled}, ${ this.zoomHandled})`,marginLeft: `${this.orgTreeOffsetLeft}px`,marginTop: `${this.orgTreeOffsetTop}px` } } }, methods: { handleNodeClick (e, data, expand) { expand() }, closeMenu () { this.currentContextMenuId = ’’ }, getBgColor (data) { return this.currentContextMenuId === data.id? data.isRoot ? ’#0d7fe8’ : ’#5d6c7b’: ’’ }, nodeRender (h, data) { return (<div class={[ ’custom-org-node’, data.children && data.children.length ? ’has-children-label’ : ’’ ]} on-mousedown={event => event.stopPropagation()} on-contextmenu={this.contextmenu.bind(this, data)}> {data.label} <dropdown trigger='custom' visible={this.currentContextMenuId === data.id} nativeOn-click={this.handleDropdownClick} on-on-click={this.handleContextMenuClick.bind(this, data)} style={{ transform: `scale(${1 / this.zoomHandled}, ${1 /this.zoomHandled})` }} v-click-outside={this.closeMenu} > <dropdown-menu slot='list'> {this.menuList.map(item => {return ( <dropdown-item name={item.key}>{item.label}</dropdown-item>) })} </dropdown-menu> </dropdown></div> ) }, contextmenu (data, $event) { const event = $event || window.event event.preventDefault? event.preventDefault(): (event.returnValue = false) this.currentContextMenuId = data.id }, setDepartmentData (data) { data.isRoot = true this.departmentData = data }, mousedownView (event) { this.canMove = true this.initPageX = event.pageX this.initPageY = event.pageY this.oldMarginLeft = this.orgTreeOffsetLeft this.oldMarginTop = this.orgTreeOffsetTop on(document, ’mousemove’, this.mousemoveView) on(document, ’mouseup’, this.mouseupView) }, mousemoveView (event) { if (!this.canMove) return const { pageX, pageY } = event this.orgTreeOffsetLeft = this.oldMarginLeft + pageX - this.initPageX this.orgTreeOffsetTop = this.oldMarginTop + pageY - this.initPageY }, mouseupView () { this.canMove = false off(document, ’mousemove’, this.mousemoveView) off(document, ’mouseup’, this.mouseupView) }, handleDropdownClick (event) { event.stopPropagation() }, handleDocumentContextmenu () { this.canMove = false }, handleContextMenuClick (data, key) { this.$emit(’on-menu-click’, { data, key }) } }, mounted () { on(document, ’contextmenu’, this.handleDocumentContextmenu) }, beforeDestroy () { off(document, ’contextmenu’, this.handleDocumentContextmenu) }}</script> <style></style>

項目srccomponentszoom-controller下面建立二個文件:

index.js

import ZoomController from ’./zoom-controller’export default ZoomController

zoom-controller.vue

<template> <div class='zoom-wrapper'> <button @click='scale(’down’)'> <Icon type='md-remove' :size='14' color='#fff'/> </button> <span class='zoom-number'>{{ value }}%</span> <button @click='scale(’up’)'> <Icon type='md-add' :size='14' color='#fff'/> </button> </div></template> <script>export default { name: ’ZoomController’, props: { value: { type: Number, default: 100 }, step: { type: Number, default: 20 }, min: { type: Number, default: 10 }, max: { type: Number, default: 200 } }, methods: { scale (type) { const zoom = this.value + (type === ’down’ ? -this.step : this.step) if ((zoom < this.min && type === ’down’) ||(zoom > this.max && type === ’up’) ) {return } this.$emit(’input’, zoom) } }}</script> <style lang='less'>.trans(@duration) { transition: ~'all @{duration} ease-in';}.zoom-wrapper { .zoom-button { width: 20px; height: 20px; line-height: 10px; border-radius: 50%; background: rgba(157, 162, 172, 1); box-shadow: 0px 2px 8px 0px rgba(218, 220, 223, 0.7); border: none; cursor: pointer; outline: none; &:active { box-shadow: 0px 0px 2px 2px rgba(218, 220, 223, 0.2) inset; } .trans(0.1s); &:hover { background: #1890ff; .trans(0.1s); } } .zoom-number { color: #657180; padding: 0 8px; display: inline-block; width: 46px; text-align: center; }}</style>

項目srcview下面建立org.vue文件

<template> <Card shadow style='height: 100%;width: 100%;overflow:hidden'> <div class='department-outer'> <div class='zoom-box'><zoom-controller v-model='zoom' :min='20' :max='200'></zoom-controller> </div> <div class='view-box'><org-view v-if='data' :data='data' :zoom-handled='zoomHandled' :menuList='menuList' @on-menu-click='handleMenuClick'></org-view> </div> </div> </Card></template> <script>import { orgList } from ’@/api/org’import { layerDialog } from ’@/libs/Diaglog’import ’./org.less’ const OrgView = Vue.component(’OrgView’, function (resolve) { require([’/user/org-view’], resolve)})const ZoomController = Vue.component(’ZoomController’, function (resolve) { require([’/user/zoom-controller’], resolve)})export default { name: ’org_tree_page’, components: { OrgView, ZoomController }, data () { return { data: null, zoom: 100, menuList: [{ key: ’add’, label: ’新增子公司’},{ key: ’edit’, label: ’編輯公司’},{ key: ’delete’, label: ’刪除公司’} ] } }, computed: { zoomHandled () { return this.zoom / 100 } }, methods: { setDepartmentData (data) { data.isRoot = true return data }, handleMenuClick ({ data, key }) { switch (key) {case ’add’:case ’edit’: console.log(data) this.showDialog(data, key) breakcase ’delete’: break } }, showDialog (data, key) { data.key = key const option = {id: key + ’SaveDialog’,title: this.$i18n.t(key),width: ’600px’,height: ’550px’,url: ’/api/org/’ + Qs.stringify(data, { arrayFormat: ’brackets’ }) } layerDialog(option) }, getDepartmentData () { const entity = {} const levels = ’0,1,2,3,4,5,6’ entity.status = 1 getOrgList(entity, 1, 20, levels).then(result => {if (result.data.code === 10000) { let len = 0 const list = result.data.data.list if (list) { len = list.length } var data = { id: 0, label: ’阿里巴巴集團’, level: 0 } if (len > 0) { data.children = this.formatData(list, 1, 0) } this.data = data} }) }, formatData (list, level, pid, pname) { const childrenData = [] for (let i = 0; i < list.length; i++) {const data = {}const item = list[i]if (level === item.level) { data.id = item.id data.label = item.name data.parentName = pname data.level = item.level data.children = this.formatData(list, level + 1, item.id, item.name) childrenData.push(data)} } return childrenData } }, mounted () { this.getDepartmentData() }}</script>

接口中核心代碼:

List<Station> stations = stationService.listByEntity(station,levelList);List<StationVo> stationVos = new ArrayList();for(Station s : stations) { StationVo vo = new StationVo(); vo.setId(s.getId()); vo.setLevel(s.getLevel()); vo.setName(s.getName()); stationVos.add(vo);}

數據庫中四個字段

SpringBoot mybatis 實現多級樹形菜單的示例代碼

mybatis 配置:

SpringBoot mybatis 實現多級樹形菜單的示例代碼

返回的json如下:

{ 'data' : { 'page' : 1, 'pageSize' : 20, 'total' : 6, 'pages' : 1, 'list' : [ { 'id' : 1, 'name' : '天貓科技服務有限公司', 'level' : 1, 'status' : 1, }, { 'id' : 2, 'name' : '淘寶技術服務有限公司', 'level' : 1, 'status' : 1, }, { 'id' : 3, 'name' : '聚劃算科技服務有限公司', 'level' : 1, 'status' : 1, }, { 'id' : 4, 'name' : '菜鳥金服', 'level' : 2, 'status' : 1, }, { 'id' : 5, 'name' : '黑鳥網絡', 'level' : 3, 'status' : 1, }, { 'id' : 6, 'name' : '白鳥 網絡', 'level' : 3, 'status' : 1, } ] }, 'message' : '獲取成功', 'code' : 200}

到此這篇關于SpringBoot mybatis 實現多級樹形菜單的示例代碼的文章就介紹到這了,更多相關SpringBoot mybatis多級樹形菜單內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
99精品国产一区二区三区| 久久福利精品| 久久xxxx| 亚洲精品va| 国产一区欧美| 岛国av在线播放| 国产欧美精品久久| 卡一精品卡二卡三网站乱码| 国产精品亚洲人成在99www| 久久亚洲精品伦理| 亚洲欧美日韩国产一区| 国产一区二区三区四区大秀 | 久久精品高清| 日韩中文在线电影| 97精品一区二区| 久久uomeier| 成人在线视频区| 成人精品高清在线视频| 久久中文字幕一区二区三区| 精品国产成人| 欧美香蕉视频| 1024精品久久久久久久久| 亚洲经典在线| 免费在线观看精品| 亚洲免费毛片| 婷婷精品久久久久久久久久不卡| 婷婷视频一区二区三区| 国产日韩在线观看视频| 久久精品一区| 91精品国产91久久久久久黑人| 不卡视频在线| 日韩精品一级中文字幕精品视频免费观看 | 久久精品av| 欧美精品一区二区三区精品| 国产亚洲一级| 日本国产欧美| 久久亚洲人体| 久久久久午夜电影| 美女久久一区| 国产精品三级| 日韩欧美1区| 亚洲一区二区三区高清| 欧美日韩中出| 亚洲成人国产| 爽好多水快深点欧美视频| 日韩一区二区三区高清在线观看| 美腿丝袜亚洲一区| 国产精品97| 国产亚洲欧美日韩在线观看一区二区 | 中文在线日韩| 国产精品videosex极品| 日韩福利一区| 蜜臀久久久久久久| 91久久精品无嫩草影院| 国产亚洲字幕| 日韩国产一区二区| 免播放器亚洲一区| 青青草视频一区| 清纯唯美亚洲综合一区| 亚洲永久av| 精品在线99| 一区二区电影在线观看| 国产美女久久| 欧美www视频在线观看| 日韩黄色大片网站| 亚洲网站视频| 亚洲婷婷丁香| 国产精品成人国产| 里番精品3d一二三区| 日韩av首页| 蜜臀av在线播放一区二区三区| 日韩欧美中文字幕一区二区三区| 亚洲精品午夜av福利久久蜜桃| 亚洲免费福利一区| 欧美激情网址| 岛国精品一区| 日韩精品一区二区三区中文字幕| 高潮一区二区| 日韩在线免费| 久久av影院| 91麻豆精品| 日本不卡一区二区三区| 亚洲精品乱码日韩| 蜜臀av一区二区三区| 亚洲一二三区视频| 欧美亚洲二区| 美腿丝袜亚洲一区| 成人看片网站| 亚洲精品成a人ⅴ香蕉片| 综合亚洲自拍| 午夜在线精品| 高清久久一区| 蜜臀av性久久久久蜜臀aⅴ流畅| 99国产精品一区二区| 国产日韩专区| 午夜亚洲福利| 成人污污视频| 成人福利av| 日韩激情一区| 亚洲免费成人| 99国产精品99久久久久久粉嫩| 亚洲大片在线| 五月婷婷亚洲| 国产经典一区| 超碰成人av| 国产精品普通话对白| 日本综合精品一区| 超碰成人av| 97精品国产99久久久久久免费| 新版的欧美在线视频| 国产一区2区| 国产精品亚洲欧美日韩一区在线 | 精品高清久久| 日韩av网站在线免费观看| 一区视频在线| 欧美天堂视频| 国产传媒在线观看| 国产精品手机在线播放| 天堂va在线高清一区| 国产欧美综合一区二区三区| 日韩精品欧美大片| 日本不卡视频在线| 亚洲乱码视频| 尤物在线精品| 红桃视频国产精品| 9色精品在线| 综合日韩av| 国产精品一区二区三区av | 日韩一区亚洲二区| 日韩亚洲精品在线| 精品国产乱码久久久久久樱花| 伊人久久亚洲| 午夜av一区| 国产一区二区精品福利地址| 日韩**一区毛片| 国产精品免费看| 久久一级电影| 成人在线观看免费视频| 国产欧美一区二区三区米奇| 午夜在线播放视频欧美| caoporn视频在线| 国产日韩一区| 日韩精品免费一区二区夜夜嗨| 老鸭窝亚洲一区二区三区| 久久久久蜜桃| 国产精品蜜芽在线观看| 国产欧美日韩一区二区三区四区| 亚洲一区有码| 中文在线不卡| 亚洲二区免费| 999精品色在线播放| 日韩精品诱惑一区?区三区| 精品视频黄色| 麻豆91小视频| 热久久久久久| 欧美日韩 国产精品| 亚洲精品影视| 亚洲日本国产| 亚洲精品网址| 日韩精品一级中文字幕精品视频免费观看 | 热三久草你在线| 国产一区 二区| 日韩手机在线| 日本少妇精品亚洲第一区| 亚洲人成网站在线在线观看| 免费视频久久| 久久aⅴ国产紧身牛仔裤| 国产一区成人| 国产精品日韩久久久| 午夜精品网站| 亚洲黄色影院| 国产婷婷精品| 夜夜嗨av一区二区三区网站四季av| 亚洲国产成人二区| 四虎4545www国产精品| 久久精品动漫| 精品欧美久久| 老司机精品久久| 亚洲精品亚洲人成在线观看| 日本a级不卡| 国产福利资源一区| 色爱综合网欧美| 欧美特黄一级大片| 亚洲免费网址| 日本一区二区三区中文字幕| 久久精品99国产国产精| 久久一区精品| 国产综合色区在线观看| 亚洲1234区| 国产精品亚洲欧美日韩一区在线| 麻豆成人av在线| 久久久久99| 精品中文字幕一区二区三区av| 麻豆成人91精品二区三区| 成人精品国产亚洲| 欧洲精品一区二区三区| 一区二区三区四区在线看| 亚州av乱码久久精品蜜桃| 国产亚洲欧美日韩精品一区二区三区 | 日本不良网站在线观看|