teambition的任务卡排序,数据是怎么存储的?

teambition的任务卡支持拖拽排序,如果从最底下拖到最顶部,数量很多时,是怎么去存这个新的顺序的?应该不会选择最暴力的方式,把每个任务卡的排序值…
关注者
121
被浏览
30,512

4 个回答

刚好这个功能是我和

@isayme

做的, 可以来答一下。


初始的时候每个任务在数据库中都有一个 order 值

{
  "_id": "xxxxx",
  "order": 100
}

然后相邻的任务间的 order 值有一个很大的差值,比如:

{
  "_id": "xxxxx",
  "name": "task 1",
  "order": 100
}

{
  "_id": "xxxxx",
  "name": "task 2",
  "order": 500
}

在用户拖拽重新排序的时候,前端会发一个 `put` 请求更新任务的 order 值:

// put /api/tasks/xxxx

const newOrder = (nextOrder - lastOrder) / 2
{
  _id: 'xxxx',
  order: newOrder
}

这个 newOrder 是前端计算出来的 nextOrder 与 lastOrder 的中间值(不需要为整数,只需要保证比前一条任务的 order 大比后一条任务的 order 小即可)。后端接受到这个值之后会计算出它新的位置,并根据新的位置计算出新的 order 值(和前端计算出来的不一样)。

然后判断这个新的 order 值是否在安全范围内:即它与上一个/下一个 任务的 order 差是否过小,如果比安全值大则将新的 order 插入数据库然后返回新的 order,前端以新的 order 为真正的任务 order。

如果比安全值小则对整个任务分组的任务 order 重计算。然后通过 socket 发送一条 stage/refresh 消息通知前端重新拉取整个任务阶段的任务(概率极小)。

@太狼 邀.

问题"最底下拖到最顶部"的答案: 通常都是仅更新被移动任务的位置信息.


两个前提:

  1. 位置的信息记录在任务的模型上(pos字段);
  2. 一般两个任务的pos值相差很大(默认是65536);

现在假设有任务 A, B, C. 列举几个常见的场景:

  • 如果C要移到A的前面, 那么后端会把 C.pos 改为 A.pos/2;
  • 若果C要移到A和B之间, 那么后端会把 C.pos 改为 (A.pos + B.pos)/2;
  • 如果B要移到C的后面, 那么后端会把 B.pos 改为 C.pos + 65536;

当然这里会有个极端情况需要处理(假设pos是整数):

如果 A.pos 是 1, B.pos 是 2, C想移到A和B之间, 其实是没有一个整数可以用的, 针对这种情况, 后端会重新给整个列表的任务重新刷一遍pos值.

更改任务位置时, 后端之所以不直接使用前端传的pos值是为了避免人为的创造极端场景...

为什么?