作者:京东物流 柳宏

1.前置常识

1.1 基本概念

1.1.1 配载
  • 配载代表着某条线路是否具备发往某个方向(区域、省市县、分拣等)的能力,也能够说是网点(分拣核心)是否具备承载配载所指方向货物的能力。个别网络规划者,在平衡线路间货量时,会通过调整配载来实现。
  • 线路上可容许配载货物的“产品类型、最终妥投目的地”,通过线路的配载,计算 以后网点 到 目标网点 的 下一个网点 ,线路 绑定的配载代表通过以后线路最终能够达到的目的地 。以下图为例

  • 示意:如果搁置在整个路由网络资源中,一个标记T1的货物要从北京发往福建,可选的路由有①北京站-北京-武汉-福建-福建站;②北京站-北京-广州-福建-福建站;之所以剔除了北京站-北京-上海-福建-福建站以及北京站-北京-武汉-上海-福建-福建站,正是因为后两条线路中未蕴含T1的配载代码,只标记了T2 ,阐明这条线路只有配载航空的货物,而没有一般陆运的带货能力。
  • 下图就是用于形容配载的树形构造

1.1.2 班期与生生效日期
  • 班期:指的是发运频率,1234567代表着每周七天中,这个班次的“上线工夫”,一般来讲,保护时缺失某个值,会造成路由中断的景象。
  • 生生效日期:指的是该配载无效工夫范畴

1.1.3 配载合并逻辑
  • 网点四级地址的关系以配载树的模式展示,勾选节点增加的配载在右侧的配载列表中展现

  • 当某个节点的子节点没有全副勾选时,展现以后勾选的节点到配载列表中

  • 当某个节点的子节点全副勾选时(在合乎相干条件时,这里波及到的算法逻辑前面详述),展现相应的父节点到配载列表中,这个逻辑是递归的

1.2 现有实现技术

•目前的线路配载前端基于zTree+FixedHeaderTable+JQuery实现,通过zTree监听节点被选中和勾销选中,计算该操作后是否触发节点的合并或开展,进而从新渲染配载列表中的数据

2. 现状问题

2.1 节点合并算法逻辑有误

  • 如果一个父节点下的所有子节点都被保护,即便子节点下的班期不同、生生效日期不重叠,零碎都会主动合并到父节点。合并的展现成果为:
  • 班期:对于纯新增配载显示1234567;对于父节点下有一个子节点,班期显示为已存在配载的班期
  • 生生效工夫:对立为该切段线路的生生效日期
  • 例如:X线路被切割成两段,2022-11-02~2023-01-25以及2022-01-26~短暂无效两段,在线路视图点击2022-11-02~2023-01-25 这段的配载保护,X下有A1(配载工夫为2022-11-02~短暂无效、班期12),其父节点为A,A下还有子节点A2、A3。明天是11.17日,将A2、A3都勾选上(工夫任意,班期为12345),配载会立即合并为A(失效工夫2022-11-02~2023-01-25,配载1234567)
线路X      失效工夫        生效工夫    2022-11-02   2023-01-25A(父节点):蕴含A1、A2、A3三个子节点,以后只存在A1的配载如下:    失效工夫        生效工夫        班期A1  2022-11-02   2099-12-31      12           参考日期为11.17日,此时勾选A2+A3后触发A的合并,此时配载列表展现A节点    失效工夫        生效工夫        班期A  2022-11-02   2023-01-25      1234567

2.2 配载保留和显示的值不统一

  • 下面操作触发合并,提交后库中保留的配载记录为:
    失效工夫        生效工夫        班期A1  2022-11-02    2022-11-16     12A   2022-11-17    2023-01-25     1234567

2.3 实质起因

  • 原有依据zTree节点触发合并的算法有问题,不思考以后节点下其余子节点的配载的班期和生生效日期,而是依据是否同一个父节点间接合并。导致合并逻辑谬误,保留与展现的数据不统一。

3. 预期成果

3.1 配载合并班期逻辑

  • 条件:同一个父节点+各个子节点班期统一
A(父节点):蕴含A1、A2、A3三个子节点,其中任意节点的班期不统一都无奈合并

3.2 配载生生效日期切断逻辑

  • 新增加节点,失效日期为 参考日期,生效日期为 线路生效日期

  • 参考日期抉择 大于 以后 同级子节点的某天,当触发合并时
  • 合并后的父节点:失效日期取参考日期,生效工夫取同级子节点列表中生效工夫最小的
  • 合并后的子节点:

1)如果 原始失效日期小于合并后父节点的失效日期,则切断 原始失效日期 ~ 父节点的失效日期-1天(相当于保留切断前的失效日期那一段)

2)如果 原始生效日期大于合并后父节点的生效日期,则切断 父节点的生效日期+1 ~ 原始生效日期 (相当于保留切断前的生效日期那一段)

  • 针对同一个节点的配载生生效日期切断的逻辑,举例
