最近公司做一个个性化很高的需求
概括为:

  1. 页面分两个区域。上方待审核区域,下方冲突区域。点击审核时上方数据全通过(请求中附带当前数据所放置通道数),下方数据全拒绝。
  2. 每天有不定量申请需要安排在通道中,一个通道表示一天24小时,通道数可配置,不同申请在同一通道中时间不重叠。
  3. 进入页面时自动排序,优先排列该天已经审核通过的请求,上方待审核通道依次排满后,剩余申请落入下方冲突区域,冲突区域每个申请独占一个通道。
  4. 所有申请都可进行手动拖动(仅上下拖动)切换通道和区域,当检测到拖动放置位置有数据时进行替换,原申请落入冲突区域。

数据结构

做需求时合适的数据结构非常重要,应该是优先考虑的问题,以下是我构建数据结构时的思路:
数据结构:每个格子应该有一个对象记录自己的时间属性,是否被占有,可以是二维数组,一维代表通道数。

进入页面获取数据后需要先在js中做一个计算(着重点),根据给出的通道数和申请信息做计算,区分出排在待审核区域的申请数组和排在冲突区域的申请数组。在这个计算过程中还需要给通道中的被占用cell做出标记,方便之后的手动排序。

实现思路

做比较复杂的需求先理清一下思路,这块功能有自动排序手动排序两大块。

  • 自动排序实现要点:
  1. 根据拿到的通道数,每个通道初始化48个小格子,带有时间信息和占用状态。
  2. 遍历每个申请,从第一个通道开始对比申请所需时间段内每个半小时格子是否都可用,当能都可用时,push进top数组(还需记录能放下的通道index)。当放不下时push进bottom数组。
  3. 全部计算完毕后,根据两个数组渲染出两组ref,下方通道数根据bottom数组的长度进行动态变化。

第二步才能是根据这两个数组动态渲染出位于两个区域的申请div

  • 手动排序实现要点:
  1. 拖动时div的位置鼠标跟随-每个请求产生的div都需要绑定一个ref(div的宽度根据请求的时间段长短决定),并且只做y轴的位置改变,x轴不变(onmousemove事件、mousedown事件、mouseup事件)
  2. 位置吸附功能,更靠近哪一个通道(不用考虑更靠近哪一个半小时格子,请求的时间段不能改变)
  3. div替换功能,当放下位置有安排请求时(宽度上有接触),将原来的请求在该通道显示取消
  4. 是否可替换的判断,待审核区域会显示审核通过的请求,该状态请求不可再被替换,即当mouseup时,不能放下
  5. 两个区域的动态渲染,待审核区域的通道数由后台决定,冲突公司的行数是无限向下扩展的,但一个公司会占据完整一行
  6. 拖动时还需要一个临时数组,被拖动起来的div代表的申请不属于上方所说的任一数组,直到放下时才做判断,push进哪一个

拖动注意点:

边界的判断和计算,当前通道,上方总通道,和下方总通道都已知。可计算。

样式的变换不能用数据判断直接替换css类的方法,因为在切换的时候,位置信息的设置会失效。应直接在js中改变css信息。

拖动结束时的判断:

  • 只在下方拖动,回到原位置
  • 拖动到了上方,

    1. 判断是哪个通道
    2. 判断该通道上是否有申请(cell上应该记录申请的信息,状态)

      • 有,并且已经被审核,不能替换,回到原位置√
      • 有,(1~多个)初始排序后的同等级申请, 替换。
      • 没有(第一次拖动所有通道该位置不出现空缺,只有二次及以上才会出现该情况,即原始自动排序顺序被打乱),将该申请移动到上方数组中,并标记好通道数
  • 替换操作

拖动和吸附时如何判断到哪个通道了:通过高度计算

判断该通道上是否有申请:找到通道了,根据通道index找到cell,cell中有状态信息

判断是否可放下:遍历拖动申请在该通道上需要占用的cell信息,根据该段cell记录的信息(是否被占用,以及被占用的申请的状态)

同等级申请的替换思路:

操作数据控制页面显示-不知道ref有没有什么异常(ref不是响应的)

  1. 遍历当前通道:找到并记录所有当前申请所需时间段上的冲突申请,处理冲突申请:将冲突申请的pipeindex置空,从top数组删除该item,bottom数组中添加该item。
  2. 绘制新添加的bottom申请
  3. 替换时cell上的记录也需要做改变;

实现效果:

image.png
项目地址,可查看详细代码和注释。并预览操作


夏安蝉
39 声望3 粉丝

路很长,慢慢走