| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- @extends('layouts.app')
- @section('title')菜单@endsection
- @section('content')
- <div class="container-fluid d-none" id="container" @drop="drop($event)" @dragover="dragover($event, false)">
- @include("maintenance.menu._modal")
- <div class="card" id="content">
- <div class="card-body">
- <button class="btn btn-outline-info mb-1 mr-3" @click="openModal()"><span class="fa fa-plus"></span> 新 增</button>
- <button class="btn border border-2 mb-1 mr-3" :class="isSaveSort ? 'btn-success' : 'text-secondary'" :disabled="!isSaveSort" @click="sort()"> 保 存 </button>
- <div class="btn-group pull-right">
- <button class="btn border btn-primary" @click="expand(true)">展开全部</button>
- <button class="btn border btn-primary" @click="expand(false)">收起全部</button>
- </div>
- <div class="row text-nowrap">
- <ul class="list-group col-9 offset-1" style="cursor: move;">
- <li class="list-group-item" v-for="menu in menus" draggable="true" :id="'menu-'+menu.id"
- :data-order="menu.sequence" :data-id="menu.id" :data-parent="menu.parent_id" :data-level="menu.level"
- @drop="drop($event)" @dragover="dragover($event)" @dragstart.stop="dragstart(menu.id)">
- <span class="fa fa-angle-right pull-left cursor-pointer font-weight-bold" @click="slide(menu.id,$event)" style="margin-top: 0.2em"> </span>
- <span v-show="menu.font" :class="'fa '+menu.font" :style="menu.font_style"></span>@{{ menu.name }}
- <span class="fa fa-close pull-right text-danger" style="cursor: pointer" @click="delMenu(menu.id)"></span>
- <span class="fa fa-edit pull-right text-primary mr-2" style="cursor: pointer" @click="openModal(menu)"></span>
- <div class="row up" v-if="menu.child.length>0" :id="'slide-'+menu.id">
- <ul class="list-group col-9 offset-1">
- <li class="list-group-item" v-for="menu2 in menu.child" draggable="true" :id="'menu-'+menu2.id"
- :data-order="menu2.sequence" :data-id="menu2.id" :data-parent="menu2.parent_id" :data-level="menu2.level"
- @drop="drop($event)" @dragover="dragover($event,dragoverId!=menu.id)" @dragstart.stop="dragstart(menu2.id)">
- <span class="fa fa-angle-right pull-left cursor-pointer font-weight-bold" @click="slide(menu2.id,$event)" style="margin-top: 0.2em"> </span>
- @{{ menu2.name }}
- <span class="fa fa-close pull-right text-danger" style="cursor: pointer" @click="delMenu(menu2.id)"></span>
- <span class="fa fa-edit pull-right text-primary mr-2" style="cursor: pointer" @click="openModal(menu2)"></span>
- <div class="row up" v-if="menu2.child.length>0" :id="'slide-'+menu2.id">
- <ul class="list-group col-9 offset-1">
- <li class="list-group-item" v-for="menu3 in menu2.child" draggable="true" :id="'menu-'+menu3.id"
- :data-order="menu3.sequence" :data-id="menu3.id" :data-parent="menu3.parent_id" :data-level="menu3.level"
- @drop="drop($event)" @dragover="dragover($event,dragoverId!=menu2.id && dragoverId!=menu.id)" @dragstart.stop="dragstart(menu3.id)">
- <span class="fa fa-angle-right pull-left cursor-pointer font-weight-bold" @click="slide(menu3.id,$event)" style="margin-top: 0.2em"> </span>
- @{{ menu3.name }}
- <span class="fa fa-close pull-right text-danger" style="cursor: pointer" @click="delMenu(menu3.id)"></span>
- <span class="fa fa-edit pull-right text-primary mr-2" style="cursor: pointer" @click="openModal(menu3)"></span>
- <div class="row up" v-if="menu3.child.length>0" :id="'slide-'+menu3.id">
- <ul class="list-group col-9 offset-1">
- <li class="list-group-item" v-for="menu4 in menu3.child" draggable="true" :id="'menu-'+menu4.id"
- :data-order="menu4.sequence" :data-id="menu4.id" :data-parent="menu4.parent_id" :data-level="menu4.level"
- @drop="drop($event)" @dragover="dragover($event,dragoverId!=menu3.id && dragoverId!=menu2.id && dragoverId!=menu.id)" @dragstart.stop="dragstart(menu4.id)">
- @{{ menu4.name }}
- <span class="fa fa-close pull-right text-danger" style="cursor: pointer" @click="delMenu(menu4.id)"></span>
- <span class="fa fa-edit pull-right text-primary mr-2" style="cursor: pointer" @click="openModal(menu4)"></span>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </div>
- <li id="dragover-container" class="border-dashed-red" v-show="isDragover" @drop="drop($event)" @dragover="dragover($event,false)">
- <div class='w-100 text-center text-secondary'>拖拽至此</div>
- </li>
- </div>
- </div>
- </div>
- @endsection
- @section('lastScript')
- <script>
- new Vue({
- el:"#container",
- data:{
- menus:[],
- unit:{},
- errors:{},
- dragoverId:"",
- isDragover : false,
- isSaveSort : false,
- menuList:[],
- icons:[],
- filterIcons:[],
- menu:{},
- },
- mounted(){
- let menus = [@foreach($menus as $menu)@json($menu),@endforeach];
- let menuMap = {};
- menus.forEach(menu=>{
- menu["child"] = [];
- menuMap["_"+menu.id] = menu;
- });
- menus.forEach(menu=>{
- if (menu.parent_id){
- menuMap["_"+menu.parent_id].child.push(menu);
- delete menuMap["_"+menu.id];
- }
- });
- this.menus = menuMap;
- this._formatSelected();
- setTimeout(function(){
- $(".up").slideUp();
- $("#container").removeClass("d-none");
- },0);
- },
- methods:{
- expand(isExpand){
- if (isExpand) $(".up").slideDown();
- else $(".up").slideUp();
- },
- slide(id,e){
- $("#slide-"+id).slideToggle();
- if (e.target.className.indexOf('right')===-1)e.target.className = "fa fa-angle-right pull-left cursor-pointer font-weight-bold";
- else e.target.className = "fa fa-angle-down pull-left cursor-pointer font-weight-bold";
- },
- delMenu(id){
- window.tempTip.confirm("确认要删除此菜单及其子级吗?",()=>{
- let url = "{{url('maintenance/menu/delete')}}";
- let ids = [id];
- let nodes = document.getElementById("menu-"+id).getElementsByTagName("LI");
- for (let i=0;i<nodes.length;i++){
- let id = nodes[i].getAttribute("data-id");
- if (id)ids.push(id);
- }
- window.tempTip.postBasicRequest(url,{ids:ids},()=>{
- document.getElementById("menu-"+id).remove();
- this.sort();
- return "删除成功";
- })
- });
- },
- seekIcon(e){
- let val = e.target.value;
- let arr = [];
- this.icons.forEach(icon=>{
- if (!val)arr.push(icon);
- else if (icon.indexOf(val)!==-1)arr.push(icon);
- });
- this.filterIcons = arr;
- },
- selectedIcon(icon){
- this.$set(this.menu,"font",icon);
- },
- _formatSelected(){
- new Promise(()=>{
- this.menuList = this._mergeArray(this.menus);
- this._getIcons()
- });
- },
- _getIcons(){
- let url = "{{url('')}}"+"/js/utilities/icons.json";
- let request = new XMLHttpRequest();
- request.open("get", url);
- request.send(null);
- request.onload = ()=>{
- if (request.status == 200) {
- this.icons = JSON.parse(request.responseText);
- this.filterIcons = JSON.parse(request.responseText);
- }
- }
- },
- _mergeArray(obj,arr=[]){
- for (let key in obj){
- let name = "";
- for (let i=1;i<obj[key]["level"];i++){
- name += " ";
- }
- if (obj[key]['level']!==1)name += "└─ ";
- name += obj[key]["name"];
- arr.push({name:name,id:obj[key]["id"],level:obj[key]["level"],parent_id:obj[key]["parent_id"]});
- if (obj[key].child)arr = this._mergeArray(obj[key].child,arr);
- }
- return arr;
- },
- openModal(menu=null){
- this.menu=Object.assign({},menu);
- if (this.menu){
- if (!this.menu.parent_id)this.menu.parent_id = "";
- if (this.menu.font_style && this.menu.font_style.slice(0,6)==='color:'){
- this.menu.font_style = this.menu.font_style.slice(6);
- if (this.menu.font_style[this.menu.font_style.length-1]===';'){
- this.menu.font_style = this.menu.font_style.slice(0,this.menu.font_style.length-1);
- }
- }
- }
- else this.menu={parent_id:""};
- $("#modal").modal("show");
- },
- submitMenu(){
- let url="{{url('maintenance/menu/save')}}";
- let msg=this.menu.id ? "成功修改菜单“"+this.menu.name+"”" : "成功新增菜单“"+this.menu.name+"”";
- let pa = null;
- let level = 0;
- if(this.menu.parent_id){
- pa = this.menu.parent_id;
- level = document.getElementById("menu-"+this.menu.parent_id).getAttribute("data-level");
- }
- let params = {
- name : this.menu.name,
- parent_id : pa,
- level : Number(level)+1,
- route:this.menu.route,
- font:this.menu.font,
- font_style:this.menu.font_style ? 'color:'+this.menu.font_style+";" : null,
- };
- if (this.menu.id){
- params = {
- id:this.menu.id,
- name : this.menu.name,
- route:this.menu.route,
- font:this.menu.font,
- font_style:this.menu.font_style ? 'color:'+this.menu.font_style+";" : null,
- };
- }
- window.tempTip.postBasicRequest(url,params,(res)=>{
- if (params.id){
- let menu = this.seekNode(this.menu.id,this.menu.parent_id);
- menu.name = params.name;
- menu.route = params.route;
- menu.font = params.font;
- menu.font_style = params.font_style;
- }else this.insert(res);
- //$("#modal").modal("hide");
- return msg;
- },true);
- },
- dragover(e, isAllow = true){
- e.preventDefault();
- e.stopPropagation();
- if (isAllow) e.currentTarget.after(document.getElementById("dragover-container"))
- },
- dragstart(id){
- $("#menu-"+id).after($("#dragover-container"));
- this.dragoverId = id;
- this.isDragover = true;
- },
- drop(e){
- e.preventDefault();
- e.stopPropagation();
- $("#dragover-container").after($("#menu-"+this.dragoverId));
- this.handleDrag(this.dragoverId);
- this.dragoverId = "";
- this.isDragover = false;
- this.isSaveSort = true;
- },
- handleDrag(id){
- return new Promise(()=>{
- let params = {};
- let dom = document.getElementById("menu-"+id);
- let oldParent = dom.getAttribute("data-parent");
- let parent = dom.parentElement;
- let newParent = function () {
- while (parent && parent.tagName!=='LI')parent = parent.parentElement;
- return parent ? parent.getAttribute("data-id") : null;
- }();
- if (oldParent!==newParent){
- dom.setAttribute("data-parent",newParent);
- params.id = id;
- params.parent_id = newParent;
- let oldLevel = dom.getAttribute("data-level");
- let newLevel = parent ? Number(parent.getAttribute("data-level"))+1 : 1;
- let diff = oldLevel-newLevel;
- if (diff!=0){
- dom.setAttribute("data-level",newLevel);
- params.level = newLevel;
- let child = dom.getElementsByTagName("LI");
- if (child.length>0){
- params.diff = diff;
- params.child = [];
- for (let i=0;i<child.length;i++){
- params.child.push(child[i].getAttribute("data-id"));
- let level = child[i].getAttribute("data-level")-diff;
- child[i].setAttribute("data-level",level);
- }
- }
- }
- if (JSON.stringify(params)!=='{}'){
- window.tempTip.postBasicRequest("{{url('maintenance/menu/update')}}",params,()=>{});
- }
- }
- });
- },
- sort(){
- let nodes = document.getElementById("content").getElementsByTagName("LI");
- let update = [["id","sequence"]];
- let index = 1;
- let arr = [];
- for (let i=0;i<nodes.length;i++){
- let id = nodes[i].getAttribute("data-id");
- let parent_id = nodes[i].getAttribute("data-parent");
- if (!id)continue;
- let oldOrder = nodes[i].getAttribute("data-order");
- if (oldOrder != index){
- nodes[i].setAttribute("data-order",index);
- update.push({id:id,sequence:index});
- }
- index++;
- //重置列表
- let name = "";
- let level = Number(nodes[i].getAttribute("data-level"));
- for (let j=1;j<level;j++){
- name += " ";
- }
- if (level!==1)name += "└─ ";
- for (let j=0;j<nodes[i].childNodes.length;j++){
- if (nodes[i].childNodes[j].nodeName==='#text' && nodes[i].childNodes[j].nodeValue!=' '){
- name += nodes[i].childNodes[j].nodeValue;
- break;
- }
- }
- arr.push({name:name,id:id,level:level,parent_id:parent_id});
- }
- this.menuList = arr;
- if (update.length > 1){
- let url = "{{url('maintenance/menu/sort')}}";
- window.tempTip.postBasicRequest(url,{"update":update},()=>{
- this.isSaveSort = false;
- });
- }else this.isSaveSort = false;
- },
- insert(menu){
- menu.child = [];
- if (!menu.parent_id){
- this.$set(this.menus,"_"+menu.id,menu);
- setTimeout(()=>{this.sort();},100);
- return;
- }
- let arr = [];
- let parent = document.getElementById("menu-"+menu.parent_id);
- while (parent){
- let parent_id = parent.getAttribute("data-id");
- if (parent_id)arr.push(parent_id);
- parent = parent.parentElement;
- }
- if (arr.length===1){
- this.menus["_"+menu.parent_id].child.push(menu);
- setTimeout(()=>{this.sort();},100);
- return;
- }
- let menus = this.menus["_"+arr[arr.length-1]];
- for (let i=arr.length-1;i>=0;i--){
- menus.child.some((menu,j)=>{
- if (menu.id==arr[i]){
- menus = menus.child[j];
- return true;
- }
- });
- }
- menus.child.push(menu);
- setTimeout(()=>{this.sort();},100);
- },
- seekNode(id,parentId){
- if (!parentId)return this.menus["_"+id];
- let arr = [];
- let parent = document.getElementById("menu-"+parentId);
- while (parent){
- let parent_id = parent.getAttribute("data-id");
- if (parent_id)arr.push(parent_id);
- parent = parent.parentElement;
- }
- if (arr.length===1){
- let menus;
- this.menus["_"+parentId].child.some((menu,j)=>{
- if (menu.id==id){
- menus = this.menus["_"+parentId].child[j];
- return true;
- }
- });
- return menus;
- }
- let menus = this.menus["_"+arr[arr.length-1]];
- for (let i=arr.length-1;i>=0;i--){
- menus.child.some((menu,j)=>{
- if (menu.id==arr[i]){
- menus = menus.child[j];
- return true;
- }
- });
- }
- menus.child.some((menu,j)=>{
- if (menu.id==id){
- menus = menus.child[j];
- return true;
- }
- });
- return menus;
- },
- seekMenu(e){
- let val = e.target.value;
- let menuMap = {};
- for (let i=0;i<this.menuList.length;i++){
- menuMap['_'+this.menuList[i].id] = i;
- }
- this.menuList.forEach((menu,index)=>{
- if (menu.name.indexOf(val)===-1)this.$set(this.menuList[index],"hide",true);
- else {
- this.$set(this.menuList[index],"hide",false);
- if (menu.parent_id){
- let tar = menuMap['_'+menu.parent_id];
- while (tar!==undefined){
- this.$set(this.menuList[tar],"hide",false);
- tar = menuMap['_'+this.menuList[tar].parent_id];
- }
- }
- }
- });
- },
- }
- });
- </script>
- @endsection
|