物流路由线路配载前端算法逻辑实现方案

news2025/6/19 12:38:05

作者:京东物流 柳宏

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-022023-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-022023-01-25,配载1234567)
线路X  
    生效时间        失效时间
    2022-11-02   2023-01-25

A(父节点):包含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     12
A   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 - 20221110
2. 配载A在经过同级子节点合并后,生失效时间为 20221105-20221108
3. 那么对于配载A来说,在合并后仍然需要保留两段配载记录
    3.1 生失效时间为 20221103-20221104
    3.2 生失效时间为 20221109-20221110


3.3 配载合并后保存逻辑

•采用所见即所的方式保存数据,用户在前端完成切断操作后,保存到数据库的记录与前端展示一致

4. 实现逻辑

4.1 整体逻辑

4.2 定义数据结构及初始化

zTree:配载树
treeNode:配载树中的节点
nodeId:节点id
childrenNodes:包含当前节点的所有子节点集合
stowageList:配载列表的Dom结构
originStowageMapTI:原始配载:{key:节点;value:配载数据的dom结构}
newStowageMapTI:新增节点配载:{key:节点id;value:节点}
stowageFrequencyMap:配载节点和班期关系:{key:节点id;value:班期}
stowageTimeMap:配载节点和生失效日期关系:{key:节点id;value:[生效时间,失效时间]}
frequencyTreeMap:班期和节点的关系:{key:班期;value:节点数组}
node.pid:节点的父id
node.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 * 1000
8. 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列表结合在一起。采用了多种数据模型+数据结构的组合形式,构造两者之间的关系,结合遍历、深度优先搜索、字符串查找等算法进行实现,在春节串点优化专项上线后取得了预期的收益。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go 构建基础的事件调度器

&#x1f447;我在这儿 当我们需要在一段时间后的特定时间或间隔运行任务时&#xff0c;我们需要使用任务调度系统来运行任务&#xff1a;例如发送电子邮件、推送通知、午夜关闭账户、清空表格等。在本文中&#xff0c;我们将构建一个基本的事件调度程序&#xff0c;使用数据库…

基于springboot和ajax的简单项目 02.一直会出现的页面的上一页,下一页,分页与总页数 (下)

在各种功能中会一直出现页面分页的问题。 对此&#xff0c;可以使用pojo对象&#xff0c;来一直管理页面分页的功能。 01.创建相关的pojo对象。 由于属性是来辅助sql语句的&#xff0c;这个pojo对象。 Setter Getter ToString NoArgsConstructorpublic class PageObject<T&…

MySQL数据库实现主从同步

安装MySQL数据库8.0.32 前言 今天来学习数据库主从同步的原理及过程&#xff0c;数据库主要是用来存储WEB数据&#xff0c;在企业当中是极为重要的&#xff0c;下面一起来看下。 1.1 数据库做主从的目的 MySQL主从复制在中小企业&#xff0c;大型企业中广泛使用&#xff0c…

【ROS2指南-2】入门 turtlesim 和 rqt

目标&#xff1a;安装并使用 turtlesim 包和 rqt 工具为即将到来的教程做准备。 教程级别&#xff1a;初学者 时间&#xff1a; 15分钟 内容 背景 先决条件 任务 1 安装turtlesim 2 启动turtlesim 3 使用turtlesim 4 安装rqt 5 使用 rqt 6 重新映射 7 关闭turtlesim …

算法 || DFS(深度优先搜索) BFS(广度优先搜索)

&#xff11;、基本概念 dfs全称为Depth First Search,即深度优先搜索。它的思想是沿着每一条可能的路径一个节点一个节点地往下搜索,搜到了路径的到终点再回溯,一直到所有路径搜索完为止。 bfsbfs全称为Breath First Search,即广度(宽度)优先搜索。它的思想是将每一层的结搜…

【SQL】数据库的创建,表的创建、更新、删除

本文内容参考书籍《SQL基础教程》&#xff0c;初学者&#xff0c;请多指教。 一、数据库的创建 1、创建数据库语句 CREATE DATABASE <数据库名称>; 2、示例 CREATE DATABAST shop&#xff1b; 二、表的创建 创建表之前&#xff0c;必须先创建用于存储表的数据库。 1、…

如何找出消耗CPU最多的线程?

如何找出消耗CPU最多的线程&#xff1f; 1.使用 top -c 找出所有当前进程的运行列表 top -c 2.按P(Shiftp)对所有进程按CPU使用率进行排序&#xff0c;找出消耗最高的线程PID ​​​ 显示Java进程 PID 为 136 的java进程消耗最 3.使用 top -Hp PID&#xff0c;查出里面消…

