上一篇说到如何在前端做多张图片的拖动排序,这篇将会从数据库表的角度,看如何记录这些图片的顺序。
首先想到的是在数据库 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空间里图片的批量管理,也有拖动排序。看下传递给后台的参数
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
表示.而 自定义的顺序
不能简单的通过对 prev
, next
列的排序获得。
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空间相册的程序员,以上纯属猜测。如有雷同,纯属巧合