国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

基于layui框架的Table列表,拖拽排序,我來了

兔白白

前言:layui 框架本身不支持table的拖拽排序,不過,在它紅極一時的時候,有過很多優(yōu)秀的第三方擴展插件,借助于這些擴展插件,我們就能輕松的完成拖拽排序這個操作啦

簡單看一下效果圖 動動手指就能輕松完成排序了,排序效果直觀可見

拖拽功能本身因為有第三方的插件,是比較好實現(xiàn)的,重點在于后端的數(shù)據(jù)更新
通常更新數(shù)據(jù)的方案有3種
一、全量更新,直接獲取更新后的列表數(shù)據(jù),將所有的ID 按照順序 發(fā)送給后端,然后后端進行全部更新(優(yōu)點,足夠簡單無腦的,缺點就是,如果數(shù)據(jù)量比較多,這樣更新會性能開銷比較大)
二、取中值法,存儲排序字段,不再是緊湊連續(xù)的,而是每個數(shù)據(jù)直接會間隔一段距離。

例如表的第一條數(shù)據(jù)sort是1000,第二條則是2000 ,第三條3000,以此類推,每個數(shù)據(jù)排序字段間隔1000的差值
然后將數(shù)據(jù)的排序字段通過對拖拽后,獲取到最新的位置前后的數(shù)據(jù)ID,
例如,將第三條數(shù)據(jù) 拖拽到1和2直接,則將1和2 發(fā)送給后端,后端查詢表后,得知他們的排序 分別是 1000,2000
此時 只需要將3的排序值改成(1000+2000)/2 = 1500 即可完成更新
這種更新的方式優(yōu)點顯而易見,只會針對有變動的數(shù)據(jù)進行更新,缺點也很明顯,如果多次更新的話,數(shù)值之間沒有足夠的空間進行二分,就會導致更新失敗
這時,我們就需要針對全表進行一次大的排序重置,將數(shù)據(jù)間的間距重新恢復到初始狀態(tài)才行,所以該方案適合更新頻率不高的場景,或者數(shù)據(jù)量比較小的也可以(另一個缺點則是新增數(shù)據(jù)的時候,也需要動態(tài)去計算排序值了,無法直接使用一個默認的排序值)

三、單表單列 ,這個我沒看懂,有點難復雜,我就不班門弄斧了,原帖在此,有興趣的可以去看看 拖拽排序后臺設計與實現(xiàn)

在這里,我使用的是第二條方案,并且會在無法繼續(xù)取中間值時,自動觸發(fā)全表重置,使用起來 還是挺安逸的

不再廢話,下面開始手摸手實現(xiàn)

我這邊是使用的 webmen-admin 框架,理論上,只要前端是用的layui 都可以使用這個教程的

有請本次友情出場的插件:layui-soul-table

先將插件代碼下載到本地,插件文件很多,因為這個插件的功能確實很多,像什么拖拽排序,表頭篩選,表頭拖拽排序等等... 不過我們先不需要管其他的,先將核心的文件復制一下,也就是 ext 的文件

進入我們自己的項目,在 plugin/admin/public/component/pear/module 目錄下 新建一個文件夾 soulTable,將ext 文件夾中的文件拷貝過來

這兒的 module 文件夾 也就是 layui的模塊文件夾, 如果有第三方插件 都可以放在這兒

新建一個JS文件,也可以直接 在plugin/admin/public/admin/js/common.js 中追加下方的代碼
plugin/admin/public/admin/js/soulTable.js

// 使用 extend 將 剛剛下載的插件 加載進來
layui.extend({
    soulTable:'soulTable/soulTable.slim',// 模塊
})

/**
 * 拖拽表格 進行排序
 * @param obj  當前拖拽對象
 * @param tableId  表的主鍵ID
 * @param updateUrl  更新數(shù)據(jù)的接口
 * @param weightField  排序字段
 */
