转载

自定义排序的表设计

上一篇说到如何在前端做多张图片的拖动排序,这篇将会从数据库表的角度,看如何记录这些图片的顺序。

第一想法

首先想到的是在数据库 photo表 中添加字段 order ,用来记录图片在其所在的相册中的位置.表的结果类似于

自定义排序的表设计

album_id是图片所在相册的id

  • 用户上传图片时,选出相册最大的order,

select max(order) from photo where album_id=?

然后在插入行的时候,order列是max(order)+1.

  • 图片移动到其他相册时,修改album_id为目标相册album_id,然后像上面,选出目标相册最大的order,并将其设置为要移动的图片order.

  • 多张图片拖动排序时,。。。本屌不敢想象,太复杂了。

设置更新时间?

和上面添加 order 字段类似,这里添加字段 update_time ,表示图片最近一次更新的时间。

自定义排序的表设计
  • 上传图片, update_time 是上传时间。

  • 移动图片, update_time 是移动操作当前的时间。

  • 图片拖动排序,比如

    自定义排序的表设计

    图片移动到图片2,3之间,这时,将被移动图片的 update_time 设置为图片2,3的 update_time之和除以2 ,以确保顺序。

    如果拖动的是多张图片,比如拖动2张,那第2张图片的 update_time 是上图中第3 (第一张拖动图片) ,4张图片的 update_time之和除以2 .其他的依次类推。

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空间相册的程序员,以上纯属猜测。如有雷同,纯属巧合

正文到此结束
Loading...