8

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

第一想法

首先想到的是在数据库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空间相册的程序员,以上纯属猜测。如有雷同,纯属巧合


TheViper
465 声望16 粉丝