From 01292306396f4e2a0556e1308609d763e37db53f Mon Sep 17 00:00:00 2001 From: zhouz <> Date: Mon, 17 Aug 2026 18:00:49 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=A2=9E=E5=8A=A0=E6=97=A5=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E5=A4=87=E8=B4=A7=E5=A5=97=E7=AE=A1=E6=97=B6=E5=BA=8F?= =?UTF-8?q?=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/lms日计划备货套管代码导读.md | 256 +++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 docs/lms日计划备货套管代码导读.md diff --git a/docs/lms日计划备货套管代码导读.md b/docs/lms日计划备货套管代码导读.md new file mode 100644 index 00000000..ec6d467b --- /dev/null +++ b/docs/lms日计划备货套管代码导读.md @@ -0,0 +1,256 @@ +# LMS 日计划、备货、套管代码导读 + +本文对应当前 LMS 日计划和管芯调度实现,用于快速定位业务入口、调度决策、现场任务以及完成回调。 + +## 一、先建立整体认识 + +系统分为两条调用链: + +1. 人工操作链:页面调用日计划接口,只修改订单、备货、套管状态,不直接创建现场任务。 +2. 定时调度链:XXL-JOB 查询状态为“进行中且未完成”的日计划,按顺序或权重策略创建现场任务;任务完成回调后才累计数量。 + +备货和套管共用日计划,但分别维护状态、进度、策略和 Claim,因此两种作业可以并行,互不占用对方的领取记录。 + +## 二、日计划人工操作时序 + +```mermaid +sequenceDiagram + autonumber + actor Worker as 工人 + participant Page as 日计划管理/作业页面 + participant Controller as DailyPlanController + participant Service as DailyPlanServiceImpl + participant Mapper as DailyPlanMapper + participant DB as MySQL + + Worker->>Page: 创建或查看日计划 + Page->>Controller: create / managementPage / workPage + Controller->>Service: 创建或查询 + Service->>Mapper: 读写日计划 + Mapper->>DB: lms_daily_plan + DB-->>Page: 日计划及当前状态 + + Worker->>Page: 开始订单并确认计划量 + Page->>Controller: startOrder(planQty, appendQty, version) + Controller->>Service: startOrder + Service->>Mapper: 校验未开始和版本,更新订单状态 + Service->>Mapper: 写数量及订单操作日志 + + Worker->>Page: 开始备货或开始套管 + Page->>Controller: startStocking / startSleeving + Controller->>Service: 变更对应作业状态 + Service->>Mapper: 状态改为进行中并记录日志 + Note over Service,DB: 此处只改变状态,不创建 Task 任务 + + opt 追加数量 + Worker->>Page: 追加数量 + Page->>Controller: appendQuantity + Controller->>Service: appendQuantity + Service->>Mapper: 增加 append_qty + Service->>Mapper: 已完成作业重新改为进行中 + end + + opt 取消或恢复 + Worker->>Page: 取消/恢复订单、备货或套管 + Page->>Controller: cancelXxx / restoreXxx + Controller->>Service: 校验状态和乐观锁版本 + Service->>Mapper: 更新状态并记录原因 + end +``` + +关键规则: + +- 开始订单、开始备货、开始套管都不会直接下发任务。 +- 订单取消会阻止新任务领取;取消之前已合法创建的任务仍可完成并回写实际数量。 +- 追加数量作用于整个日计划,所以已完成的备货、套管都会重新进入进行中,不需要在作业页分别追加。 +- 所有页面操作都携带 `version`,防止页面操作相互覆盖。 + +## 三、备货定时调度时序 + +```mermaid +sequenceDiagram + autonumber + participant XXL as XXL-JOB
dailyPlanStockingJob + participant Dispatch as CoreTubeTaskDispatchServiceImpl + participant Schedule as DailyPlanScheduleServiceImpl + participant CoreDB as CoreTubeMapper + participant PointDB as StockingIvtMapper + participant Task as Task模块 + + XXL->>Dispatch: dispatchStockingOnce() + Dispatch->>Schedule: previewStockingCandidates() + Schedule-->>Dispatch: 按顺序/权重排列的候选 + + loop 每种物料规格只检查一次 + Dispatch->>CoreDB: 查询对接位可用目标管芯 + alt 对接位存在目标管芯 + Dispatch->>Schedule: claimStockingCandidate(日计划ID) + Schedule-->>Dispatch: 单根Claim + Dispatch->>CoreDB: 原子预占一根管芯 + Dispatch->>Task: 创建CORE_TUBE_STOCKING_PICK + Task-->>Dispatch: taskId + Dispatch->>CoreDB: 管芯绑定taskId + Dispatch->>Schedule: confirmTaskCreated(claimToken) + Note over Schedule: 只有单根任务创建成功才推进权重 + Dispatch-->>XXL: 本轮结束,只创建一条任务 + else 当前规格不能直接抓取 + Note over Dispatch: 跳到下一规格,不提前消耗权重 + end + end + + alt 所有规格都不能直接抓取且对接位有托盘 + Dispatch->>PointDB: 查询空缓存位 + Dispatch->>Task: 创建CORE_TUBE_PALLET_OUT + Note over Dispatch: 本轮只移出一托盘,不创建抓取任务 + else 对接位为空 + Dispatch->>PointDB: 为候选规格选择缓存位托盘 + Note over PointDB: 优先选择可满足剩余量的最小托盘
否则选择库存最多托盘 + Dispatch->>Task: 创建CORE_TUBE_PALLET_IN + Note over Dispatch: 同规格未完成托盘任务使用业务键防重 + else 无可用托盘 + Dispatch-->>XXL: 记录备货区无可用管芯并结束 + end +``` + +备货数量何时增加: + +- 托盘移入或移出完成:只更新托盘点位和整托盘管芯位置,`stocked_qty` 不增加。 +- 桁架成功抓取一根管芯并送入管芯库:`stocked_qty + 1`。 +- 每轮调度每个租户最多创建一条现场任务。 + +## 四、套管定时调度时序 + +```mermaid +sequenceDiagram + autonumber + participant XXL as XXL-JOB
dailyPlanSleevingJob + participant Dispatch as CoreTubeTaskDispatchServiceImpl + participant Schedule as DailyPlanScheduleServiceImpl + participant CoreDB as CoreTubeMapper + participant Task as Task模块 + + XXL->>Dispatch: dispatchSleevingOnce() + Dispatch->>Schedule: previewSleevingCandidates() + Schedule-->>Dispatch: 按套管策略排列的候选 + + loop 每种物料规格只检查一次 + Dispatch->>CoreDB: 查询管芯库一根可用目标管芯 + alt 管芯存在 + Dispatch->>Schedule: claimSleevingCandidate(日计划ID) + Schedule-->>Dispatch: 单根Claim + Dispatch->>CoreDB: 原子预占管芯 + Dispatch->>Task: 创建CORE_TUBE_SLEEVING_OUT + Task-->>Dispatch: taskId + Dispatch->>CoreDB: 管芯绑定taskId + Dispatch->>Schedule: confirmTaskCreated(claimToken) + Dispatch-->>XXL: 本轮结束,只创建一根 + else 管芯库没有目标管芯 + Dispatch->>Task: 查询该物料的未完成备货任务 + alt 存在托盘移入或备货抓取任务 + Dispatch-->>XXL: 记录“正在备货”,继续下一规格 + else 不存在备货任务 + Dispatch-->>XXL: 记录“备货区库存不足”,继续下一规格 + end + end + end +``` + +套管数量只在单根管芯出库任务完成后增加。套管策略和备货策略分别存储,因此可以一边使用顺序模式、一边使用权重模式。 + +## 五、任务完成与取消回调时序 + +```mermaid +sequenceDiagram + autonumber + participant ACS as AGV/桁架/套管设备 + participant Task as Task模块 + participant Handler as CoreTubeStockingTask
CoreTubeSleevingTask + participant Dispatch as CoreTubeTaskDispatchServiceImpl + participant CoreDB as lms_core_tube + participant Plan as DailyPlanScheduleServiceImpl + + ACS->>Task: 上报任务完成或取消 + Task->>Handler: 按handleCode调用处理器 + + alt 托盘移入/移出完成 + Handler->>Dispatch: handleFinished(taskId, false) + Dispatch->>CoreDB: 原子迁移源/目标点位 + Dispatch->>CoreDB: 更新整托盘管芯当前位置 + Note over Plan: 不更新日计划完成数量 + else 单根备货抓取完成 + Handler->>Dispatch: handleFinished(taskId, false) + Dispatch->>CoreDB: 管芯进入管芯库并清除托盘格位 + Dispatch->>Plan: increaseStockedQuantity(..., 1) + Plan->>Plan: 确认Claim并写进度日志 + else 单根套管出库完成 + Handler->>Dispatch: handleFinished(taskId, true) + Dispatch->>CoreDB: 管芯进入套管设备阶段 + Dispatch->>Plan: increaseSleevedQuantity(..., 1) + Plan->>Plan: 确认Claim并写进度日志 + else 单根任务取消 + Handler->>Dispatch: handleCancelled(taskId, ...) + Dispatch->>CoreDB: 管芯恢复原阶段和可用状态 + Dispatch->>Plan: releaseClaim(claimToken) + end + + Note over Dispatch,Plan: 更新语句绑定taskId或claimToken
重复完成、重复取消不会重复累计 +``` + +## 六、推荐代码阅读顺序 + +### 第一步:看页面能做什么 + +- `DailyPlanController`:所有日计划管理和作业接口入口。 +- `DailyPlanService`:人工操作能力清单。 +- `DailyPlanServiceImpl`:订单、备货、套管的状态转换和追加数量逻辑。 + +先重点阅读这些方法: + +1. `startOrder` +2. `appendQuantity` +3. `startStocking` / `startSleeving` +4. `cancelOrder` / `restoreOrder` / `finishOrder` +5. `updateSort` / `updateWeight` / `updateStrategy` + +### 第二步:看定时器入口 + +- `DailyPlanCoreTubeJob.dailyPlanStockingJob` +- `DailyPlanCoreTubeJob.dailyPlanSleevingJob` + +这两个方法本身很薄,只负责按租户触发调度。核心判断都在 `CoreTubeTaskDispatchServiceImpl`。 + +### 第三步:看备货和套管如何选任务 + +- `CoreTubeTaskDispatchServiceImpl.dispatchStockingOnce`:对接位优先、托盘移出/移入及规格跳过。 +- `CoreTubeTaskDispatchServiceImpl.dispatchSleevingOnce`:管芯库单根出库和缺货日志。 +- `CoreTubeTaskDispatchServiceImpl.createSingleTubeTask`:Claim、管芯预占、Task 创建及权重确认的事务边界。 +- `CoreTubeTaskDispatchServiceImpl.createPalletTask`:一次只创建一条托盘任务的决策。 + +### 第四步:看顺序、权重和并发控制 + +- `DailyPlanScheduleServiceImpl.previewCandidates`:只排列候选,不分配库存、不推进权重。 +- `DailyPlanScheduleServiceImpl.claimCandidate`:为一根现场任务创建排他 Claim。 +- `DailyPlanScheduleServiceImpl.confirmTaskCreated`:任务真正创建成功后才推进权重。 +- `DailyPlanScheduleServiceImpl.increaseQuantity`:任务完成后的幂等进度确认。 +- `DailyPlanStrategyInitializer`:为新租户并发安全地初始化默认顺序策略。 + +### 第五步:看任务完成后发生什么 + +- `CoreTubeStockingTask`:托盘和备货抓取任务回调入口。 +- `CoreTubeSleevingTask`:套管出库任务回调入口。 +- `CoreTubeTaskDispatchServiceImpl.handleFinished`:完成后的库存位置和日计划数量更新。 +- `CoreTubeTaskDispatchServiceImpl.handleCancelled`:取消后的管芯与 Claim 恢复。 + +### 第六步:最后看 SQL 原子条件 + +- `DailyPlanMapper.xml`:候选条件、状态转换、已备货/已套管数量原子累加。 +- `DailyPlanClaimMapper.xml`:Claim 活动、确认、释放和过期条件。 +- `CoreTubeMapper.xml`:管芯预占、绑定任务、完成和取消。 +- `StockingIvtMapper.xml`:对接位、缓存位、托盘选择和托盘点位迁移。 + +## 七、最重要的四个业务边界 + +1. 页面“开始备货/开始套管”只改变状态,真正任务由 XXL-JOB 创建。 +2. 候选预览不等于库存分配;只有创建单根任务成功后才消耗权重。 +3. 托盘 AGV 任务不增加日计划进度,单根管芯任务完成才增加一根。 +4. 备货和套管有独立状态、策略、Claim 和进度,同一日计划上可以并行执行。