function rowDragDoneFunc(obj,tableId,updateUrl,weightField){
    weightField = weightField || 'weight';
    console.log(obj.row,'--obj.row')
    // 獲取最新位置 前后數(shù)據(jù)的id
    var beforId = afterId = 0;
    if(obj.newIndex > 0){
        beforId = obj.cache[obj.newIndex-1][tableId]
    }
    if(obj.newIndex < obj.cache.length-1){
        afterId = obj.cache[obj.newIndex+1][tableId]
    }
    var data = {
        dragDone:1,// 增加數(shù)據(jù)標識  方便后臺接口進行判斷
        id:obj.row[tableId],
        field:weightField,
        beforId,afterId
    }
    // 提交數(shù)據(jù)進行排序更新
    layui.$.post(updateUrl,data,function(res){
        if(res.code){
            layui.layer.msg(res.msg,{icon:5});
        }else{
            obj.row[weightField] =res.data;
            refreshTable();
        }
    })
}

在業(yè)務代碼中開始使用
app/admin/view/app/demo/index.html
注意:如果上面是新建的 soulTable.js 文件 則需要在 index.html 中 引入這個js文件方可

  table.render({
      elem: "#data-table",
      url: SELECT_API,
      page: true,
      cols: [cols],
      skin: "row",// line 行邊框風格  row 列邊框風格  nob 無邊框
      even:true,// 隔行換色
      size: "lg",
      toolbar: "#table-toolbar",
      autoSort: false,
      where:{field:'weight',order:'desc'},// 默認使用的weight 倒序
      defaultToolbar: [{
      title: "刷新",
      layEvent: "refresh",
      icon: "layui-icon-refresh",
      }, "filter", "print", "exports"],
      // 關(guān)鍵代碼 拖拽方法回調(diào) rowDragDoneFunc 就是上面創(chuàng)建的方法
      rowDrag:{
        done:(obj)=>{rowDragDoneFunc(obj,PRIMARY_KEY,UPDATE_API,'weight')},
      },
      done: function () {
          layer.photos({photos: 'div[lay-id="data-table"]', anim: 5});

          // 關(guān)鍵代碼 拖拽方法綁定
          soulTable.render(this);
    }})

至此,前端的代碼已經(jīng)添加完畢了,下面需要對后臺代碼進行一點點小小的改動
app/admin/app/servicers/DragdoneUpService.php

<?php

namespace app\admin\app\servicers;

use support\Db;
use support\exception\ApiException;
use support\facade\Logger;
use support\Request;
use support\Response;

class DragdoneUpService extends BaseService
{
    const sortSpace = 1000;// 排序默認間距

