# LMS 日计划管理实现计划 > **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。 **目标:** 在 LMS 中实现 ERP/人工日计划、独立的查询维护与作业页面、订单/备货/套管状态机、顺序与权重策略,以及供后续定时器调用的调度查询和进度更新能力。 **架构:** 后端按 `dailyplan` 业务包组织,日计划、策略、操作日志分别映射独立表并使用 Mapper XML。管理端接口、ERP 推送接口和内部调度能力共用 `DailyPlanService` 状态机,所有状态及数量变更使用事务和版本号。前端使用两个同级动态菜单页面,共用同一 API 类型和详情组件。 **技术栈:** Java 17、Spring Boot、Spring Security、MyBatis/MyBatis-Plus 分页、MySQL、EasyTrans、Vue 3、TypeScript、Vben Admin、Ant Design Vue Next、VXE Table。 --- ## 文件结构 ### 数据库与公共常量 - 创建 `sql/mysql/lms_daily_plan.sql`:三张业务表、编码规则、字典和初始策略。 - 创建 `sql/mysql/lms_daily_plan_menu.sql`:两个菜单及按钮权限。 - 创建 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanSourceTypeEnum.java`:来源枚举。 - 创建 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanOrderStatusEnum.java`:订单状态枚举。 - 创建 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanWorkStatusEnum.java`:备货/套管状态枚举。 - 创建 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyModeEnum.java`:策略模式枚举。 - 创建 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyTypeEnum.java`:策略业务类型枚举。 - 修改 `nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java`:日计划业务错误码。 ### 后端 - 创建 `nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanDO.java`:主表映射。 - 创建 `.../dailyplan/DailyPlanStrategyDO.java`:策略表映射。 - 创建 `.../dailyplan/DailyPlanOperationLogDO.java`:操作日志表映射。 - 创建 `.../dal/mysql/dailyplan/DailyPlanMapper.java` 和 `src/main/resources/mapper/dailyplan/DailyPlanMapper.xml`:主表查询和原子更新。 - 创建 `.../dal/mysql/dailyplan/DailyPlanStrategyMapper.java` 和对应 XML:策略查询、切换及游标更新。 - 创建 `.../dal/mysql/dailyplan/DailyPlanOperationLogMapper.java` 和对应 XML:日志追加与分页查询。 - 创建 `.../controller/admin/dailyplan/vo/*.java`:管理、作业和操作请求/响应 VO。 - 创建 `.../controller/erp/dailyplan/vo/ErpDailyPlanPushReqVO.java`:ERP 推送请求。 - 创建 `.../service/dailyplan/DailyPlanService.java`、`DailyPlanServiceImpl.java`:状态机和事务。 - 创建 `.../service/dailyplan/DailyPlanScheduleService.java`、`DailyPlanScheduleServiceImpl.java`:定时器候选和进度更新。 - 创建 `.../controller/admin/dailyplan/DailyPlanController.java`:管理与作业接口。 - 创建 `.../controller/erp/dailyplan/ErpDailyPlanController.java`:ERP 推送接口。 - 修改 `.../framwork/security/config/SecurityConfiguration.java`:放行 ERP 路径,由控制器校验独立令牌。 - 修改 `.../framwork/rpc/config/RpcConfiguration.java`:注册 `CodeGenApi`。 - 修改 `nl-module-lms/nl-module-lms-server/src/main/resources/application-*.yaml`:仅增加配置键引用;实际令牌由 Nacos 环境配置。 ### 前端 - 创建 `nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/lms/dailyplan/index.ts`:API 类型和请求。 - 创建 `.../src/views/lms/dailyplan/index.vue`、`data.ts`:日计划管理页。 - 创建 `.../src/views/lms/dailyplan/modules/form.vue`:人工新增/编辑抽屉。 - 创建 `.../src/views/lms/dailyplan/modules/start-order.vue`:开始订单弹窗。 - 创建 `.../src/views/lms/dailyplan/modules/detail.vue`:共享详情与操作日志抽屉。 - 创建 `.../src/views/lms/dailyplanwork/index.vue`、`data.ts`:日计划作业页。 - 创建 `.../src/views/lms/dailyplanwork/modules/operation.vue`:追加、取消、恢复等操作弹窗。 - 创建 `.../src/views/lms/dailyplanwork/modules/strategy.vue`:策略切换弹窗。 - 创建 `.../src/views/lms/dailyplanwork/modules/sort.vue`:批量顺序调整弹窗。 - 修改 `nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/packages/constants/src/dict-enum.ts`:字典编码。 ## 任务 1:建立数据库、字典、编码规则和菜单 - [ ] **步骤 1:创建业务表脚本** 在 `sql/mysql/lms_daily_plan.sql` 创建: ```sql CREATE TABLE lms_daily_plan ( daily_plan_id BIGINT NOT NULL COMMENT '日计划标识', plan_code VARCHAR(32) NOT NULL COMMENT '日计划编号', source_type TINYINT NOT NULL COMMENT '来源类型:1 ERP,2 人工', erp_order_code VARCHAR(64) NULL COMMENT 'ERP订单号', manual_order_code VARCHAR(64) NULL COMMENT '人工订单号', plan_date DATE NOT NULL COMMENT '计划日期', material_id BIGINT NOT NULL COMMENT '管芯物料标识', material_code VARCHAR(64) NOT NULL COMMENT '管芯物料编码', material_name VARCHAR(128) NOT NULL COMMENT '管芯物料名称', material_spec VARCHAR(128) NULL COMMENT '管芯规格', plan_qty INT NOT NULL COMMENT '计划数量', append_qty INT NOT NULL DEFAULT 0 COMMENT '追加数量', stocked_qty INT NOT NULL DEFAULT 0 COMMENT '已备货数量', sleeved_qty INT NOT NULL DEFAULT 0 COMMENT '已套管数量', packing_info TEXT NULL COMMENT '装箱信息', sort_seq INT NOT NULL COMMENT '顺序号', weight INT NOT NULL DEFAULT 1 COMMENT '权重', order_status TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态', stocking_status TINYINT NOT NULL DEFAULT 0 COMMENT '备货状态', sleeving_status TINYINT NOT NULL DEFAULT 0 COMMENT '套管状态', previous_order_status TINYINT NULL COMMENT '取消前订单状态', previous_stocking_status TINYINT NULL COMMENT '取消前备货状态', previous_sleeving_status TINYINT NULL COMMENT '取消前套管状态', order_start_time DATETIME NULL, order_end_time DATETIME NULL, stocking_start_time DATETIME NULL, stocking_complete_time DATETIME NULL, sleeving_start_time DATETIME NULL, sleeving_complete_time DATETIME NULL, version INT NOT NULL DEFAULT 0 COMMENT '版本号', creator VARCHAR(64) NULL, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updater VARCHAR(64) NULL, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted BIT(1) NOT NULL DEFAULT b'0', tenant_id BIGINT NOT NULL DEFAULT 0, PRIMARY KEY (daily_plan_id), UNIQUE KEY uk_lms_daily_plan_code (plan_code, tenant_id), UNIQUE KEY uk_lms_daily_plan_erp_order (erp_order_code, tenant_id) ) COMMENT='LMS日计划'; ``` 同一脚本创建 `lms_daily_plan_strategy` 和 `lms_daily_plan_operation_log`。策略表以 `(strategy_type, tenant_id)` 唯一,包含 `strategy_mode`、`cursor_daily_plan_id`、`version` 和审计字段;日志表包含操作对象、操作类型、前值、后值、数量变化、原因和审计字段。 - [ ] **步骤 2:初始化编码规则和字典** 幂等写入编码规则 `LMS_DAILY_PLAN_CODE`,段配置生成 `DPyyyyMMdd0001`。幂等写入以下字典: ```text lms_daily_plan_source_type: 1 ERP, 2 人工 lms_daily_plan_order_status: 0 未开始, 1 进行中, 2 已结束, 3 已取消 lms_daily_plan_work_status: 0 未开始, 1 进行中, 2 已完成, 3 已取消 lms_daily_plan_strategy_mode: 1 顺序模式, 2 权重轮转 ``` 为每个现有租户幂等初始化备货、套管两条顺序模式策略。 - [ ] **步骤 3:创建菜单权限脚本** 在 `sql/mysql/lms_daily_plan_menu.sql` 下将两个 type=2 菜单挂到 `tube-library`: ```text 日计划管理 -> lms/dailyplan/index 日计划作业 -> lms/dailyplanwork/index ``` 创建权限: ```text lms:daily-plan:query lms:daily-plan:create lms:daily-plan:update lms:daily-plan:start lms:daily-plan:operate lms:daily-plan:schedule lms:daily-plan:strategy ``` 脚本按路径、组件和权限编码幂等,并为已授权子菜单的角色补齐“管芯库管理”父目录权限。 - [ ] **步骤 4:验证 SQL** 运行: ```bash MYSQL_PWD=root /usr/local/mysql/bin/mysql --protocol=TCP -h 127.0.0.1 -P 3306 -u root -D huachuang_lms_dev -e "SOURCE sql/mysql/lms_daily_plan.sql; SOURCE sql/mysql/lms_daily_plan_menu.sql;" ``` 连续执行两次,预期无重复键错误;查询三张表、字典、编码规则和菜单,预期每项只有一份有效数据。 - [ ] **步骤 5:提交数据库基线** ```bash git add sql/mysql/lms_daily_plan.sql sql/mysql/lms_daily_plan_menu.sql git commit -m "feat: 初始化LMS日计划数据结构" ``` ## 任务 2:建立枚举、数据对象和错误码 - [ ] **步骤 1:创建五个业务枚举** 枚举使用 `Integer code` 和 `getByCode`。状态码严格使用任务 1 的字典值。例如: ```java public enum DailyPlanOrderStatusEnum { NOT_STARTED(0), IN_PROGRESS(1), FINISHED(2), CANCELED(3); private final Integer code; public static DailyPlanOrderStatusEnum getByCode(Integer code) { for (DailyPlanOrderStatusEnum value : values()) { if (value.code.equals(code)) { return value; } } return null; } } ``` - [ ] **步骤 2:创建三个 DO** `DailyPlanDO` 继承 `TenantBaseDO`(若 LMS 当前公共基类只支持 `BaseDO`,则显式增加 `tenantId`),字段与 DDL 一一对应;主键使用 `@TableId`。策略和日志 DO 同样只表达表结构,不加入业务方法。 - [ ] **步骤 3:增加错误码** 在 `ErrorCodeConstants` 增加:日计划不存在、ERP 订单重复/终态不可更新、ERP 数量减少、非法状态流转、数量超限、版本冲突、策略不存在、顺序或权重非法、取消/恢复原因缺失、ERP 令牌错误。 - [ ] **步骤 4:编译 API 和 Server** ```bash ./mvnw -pl nl-module-lms/nl-module-lms-server -am -DskipTests compile ``` 预期 `BUILD SUCCESS`。 - [ ] **步骤 5:提交基础模型** ```bash git add nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums \ nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan git commit -m "feat: 增加LMS日计划领域模型" ``` ## 任务 3:实现 Mapper XML 与并发更新 - [ ] **步骤 1:实现日计划查询** `DailyPlanMapper` 提供: ```java PageResult selectManagementPage(DailyPlanPageReqVO reqVO); PageResult selectWorkPage(DailyPlanWorkPageReqVO reqVO); DailyPlanDO selectById(Long dailyPlanId); DailyPlanDO selectByErpOrderCode(String erpOrderCode); List selectStockingCandidates(); List selectSleevingCandidates(); ``` 所有查询写入 `DailyPlanMapper.xml`。管理分页默认 `plan_date DESC, sort_seq ASC, daily_plan_id DESC`;作业分页限定进行中或指定的已取消页签,不限制日期,按 `sort_seq ASC, daily_plan_id ASC`。 - [ ] **步骤 2:实现受控写入** XML 提供 `insertDailyPlan`、`updateNotStartedPlan`、`updateStateWithVersion`、`updateSortWithVersion`、`updateWeightWithVersion` 和两个基于 Claim 的原子进度方法。页面写操作使用日计划版本;调度进度以 Claim 令牌及领取时对应作业进度作为并发边界: ```sql UPDATE lms_daily_plan SET stocked_qty = stocked_qty + #{incrementQty}, stocking_status = CASE WHEN stocking_status = 1 AND stocked_qty + #{incrementQty} = plan_qty + append_qty THEN 2 ELSE stocking_status END, version = version + 1, updater = #{updater} WHERE daily_plan_id = #{dailyPlanId} AND stocked_qty = #{claimProgressQty} AND stocked_qty + #{incrementQty} <= plan_qty + append_qty ``` 套管方法使用独立的 `sleeved_qty` 快照约束。排序、权重、ERP 追加和另一作业进度引起的日计划版本变化不影响确认。取消或结束只阻止新领取,已有有效 Claim 仍允许累计数量,且 SQL 不覆盖用户选择的取消或结束状态。受影响行数不是 1 时由 Service 区分进度冲突或数量超限。 - [ ] **步骤 3:实现策略与日志 Mapper** 策略 XML 提供按业务类型查询、版本切换模式、版本更新游标。日志 XML 提供插入和按日计划 ID、操作时间倒序查询。 - [ ] **步骤 4:编译检查 Mapper 签名** 运行 Maven compile,预期 Mapper XML 可解析且无 `Invalid bound statement` 的构建期问题。 - [ ] **步骤 5:提交持久层** ```bash git add nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/dailyplan \ nl-module-lms/nl-module-lms-server/src/main/resources/mapper/dailyplan git commit -m "feat: 实现LMS日计划持久层" ``` ## 任务 4:实现请求响应模型和日计划状态机 - [ ] **步骤 1:创建查询和响应 VO** 创建管理分页、作业分页、详情、操作日志和策略响应。`DailyPlanRespVO` 实现 EasyTrans `VO`,`dailyPlanId` 标注 `@TableId`,修改人按现有备货区域模式翻译为 `updaterName`。 - [ ] **步骤 2:创建写入请求 VO** 创建人工新增、更新、开始订单、追加数量、原因操作、批量顺序、权重、策略切换请求。使用 `@NotNull`、`@NotBlank`、`@Positive`、`@Size` 完成参数校验;所有修改请求携带 `version`。 - [ ] **步骤 3:实现人工创建与编辑** `DailyPlanServiceImpl#createManualPlan` 调用 `CodeGenApi.generate` 生成 `LMS_DAILY_PLAN_CODE`。RPC 返回失败必须抛业务异常。初始三个状态为未开始,数量进度为零,权重默认 1。 编辑方法只接受人工来源且订单未开始的计划,并通过版本更新防止覆盖。 - [ ] **步骤 4:实现三条状态机** 为每个业务动作实现公开 Service 方法,不暴露通用状态修改: ```java void startOrder(DailyPlanStartReqVO reqVO); void appendQuantity(DailyPlanAppendReqVO reqVO); void startStocking(DailyPlanVersionReqVO reqVO); void cancelStocking(DailyPlanReasonReqVO reqVO); void restoreStocking(DailyPlanReasonReqVO reqVO); void startSleeving(DailyPlanVersionReqVO reqVO); void cancelSleeving(DailyPlanReasonReqVO reqVO); void restoreSleeving(DailyPlanReasonReqVO reqVO); void cancelOrder(DailyPlanReasonReqVO reqVO); void restoreOrder(DailyPlanReasonReqVO reqVO); void finishOrder(DailyPlanVersionReqVO reqVO); ``` 每个方法先校验当前状态,再构造新的更新对象;禁止直接修改查询得到的 DO。状态更新和操作日志使用同一 `@Transactional` 事务。 - [ ] **步骤 5:实现排序、权重和策略切换** 批量排序校验所有顺序为正整数且计划处于未结束状态,在一个事务内逐条版本更新;任一失败整体回滚。权重只允许正整数。策略切换分别更新备货或套管配置并清空轮转游标,立即影响下一轮调度。 - [ ] **步骤 6:编译并提交状态机** 运行 Maven compile,预期成功。提交 VO、Service 和 RPC 配置: ```bash git commit -m "feat: 实现LMS日计划状态流转" ``` ## 任务 5:实现 ERP 幂等推送与独立鉴权 - [ ] **步骤 1:定义 ERP 请求** `ErpDailyPlanPushReqVO` 包含 ERP 订单号、计划日期、物料 ID/编码/名称/规格、计划数量和装箱信息,数量使用 `@Positive`。 - [ ] **步骤 2:实现幂等推送** `pushErpDailyPlan` 使用 ERP 订单号查询: ```text 不存在 -> 新建 未开始 -> 覆盖 ERP 可维护字段 进行中且数量增加 -> 差额累计 append_qty 进行中且数量相同 -> 返回现有日计划编号 进行中且数量减少 -> 抛业务异常 已结束或已取消 -> 抛业务异常 ``` 创建、更新和日志在同一事务;唯一键冲突按幂等查询重新判定,不返回数据库异常文本。 - [ ] **步骤 3:实现令牌鉴权** 控制器接收 `X-ERP-Token`,使用: ```java @Value("${erp.daily-plan.token}") private String erpDailyPlanToken; ``` 令牌不匹配时抛出 ERP 令牌错误。`SecurityConfiguration` 只对 `/lms/daily-plan/erpPush` 放行登录鉴权,业务令牌仍为必填。配置文件不写真实令牌,只声明由 Nacos 提供的配置键。 - [ ] **步骤 4:实现 ERP Controller** 接口路径使用驼峰: ```text POST /lms/daily-plan/erpPush ``` 返回 LMS 日计划编号,重复推送返回相同编号。 - [ ] **步骤 5:编译并提交 ERP 接口** 运行 Maven compile,预期成功;提交请求、Controller、Service 与安全配置。 ## 任务 6:实现后续定时器使用的调度服务 - [ ] **步骤 1:定义调度返回对象** 创建 `DailyPlanScheduleCandidate`,包含日计划 ID、计划编号、物料信息、建议处理数量、版本号、策略模式、排他 Claim 令牌和租约过期时间。版本号仅供展示审计,不作为进度确认并发边界。 - [ ] **步骤 2:实现顺序模式选择** 备货或套管候选先按 `sort_seq ASC, daily_plan_id ASC` 查询。顺序模式只返回第一张可执行计划,建议数量为全部剩余数量。 - [ ] **步骤 3:实现权重轮转选择** 根据策略游标从有序候选列表定位下一张;建议数量为 `min(weight, remainingQty)`。先原子创建 Claim,成功后再以策略版本号更新游标到下一张计划,两者同事务提交。游标无效时从顺序第一张开始。 - [ ] **步骤 4:实现原子进度更新** 提供: ```java void increaseStockedQuantity(String claimToken, Long dailyPlanId, Integer quantity, String operator); void increaseSleevedQuantity(String claimToken, Long dailyPlanId, Integer quantity, String operator); ``` 确认先锁定并原子消费 Claim,再按 Claim 保存的对应作业进度快照更新数量并追加日志。备货、套管可独立并发;同一 Claim 重复确认幂等成功。更新到需求总量时,仅当该作业仍在进行中才同步写完成状态和完成时间;若用户已取消或结束则保留终态。另提供 Claim 续租、主动释放和过期回收能力。 - [ ] **步骤 5:编译并提交调度能力** 运行 Maven compile;提交 Schedule Service 和相关 DTO。 ## 任务 7:实现管理端 Controller 与前端 API - [ ] **步骤 1:实现管理端接口** `DailyPlanController` 使用 `/lms/daily-plan`,提供 `managementPage`、`workPage`、`get`、`operationLogList`、`create`、`update`、`startOrder`、`appendQuantity`、三组备货/套管/订单操作、`updateSort`、`updateWeight`、`getStrategies` 和 `updateStrategy`。查询响应增加 `@TransMethodResult`。 - [ ] **步骤 2:绑定权限** 按照菜单脚本权限编码给每个接口增加 `@PreAuthorize`,禁止仅靠前端隐藏按钮控制权限。 - [ ] **步骤 3:创建前端 API** `src/api/lms/dailyplan/index.ts` 定义 `DailyPlan`、`OperationLog`、`Strategy` 和所有请求类型;接口路径与 Controller 驼峰方法一致。 - [ ] **步骤 4:编译和类型检查** 运行 Maven compile;前端运行: ```bash pnpm --filter @vben/web-antdv-next typecheck ``` - [ ] **步骤 5:提交接口层** ```bash git commit -m "feat: 增加LMS日计划管理接口" ``` ## 任务 8:实现“日计划管理”页面 - [ ] **步骤 1:注册字典常量** 在 `dict-enum.ts` 增加四个 `LMS_DAILY_PLAN_*` 编码,页面统一使用 `getDictOptions` 和 `CellDict`。 - [ ] **步骤 2:实现查询与列表** `dailyplan/data.ts` 查询项包括计划/订单号、日期范围、管芯、来源和订单状态。列表展示计划、ERP/人工订单、日期、管芯、需求总量、两个完成进度、三个状态、来源、修改人和修改时间。 - [ ] **步骤 3:实现新增/编辑抽屉** 表单字段为计划日期、人工订单号、管芯、计划数量、装箱信息、顺序和权重。ERP 来源以及已开始计划不显示编辑入口。 - [ ] **步骤 4:实现开始订单和详情** 开始订单弹窗展示原计划量、确认计划量、已有追加、本次追加和开始后总量;确认计划量为必填正整数,ERP 与人工来源都可在开始时确认。服务端在同一事务内原子更新计划量、累计追加量和订单状态,并分别记录数量调整、追加和开始日志。管理页为未开始订单提供填写原因的取消入口。详情抽屉展示三类状态时间和按时间倒序的操作记录。 - [ ] **步骤 5:运行局部 ESLint** ```bash node node_modules/eslint/bin/eslint.js \ apps/web-antdv-next/src/api/lms/dailyplan/index.ts \ apps/web-antdv-next/src/views/lms/dailyplan ``` - [ ] **步骤 6:提交管理页面** ```bash git commit -m "feat: 增加LMS日计划管理页面" ``` ## 任务 9:实现“日计划作业”页面 - [ ] **步骤 1:实现进行中与已取消页签** 默认页签请求所有日期的进行中订单;已取消页签请求可恢复订单。列表始终显示顺序,展示管芯、需求总量、备货进度、套管进度和状态。 - [ ] **步骤 2:实现策略联动列** 页面加载备货和套管两条策略。考虑两类策略可能不同,列表提供“备货作业”和“套管作业”视图切换;当前视图为权重模式时显示权重列,否则隐藏权重列,但顺序列始终显示。 - [ ] **步骤 3:实现状态操作** 根据状态动态提供追加、开始/取消/恢复备货、开始/取消/恢复套管、取消/恢复/结束订单。取消和恢复要求原因,所有操作携带版本号,成功后刷新表格和策略。 - [ ] **步骤 4:实现批量顺序和权重维护** 顺序弹窗列出当前可作业计划并允许输入正整数;权重模式下允许内联修改权重。提交冲突时展示后端提示并重新加载。 - [ ] **步骤 5:实现策略切换** 备货、套管各自展示当前模式和修改时间。切换二次确认,说明“下一轮调度立即生效,已下发任务不撤销”。 - [ ] **步骤 6:运行类型检查和 ESLint** 对 API、两个页面及模块运行类型检查和局部 ESLint,预期无错误。 - [ ] **步骤 7:提交作业页面** ```bash git commit -m "feat: 增加LMS日计划作业页面" ``` ## 任务 10:执行端到端验证和收尾 - [ ] **步骤 1:完整后端编译** ```bash ./mvnw -pl nl-module-lms/nl-module-lms-server -am -DskipTests compile ``` 预期 `BUILD SUCCESS`。 - [ ] **步骤 2:完整前端检查** 运行目标应用 typecheck,并对所有日计划相关 TS/Vue 文件执行 ESLint,预期退出码 0。 - [ ] **步骤 3:执行 SQL 幂等验证** 在本地开发库连续执行两次初始化和菜单脚本,查询确认三张表、两条策略、四组字典、两个菜单及按钮权限无重复。 - [ ] **步骤 4:联调关键业务路径** 按顺序验证:ERP 首推 → 重推不变 → 未开始覆盖 → 开始订单 → ERP 增量追加 → 开始备货/套管 → 调度候选查询 → 原子更新进度 → 取消/恢复 → 结束订单。另验证 ERP 减量、终态推送、数量超限和旧版本更新均返回预期业务错误。 - [ ] **步骤 5:核对双页面边界** 确认管理页面可查全量但不提供现场作业按钮;作业页面不限制日期、默认只展示进行中,并通过已取消页签恢复订单;已结束订单不出现在作业页面。 - [ ] **步骤 6:核对策略行为** 使用 A(顺序 1、权重 2)、B(顺序 2、权重 3)、C(顺序 3、权重 1)验证权重候选为 A×2 → B×3 → C×1 循环;切到顺序模式后只返回顺序第一张未完成计划。 - [ ] **步骤 7:检查工作区并提交收尾** ```bash git diff --check git status --short ``` 只提交日计划相关文件,不包含用户已有的 `nl-module-wms/img.png` 或其他无关改动。