1. 配载A的原始生生效工夫为 20221103 - 202211102. 配载A在通过同级子节点合并后,生生效工夫为 20221105-202211083. 那么对于配载A来说,在合并后依然须要保留两段配载记录    3.1 生生效工夫为 20221103-20221104    3.2 生生效工夫为 20221109-20221110

3.3 配载合并后保留逻辑

•采纳所见即所的形式保留数据,用户在前端实现切断操作后,保留到数据库的记录与前端展现统一

4. 实现逻辑

4.1 整体逻辑

4.2 定义数据结构及初始化

zTree:配载树treeNode:配载树中的节点nodeId:节点idchildrenNodes:蕴含以后节点的所有子节点汇合stowageList:配载列表的Dom构造originStowageMapTI:原始配载:{key:节点;value:配载数据的dom构造}newStowageMapTI:新增节点配载:{key:节点id;value:节点}stowageFrequencyMap:配载节点和班期关系:{key:节点id;value:班期}stowageTimeMap:配载节点和生生效日期关系:{key:节点id;value:[失效工夫,生效工夫]}frequencyTreeMap:班期和节点的关系:{key:班期;value:节点数组}node.pid:节点的父idnode.id:节点的id

在配载树上监听事件,当触发选中/勾销选中时,递归的获取childrenNodes

保护配载与班期、配载与生生效日期的关系

将已有配载列表中的数据保护到stowageFrequencyMap、stowageTimeMap、originStowageMapTI中

4.3 配载合并班期逻辑

1)如果以后节点非禁用 && 勾选 执行 合并逻辑;否则递归遍历节点;最终返回后果集

2)如果以后节点非半选 && 非父节点,向父节点中查找班期,保护节点属性,退出后果集并返回

3)依据节点的pid查找stowageFrequencyMap中是否存在班期

配载树中的网点关系次要是四级,举例说明 C(快递全国) 上面某些节点的level 与 pid 的关系level=1  pid:C  示意全国level=2 pid:C-10 示意华南level=3  pid:C-10-16 示意福建level=4  pid:C-10-16-1303 示意泉州算法逻辑:依据pid截取相应的字符串为key,查找是否存在父节点的班期

1.如果是父节点则遍历,依照每个子节点去stowageFrequencyMap中获取班期,分为两种状况如下;找到班期后保护frequencyTreeMap,将同班期的节点保护到list中保留,即造成 班期-节点list的数据结构

2.向父节点中获取班期,同上

3.向子节点中递归获取班期,并将后果保留到新的数据结构frequencyChildMap中,而后合并到frequencyTreeMap中

对frequencyTreeMap汇合进行判断,如果数量为1示意 与该节点同级的节点班期雷同,触发了合并,将节点退出后果集返回;否则阐明以后节点的同级节点存在不同班期,不能进行节点向上合并,间接遍历frequencyTreeMap中的value汇合,退出后果集返回

对于触发了合并的后果集 frequencyTreeMap 中的每个节点遍历 同 以后线路的生生效日期比拟,取出同级节点中的最大失效工夫最小生效工夫作为该同级节点中的最大公共工夫范畴设置到每个节点属性中

4.4 配载生生效日期切断逻辑

定义变量

1. queryTime:参考日期2. maxDisableTime:最大生效工夫3. enableTime:线路失效工夫4. disableTime:线路生效工夫5. originEnableTime:记录原始失效工夫6. originDisableTime:记录原始生效工夫7. newDisableTime :enableTime - 24 * 60 * 60 * 10008. newEnableTime:disableTime + 24 * 60 * 60 * 1000

循环遍历每个后果集中的节点,判断是否渲染到配载列表中

依据以后节点id判断是否存在于 stowageList 中,如果存在间接显示;依据节点id删除originStowageMapTI汇合

更新生生效日期,别离判断 原始配载中是否存在须要切断的日期,新增加配载中是否存在须要切断的日期;而后将以后节点增加到配载列表中

  • 遍历 originStowageMapTI ,判断历史的配载节点是否须要进行日期切断,分为以下两种状况;而后依据节点id删除 originStowageMapTI
  • 如果 originEnableTime < enableTime:增加新的配载记录,失效工夫取 originEnableTime, 生效工夫取newDisableTime
  • 如果 originDisableTime > disableTime:增加新的配载记录,失效工夫取 newEnableTime, 生效工夫取 originDisableTime

  • 遍历 newStowageMapTI ,判断新增加的节点是否须要进行日期切断;而后依据节点id删除 newStowageMapTI
  • 如果 originDisableTime > disableTime:增加新的配载记录,失效工夫取 newEnableTime, 生效工夫取 originDisableTime

5. 总结

•路由线路配载保护业务外围且频繁应用性能,为了实现业务述求,将齐全没有关联的树形构造Dom列表联合在一起。采纳了多种数据模型+数据结构的组合模式,结构两者之间的关系,联合遍历、深度优先搜寻、字符串查找等算法进行实现,在春节串点优化专项上线后获得了预期的收益。