上一篇说到如何在前端做多张图片的拖动排序,这篇将会从数据库表的角度,看如何记录这些图片的顺序。
第一想法
首先想到的是在数据库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
表示.而自定义的顺序
不能简单的通过对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空间相册的程序员,以上纯属猜测。如有雷同,纯属巧合
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。