Ver Fonte

动态菜单后台逻辑与前台渲染生成部分

Zhouzhendong há 5 anos atrás
pai
commit
a031b38bcf

+ 21 - 0
app/Http/Controllers/MenuController.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Controllers;
+
+class MenuController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\View\View
+     */
+    public function index()
+    {
+        return \view("maintenance.menu.index",["menus"=>app("MenuService")->getMenu()]);
+    }
+
+    public function update()
+    {
+
+    }
+}

+ 0 - 1
app/Services/MenuService.php

@@ -45,7 +45,6 @@ class MenuService
 
     public function getVisibleFunctionList()
     {
-        Cache::flush();
         /** @var Collection $authorities */
         $authorities = app("AuthorityService")->getUserAuthority();
         if (!$authorities)$authorities = [];

+ 6 - 2
resources/views/layouts/app.blade.php

@@ -45,8 +45,12 @@
             let dom = createBeforeMenu(type);
             for (let i=0;i<menus.length;i++){
                 if (!menus[i].route)continue;
-                let uri = menus[i].route.split(/[/?]/)[type-1];
-                let isEquals = uri==='*' || uri===relativeUrl[type-1];
+                let uri = menus[i].route.split(/[/?]/);
+                let isEquals = uri[type-1]===relativeUrl[type-1];
+                if (uri[type-1]==='*'){
+                    if (uri[type]===relativeUrl[type]) isEquals=true;
+                    else continue;
+                }
                 dom.appendChild(createChildElement(type,menus[i],isEquals));
                 if (isEquals && menus[i].child && menus[i].child.length>0){
                     createMenu(type+1,menus[i].child);

+ 1 - 1
resources/views/maintenance/index.blade.php

@@ -2,7 +2,7 @@
 @section('title')设置@endsection
 
 @section('content')
-    @component('maintenance.menu')@endcomponent
+    {{--@component('maintenance.menu')@endcomponent--}}
 {{--    <div class="container-fluid" id="nav2">--}}
 {{--        <div class="card">--}}
 {{--            --}}

+ 21 - 0
resources/views/maintenance/menu/_modal.blade.php

@@ -0,0 +1,21 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="modal">
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <label class="col-2 offset-1" for="name">名称</label>
+                    <input class="col-7 form-control form-control-sm" :class="errors.name ? 'is-invalid' : ''" id="name" type="text" v-model="unit.name">
+                    <span class="invalid-feedback mt-0 offset-3" role="alert" v-if="errors.name">
+                        <strong>@{{ errors.name[0] }}</strong>
+                    </span>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-success" @click="submitUnit()">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 186 - 0
resources/views/maintenance/menu/index.blade.php

@@ -0,0 +1,186 @@
+@extends('layouts.app')
+@section('title')菜单@endsection
+
+@section('content')
+    <div class="container-fluid" id="container" @drop="drop($event)" @dragover="dragover($event, false)">
+        @include("maintenance.menu._modal")
+        <div class="card">
+            <div class="card-body">
+                @can("计量单位-录入")<button class="btn btn-outline-info mb-1 mr-3" @click="openModal()"><span class="fa fa-plus"></span>&nbsp;新&nbsp;&nbsp;增</button>@endcan
+                @can("计量单位-录入")<button class="btn border border-2 mb-1 mr-3" :class="isSaveSort ? 'btn-success' : 'text-secondary'" :disabled="!isSaveSort" @click="sort()"> 保 存 </button>@endcan
+                <div class="row text-nowrap" style="cursor: move;">
+                    <ul class="list-group col-9 offset-1">
+                        <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 v-if="menu.font" :class="menu.font" :style="menu.font_style"></span>@{{ menu.name }}
+                            <div class="row">
+                                <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)">
+                                        @{{ menu2.name }}
+                                        <div class="row" style="margin-left: 50px">
+                                            <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)">
+                                                    @{{ menu3.name }}
+                                                    <div class="row" style="margin-left: 50px">
+                                                        <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 }}
+                                                            </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,
+            },
+            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;
+            },
+            methods:{
+                openModal(unit = null){
+                    if (unit) this.unit={id:unit.id,name:unit.name};
+                    else this.tag={id:"",name:""};
+                    $("#modal").modal("show");
+                },
+                submitUnit(){
+                    let url="{{url('maintenance/unit/save')}}";
+                    let msg=this.unit.id ? "成功修改单位“"+this.unit.name+"”"  : "成功新增单位“"+this.unit.name+"”";
+                    window.tempTip.postBasicRequest(url,this.unit,(res)=>{
+                        if(res && res.errors){
+                            this.errors = res.errors;
+                            return '';
+                        }
+                        if (this.unit.id){
+                            this.units.some((unit)=> {
+                                if (unit.id === this.unit.id){
+                                    unit.name = this.unit.name;
+                                    return true;
+                                }
+                            });
+                        }else this.units.unshift({
+                            id:res.id,
+                            name:res.name,
+                            created_at:res.created_at,
+                        });
+
+                        $("#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.dragoverId = "";
+                    this.isDragover = false;
+                    this.isSaveSort = true;
+                },
+                handleDrag(id){
+                    return new Promise((resolve, reject)=>{
+                        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.parent_id = newParent;
+                            let oldLevel = dom.getAttribute("data-level");
+                            let newLevel = parent ? parent.getAttribute("data-level") : 1;
+                            let diff = oldLevel-newLevel;
+                            if (diff!=0){
+                                dom.setAttribute("data-level",newLevel);
+                                params.level = newLevel;
+                                params.diff = diff;
+                                let child = dom.getElementsByTagName("LI");
+                                if (child.length>0){
+                                    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 parent = document.getElementById("parent").children;
+                    let update = [["id","sequence"]];
+                    for (let i=0;i<parent.length;i++){
+                        let order = parent[i].getAttribute("data-order");
+                        let id = parent[i].getAttribute("data-id");
+                        if (id && order !== i+1)update.push({id:id,sequence:i+1});
+                    }
+                    if (update.length > 1){
+                        let url = "{{url('maintenance/unit/sort')}}";
+                        window.tempTip.postBasicRequest(url,{"update":update},res=>{
+                            this.isSaveSort = false;
+                            return "";
+                        });
+                    }else this.isSaveSort = false;
+                },
+            }
+        });
+    </script>
+@endsection

+ 5 - 0
routes/web.php

@@ -34,6 +34,11 @@ Route::group(['prefix'=>'password'],function(){
 Route::get('denied',function (){return view('exception.authority');});
 /** 基础设置 */
 Route::group(['prefix'=>'maintenance'],function(){
+    /** 菜单 */
+    Route::get('menu', 'MenuController@index');
+    Route::group(['prefix'=>"menu"],function (){
+        Route::get('update', 'MenuController@update');
+    });
 
     /** 商品 */
     Route::group(['prefix'=>'commodity'],function(){