    /**
     * 拖拽排序 后臺處理邏輯
     * @param Request $request 接收的參數(shù)
     * @param \support\Model $model 被排序的表
     * @return true
     * @throws ApiException
     */
    static function dragDoneUpData(Request $request,\support\Model $model){
        $primary_key = $model->getKeyName();
        // 獲取前一條數(shù)據(jù)的 排序數(shù)值
        $params = $request->post();
        $field = $params['field'];
        $selfId = $params[$primary_key];
        $afterWeight = $beforWeight = 0;
        if($params['beforId']){
            $beforWeight = $model->where($primary_key,$params['beforId'])->value($field);
        }else{
            // 不存在 則查詢 后一個位置的前一條記錄  先查詢 后者的排序值
            $afterWeight = $model->where($primary_key,$params['afterId'])->value($field);

            $info = $model->where([[$field,'>',$afterWeight],[$primary_key,'<>',$selfId]])->orderBy($field,'desc')->select($primary_key,$field)->first();
            if($info){
                $beforWeight = $info[$field];
                $params['beforId'] = $info[$primary_key];
            }else{
                $beforWeight = -1 ;// 沒有記錄
            }
        }
//        Logger::debug(['$beforWeight',$beforWeight]);
        if(!$afterWeight){
            if($params['afterId']){
                $afterWeight = $model->where($primary_key,$params['afterId'])->value($field);
            }else{
                $info = $model->where([[$field,'<',$beforWeight],[$primary_key,'<>',$selfId]])->orderBy($field,'desc')->select($primary_key,$field)->first();
                if($info){
                    $afterWeight = $info[$field];
                    $params['afterId'] = $info[$primary_key];
                }else{
                    $afterWeight = -1 ;// 沒有記錄
                }
            }
        }

        // 間隔值太小  觸發(fā)全表重排
        if(abs($afterWeight - $beforWeight)<10  ||
            ($beforWeight<0 && $afterWeight<10) ||
            ($beforWeight<10 && $afterWeight<0)
        ){
            self::dragDoneUpDataDefault($model,$field);
            // 再次獲取新的 排序數(shù)值
            $beforWeight = $model->where($primary_key,$params['beforId'])->value($field)?:-1;
            $afterWeight = $model->where($primary_key,$params['afterId'])->value($field)?:-1;
        }

        // 如果當前位置末尾沒有數(shù)據(jù)了
        if($afterWeight == -1) $afterWeight = 0;
        if($beforWeight == -1){
            // 如果當前位置前面沒有數(shù)據(jù)了  則更新的排序值 = 最大的排序值+間隔值
            $newWeight = $afterWeight + self::sortSpace;
        }else{
            // 取中間值 則為當前數(shù)據(jù)的值
            $newWeight = ceil(($beforWeight + $afterWeight) / 2);
        }
//        Logger::debug(['取中間值',$newWeight,$beforWeight,$afterWeight,$params]);
        if($newWeight<2){
//            throw new ApiException('抱歉,排序失敗,取值錯誤');
        }
        // 更新排序
        $model->where($primary_key,$selfId)->update([$field=>$newWeight]);
        return $newWeight;
    }

    /**
     * 全表重排排序
     * @param \support\Model $model
     * @param $field
     * @param $sortSpace
     * @return void
     */
    static protected function dragDoneUpDataDefault(\support\Model $model,$field){
        $tableName = $model->getTable();
        $primary_key = $model->getKeyName();
        $sortSpace = self::sortSpace;
        DB::statement("SET @row_number = 0");
        $sql = " UPDATE $tableName t1
                JOIN (
                    SELECT id, (@row_number := @row_number + 1) AS new_weight
                    FROM (
                        SELECT id, $field
                        FROM $tableName
                        ORDER BY $field asc,$primary_key asc
                    ) AS sorted_table
                ) AS t2 ON t1.id = t2.id
                SET t1.$field = t2.new_weight * $sortSpace";
        return Db::statement($sql);
    }
}

最后,前往我們的業(yè)務控制器中, 調(diào)用我們上方聲明的方法即可
app/admin/app/controller/DemoController.php


    /**
     * 更新
     * @param Request $request
     * @return Response
     * @throws BusinessException
    */
    public function update(Request $request): Response
    {
        if ($request->method() === 'POST') {
            // 通過前端我們安排的間諜 dragDone 來判斷本次請求是否是拖拽排序
            // 拖拽排序更新
            if($request->post('dragDone')==1 && DragdoneUpService::dragDoneUpData($request,$this->model)){
                return $this->json(0,'ok');
            }
            return parent::update($request);
        }
        return view('app/demo/update');
    }

好了,到此為止,相信各位看官都能夠輕松完成表格的拖拽排序啦~~~
(小插曲,最開始是想給一鍵菜單里面加個拖拽排序。畢竟 字段不能拖拖 著實難受,不過 在那邊試了下 遇到了點挫折,明天我會繼續(xù)努力的,如果成功了,我再來更新 ^_^)

5783 2 2
2個評論

jian1098

正好頭疼這個排序問題,每次建表創(chuàng)建時間排前面看著難受,下午試試看

hulang

dragDoneUpDataDefault函數(shù)里面的SQL,能否PHP

  • 兔白白 2024-06-24

    這個sql 我只會原生的寫法。 用 orm 不知道怎么寫 QAQ

  • hulang 2024-06-24

    這,好吧。。。。

兔白白

1000
積分
0
獲贊數(shù)
0
粉絲數(shù)
2024-04-18 加入
??