JavaEE简单示例——基于XML配置文件的SSM整合

SSM整合 在本节中&#xff0c;我们会将之前我们学习过的三个框架结合起来&#xff0c;让他们可以融合起来&#xff0c;搭建成一个完整的贯穿整个三层架构的整体框架。 三层框架与对应的框架功能 我们首先回顾一下我们编写软件的三层框架以及对应使用的框架都分别是什么&…

代码随想录算法训练营第五十九天| 503. 下一个更大元素 II、42. 接雨水。

503. 下一个更大元素 II 题目链接&#xff1a;力扣 题目要求&#xff1a; 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。数字 x 的 下一个更大的元素 是按数组遍历顺…

( “树” 之 DFS) 110. 平衡二叉树 ——【Leetcode每日一题】

110. 平衡二叉树 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] …

智慧钢铁厂人员定位系统解决方案,助力钢铁企业提升安全生产管理水平

作为国民经济的基础原材料产业&#xff0c;钢铁工业在经济发展中具有重要地位。中国钢铁工业不仅为我国国民经济的快速发展做出了重大贡献&#xff0c;也为世界经济的繁荣和世界钢铁工业的发展起到了积极的促进作用&#xff0c;但钢铁行业在快速发展的同时也存在一些安全管理问…

React应用(基于React脚手架)

目录前言&#xff1a;一、使用create-react-app创建react应用1、什么是 react 脚手架&#xff1f;2. 创建 cli 脚手架方式13. 创建 cli 脚手架方式24. npx:5. react脚手架项目结构6. 功能界面的组件化编码流程&#xff08;通用&#xff09;7. 如何更改脚手架版本二、React 组件…

【SpringMVC】7—文件上传

⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; 如果文章对你有所帮助&#xff0c;可以点赞&#x1f44d;…

【深入理解SSD 实践】对NVMe SSD热插拔时,正确做法是怎样的?

声明 主页&#xff1a;元存储的博客_CSDN博客 依公开知识及经验整理&#xff0c;如有误请留言。 个人辛苦整理&#xff0c;付费内容&#xff0c;禁止转载。 内容摘要 前言 概念 SAS/SATA 和NVMe 区别 热插拔分类 热插拔基本原理 如何确认是否支持热插拔&#xff1f; 热插…

Python批量导出阿里云ECS和Redis实例的监控数据到Excel

背景 某公司使用阿里云的 ECS 和 Redis 服务作为其业务支撑&#xff0c;为了及时了解机器的使用情况&#xff0c;领导要求业务部门对所有阿里云机器的平均资源使用率进行统计&#xff0c;并汇总在一个 Excel 表格中&#xff0c;以便领导查看和分析。 需求 为了满足领导的需求…

C++ const的作用

1.const在C中是只读变量&#xff0c;在C中表示常量 以下代码&#xff0c;在C中是错误的&#xff0c;但是在C中是正确的。 void main() {const int n 10;int arr [n]; }2.const不仅可以定义一个常量&#xff0c;也可以定义函数参数 例如&#xff1a; char *strcpy(char *dest…

一次弄懂gzip模块启用和配置指令

接下来所学习的指令都来自ngx_http_gzip_module模块&#xff0c;该模块会在nginx安装的时候内置到nginx的安装环境中&#xff0c;也就是说我们可以直接使用这些指令。 1. gzip指令&#xff1a;该指令用于开启或者关闭gzip功能 注意只有该指令为打开状态&#xff0c;下面的指令才…

联想凌拓 ThinkSystem DE 系列全闪存阵列

ThinkSystem DE 系列全闪存阵列 超高的性能&#xff0c;极具竞争力的价格 通过消除过量配置最大限度地提高效率&#xff0c;同时通过降低空间、电源和冷却要求来降低成本。 利用高级数据保护&#xff0c;在本地或从远距离上防止数据丢失和停机事件。 在模块化 2U 构建模块中…

ModStartBlog v7.1.0 ChatGPT支持,界面全新优化

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场&#xff0c;后台一键快速安装 …

【ChatGPT】ChatGPT-5 强到什么地步?

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 ChatGPT-5 强到什么地步&#xff1f; 技术 深度学习模型的升级 更好的预测能力 自适应学习能力 特点 语言理解能力更强 自我修正和优化 更广泛的应用领域 应用 对话系统 智能写作…