自定義排序的表設計

上一篇說到如何在前端作多張圖片的拖動排序,這篇將會從數據庫表的角度,看如何記錄這些圖片的順序。javascript

第一想法

首先想到的是在數據庫photo表中添加字段order,用來記錄圖片在其所在的相冊中的位置.表的結果相似於
圖片描述
album_id是圖片所在相冊的idhtml

  • 用戶上傳圖片時,選出相冊最大的order,前端

select max(order) from photo where album_id=?

而後在插入行的時候,order列是max(order)+1.java

  • 圖片移動到其餘相冊時,修改album_id爲目標相冊album_id,而後像上面,選出目標相冊最大的order,並將其設置爲要移動的圖片order.程序員

  • 多張圖片拖動排序時,。。。本屌不敢想象,太複雜了。sql

設置更新時間?

和上面添加order字段相似,這裏添加字段update_time,表示圖片最近一次更新的時間。
圖片描述數據庫

  • 上傳圖片,update_time是上傳時間。segmentfault

  • 移動圖片,update_time是移動操做當前的時間。ui

  • 圖片拖動排序,好比
    圖片描述
    圖片移動到圖片2,3之間,這時,將被移動圖片的update_time設置爲圖片2,3的update_time之和除以2,以確保順序。
    若是拖動的是多張圖片,好比拖動2張,那第2張圖片的update_time是上圖中第3(第一張拖動圖片),4張圖片的update_time之和除以2.其餘的依次類推。spa

qq空間是怎麼作的?

qq空間裏圖片的批量管理,也有拖動排序。看下傳遞給後臺的參數
圖片描述

參數說明

codeList是選中拖動圖片的photo_id,以_做爲分隔符,這裏選中了3張圖片。
prevKey,nextKey是拖動的目標位置左右兩邊圖片的photo_id.
prevIdx,nextIdx是拖動的目標位置左右兩邊圖片的索引,這裏是想把圖片插到第2,3張圖片之間。

雙向鏈表

看到上面的參數,是否是很容易想到雙向鏈表
圖片描述
上圖是相冊沒有進行過任何拖動排序的狀況,prev,next字段爲0分別表示該圖片已經相冊是第一張或最後一張圖片。

拖動排序

如今拖動排序,圖片從左到右的photo_id依次爲1-8,拖動的圖片photo_id是7,目標是photo_id是2,3的圖片之間。
圖片描述
具體操做

  • 選出拖動圖片的prev,next

select prev,next from photo where photo_id=7
  • 選出拖動圖片的前一張(若是有)圖片和後一張(若是有)圖片

select photo_id as prev_photo from photo where photo_id<7 limit 1
select photo_id as next_photo from photo where photo_id>7 limit 1
  • 將拖動圖片的前一張圖片和後一張圖片連起來

update photo set next=next_photo where photo_id=prev_photo
update photo set prev=prev_photo where photo_id=next_photo
  • 將拖動圖片插到目標位置

update photo set next=7 where photo_id=2
update photo set prev=7 where photo_id=3
update photo set prev=2,next=3 where photo_id=7

這裏只拖動了一張圖片,若是拖動多張的話,代碼就要複雜些,由於拖動的各照片要構建雙向鏈表。本屌暫時不寫多張拖動的狀況,之後有時間的話會補上。

上傳圖片

  • 找到最後一張圖片

select photo_id as last_photo from photo where next=0
  • 上傳圖片

  • 上傳的圖片放到最後

update photo set next=upload_photo where photo_id=last_photo
update photo set prev=last_photo,next=0 where photo_id=upload_photo

刪除圖片

  • 選出拖動圖片的prev,next

select prev as prev_photo,next as next_photo from photo where photo_id=7
  • 將刪除圖片的前一張圖片和後一張圖片連起來

update photo set next=next_photo where photo_id=prev_photo
update photo set prev=prev_photo where photo_id=next_photo
  • 刪除圖片

移動圖片

前面的操做都是在一個相冊中進行,因此where條件中就沒寫album_id.
qq空間中圖片移動到另外一個相冊,圖片會被排到相冊的最後一個位置,這裏也同樣。
具體的

  • 選出移動圖片的prev,next

select prev,next from photo where photo_id=move_photo
  • 選出移動圖片的前一張(若是有)圖片和後一張(若是有)圖片

select photo_id as prev_photo from photo where photo_id<move_photo limit 1
select photo_id as next_photo from photo where photo_id>move_photo limit 1
  • 將移動圖片的前一張圖片和後一張圖片連起來

update photo set next=next_photo where photo_id=prev_photo
update photo set prev=prev_photo where photo_id=next_photo
  • 找到另外一個相冊中的最後一張圖片

select photo_id as last_photo from photo where next=0 and album_id=another_album
  • 移動的圖片放到最後

update photo set next=move_photo where photo_id=last_photo
  • 設置移動圖片的prev,next

update photo set prev=last_photo,next=0 where photo_id=move_photo

雙向鏈表如何呈現?

上一節說的是在不一樣場景下,數據庫表該如何變化,實際就是很簡單的雙向鏈表操做。可是若是用這種表結構不能按用戶自定義的順序把圖片呈現出來,仍是沒什麼卵用。
下面說說怎麼呈現。
一般圖片都是按時間降序排列,這裏簡單的用order by photo_id desc表示.而自定義的順序不能簡單的經過對prevnext列的排序得到。

var data=[//順序:5 2 3 9 8 1 4 10 7 6
            {id:10,prev:4,next:7},
            {id:9,prev:3,next:8},
            {id:8,prev:9,next:1},
            {id:7,prev:10,next:6},
            {id:6,prev:7,next:0},
            {id:5,prev:0,next:2},
            {id:4,prev:1,next:10},
            {id:3,prev:2,next:9},
            {id:2,prev:5,next:3},
            {id:1,prev:8,next:4}
        ];

既然數據庫不能排序就只有寫代碼排序了。這裏用js排序,代碼很簡單,沒幾行

順序:5 2 3 9 8 1 4 10 7 6
    <div ms-controller='sort'>
        <ul>
            <li ms-repeat='list'>
            pic{{el.id}}   prev:{{el.prev}}   next:{{el.next}}
            </li>
        </ul>
    </div>
require(['avalon'],function(avalon){
        var sort=avalon.define({
            $id:'sort',
            list:[]
        });
        avalon.scan();
        var data=[//先按時間降序排列,而後自定義順序:5 2 3 9 8 1 4 10 7 6
            {id:10,prev:4,next:7},
            {id:9,prev:3,next:8},
            {id:8,prev:9,next:1},
            {id:7,prev:10,next:6},
            {id:6,prev:7,next:0},
            {id:5,prev:0,next:2},
            {id:4,prev:1,next:10},
            {id:3,prev:2,next:9},
            {id:2,prev:5,next:3},
            {id:1,prev:8,next:4}
        ];
        var next=0,result=[],photo_id_arr=[];//photo_id_arr保存全部的photo_id
        data.sort(function(a,b){//排序只是爲了保證data[0]取到的是鏈表的頭元素
            return a.prev-b.prev;
        });
        avalon.each(data,function(i,el){
            photo_id_arr.push(el.id);
        });
        while(next!=-1){//若是元素的next(即下一個photo_id)在photo_id_arr中存在
            var cur=data[next];
            result.push(cur);
            next=photo_id_arr.indexOf(cur.next);
        }
        sort.list=result;
    });

圖片描述
例子下載
本屌非開發qq空間相冊的程序員,以上純屬猜想。若有雷同,純屬巧合

相關文章
相關標籤/搜索