# ND3 阶段性产品报表 — 前端对接说明 ## 一、基础约定 | 项 | 说明 | |----|------| | 服务地址 | **本系统(若依)** `http://{host}:8033`,`context-path: /` | | 统一响应 | `{ code, msg, data }`,`code === 200` 为成功 | | 鉴权 | 须登录;请求头 `Authorization: Bearer {token}` | | 模块前缀 | `/system/nd3/phased-product` | > **勿用** `http://xxx:8081/api/login`:那是配置里的 **PLM 外部接口** 地址,不是本后端登录;字段也不是 `UserName`/`Password`。 --- ## 〇、登录(调 ND3 接口前必做) ### 0.1 验证码(若后台开启) ``` GET http://{host}:8033/captchaImage ``` `data.captchaEnabled === true` 时,记下 `data.uuid`,按图片算出 `code`(数学验证码为算式结果)。 ### 0.2 登录 **POST** `/login`(无 `/api` 前缀) **Body(JSON,小写字段名)** ```json { "username": "admin", "password": "admin123", "code": "8", "uuid": "从 captchaImage 返回的 uuid" } ``` 验证码关闭时 `code`、`uuid` 可省略。 **成功示例** ```json { "code": 200, "msg": "操作成功", "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } } ``` 后续 ND3 请求头: ``` Authorization: Bearer {data.token} ``` **Apifox 正确示例** ``` POST http://192.168.31.195:8033/login Content-Type: application/json {"username":"叮叮","password":"123456","code":"","uuid":""} ``` (用户名须为系统 `sys_user` 里的 **user_name**,不是昵称;密码与库中一致。) --- ## 二、接口列表 ### 1. 检索 ND 项目(选令号 / 切换项目) **GET** `/system/nd3/phased-product/search` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | keyword | string | 是 | 物料编码、BOM 父项或 ND3 生产令号关键字 | **示例** ``` GET http://localhost:8033/system/nd3/phased-product/search?keyword=LTBZE ``` **data 结构** ```ts interface Nd3PhasedProductProjectVo { productionOrderNo: string; // 生产令号,切换项目用 productCode: string; // 默认主产品图号,可传给 report productName: string; } ``` --- ### 2. 报表(页面主数据) **GET** `/system/nd3/phased-product/report` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | productionOrderNo | string | 否* | ND3 生产令号;有令号时发货/在途可按令号过滤 | | materialCode | string | 否* | 主产品物料编码;只填此项可查金蝶 BOM + 库存/在途 | | inputQty | number | 否 | 计划投产量;大于 0 时返回 deployRows | \* `productionOrderNo` 与 `materialCode` **至少填一项**(二选一或都填)。 **示例** ``` # 只填物料号(不必填令号) GET .../report?materialCode=LTBZE/L.01.0-MP # 按令号查(可再指定主产品) GET .../report?productionOrderNo=ND3-26-009-LT GET .../report?productionOrderNo=ND3-26-009-LT&materialCode=KP14E(B)-45C-180B-42T-R # 带投产量试算 GET .../report?materialCode=LTBZE/L.01.0-MP&inputQty=10 ``` **data 结构** ```ts interface Nd3PhasedProductReportVo { productionOrderNo: string; bomHeader: Nd3BomHeaderVo; mainProduct: Nd3MainProductVo; subItems: { selfMade: Nd3SubMaterialRowVo[]; purchase: Nd3SubMaterialRowVo[] }; deployRows: Nd3DeployRowVo[]; // 仅传 inputQty 时有数据 } interface Nd3SubMaterialRowVo { materialCode: string; materialName: string; materialType: string; // 自制 | 外购 requiredQty: number; // 单台用量 stockQty: number; noPickedQty: number; transitMoQty: number; transitPoQty: number; expectedAvailableQty: number; // 库存 + 在途 − 未领料 transitMoRows: Nd3TransitMoRowVo[]; // productionOrderNo / sclh, planFinishDate transitPoRows: Nd3TransitPoRowVo[]; // productionOrderNo / projectOrderNo, deliveryDate(到货日期) } interface Nd3MainProductVo { productCode: string; productName: string; stockQty: number; deliverQty: number; transitQty: number; // 在途合计 stockDrillRows: Nd3QuantityDrillRowVo[]; deliverDrillRows: Nd3QuantityDrillRowVo[]; transitDrillRows: Nd3QuantityDrillRowVo[]; transitMoRows: Nd3TransitMoRowVo[]; } interface Nd3DeployRowVo { materialCode: string; materialName: string; needQty: number; // 单台用量 × inputQty remainDeployQty: number; // max(0, 需投 − 可用) } ``` --- ## 三、页面流程(建议) ``` 1. 产品检索框 [keyword] → 调 /search → 列表展示(可能有令号,也可能只有 productCode) 2. 用户选中一条 → 记录 productCode;有 productionOrderNo 则一并带上 3. 调 /report:**至少传 materialCode 或 productionOrderNo**(只搜到 BOM 时只传 materialCode 即可) 4. 用户切换项目 → 有令号则改 productionOrderNo 重查;无令号则改 materialCode 重查 5. 用户改投产量 → 带上 inputQty 再调 /report → 展示 deployRows ``` --- ## 四、界面布局建议 ### 4.1 顶部筛选区 | 控件 | 绑定 | 行为 | |------|------|------| | 项目产品检索 | keyword | 失焦/搜索按钮 → `/search` | | 当前生产令号 | productionOrderNo | 来自 search 选中项,只读或可下拉切换 | | 主产品图号 | materialCode | 可选;默认用 search 返回的 productCode 作为 materialCode | | 投产量 | inputQty | 数字输入;变更后重新 `/report` | ### 4.2 主产品卡片 展示 `data.mainProduct`: | 列名 | 字段 | 交互 | |------|------|------| | 主产品编码 | productCode | 文本 | | 主产品名称 | productName | 文本 | | 库存数量 | stockQty | 可点击 → 弹窗/展开 `stockDrillRows` | | 发货数量 | deliverQty | 可点击 → `deliverDrillRows` | | 在途数量 | transitQty | 可点击 → `transitDrillRows` / `transitMoRows` | 下钻表列:`sclh` | `orderNo` | `qty` | `planStartDate` | `planFinishDate` | `instockQty` | `notInstockQty` ### 4.3 BOM 子项表(主体) 数据源:`data.subItems.selfMade` + `data.subItems.purchase` | 列名 | 字段 | 说明 | |------|------|------| | 物料编码 | materialCode | | | 物料名称 | materialName | | | 类型 | materialType | 自制 / 外购 | | 单台用量 | requiredQty | | | 库存 | stockQty | | | 未领料 | noPickedQty | | | 在途(MO) | transitMoQty | | | 在途(PO) | transitPoQty | | | 预计可用 | expectedAvailableQty | 库存 + 在途 − 未领料 | | 操作 | — | MO → `transitMoRows`,PO → `transitPoRows` | **采购在途明细弹窗**(数据源:`row.transitPoRows`,不要用 MO 的 `sclh` / `planFinishDate` 列名) | 列名 | 字段 | 说明 | |------|------|------| | 采购单号 | billNo | | | 生产令号 | **productionOrderNo** 或 projectOrderNo | 金蝶 F_UCHN_Text2 | | 到货日期 | **deliveryDate** | 金蝶 FDeliveryDate,展示时建议 `slice(0,10)` | | 订单日期 | orderDate | | | 订单数量 | orderQty | | | 剩余未入库 | remainStockInQty | | **生产在途明细弹窗**(数据源:`row.transitMoRows`) | 列名 | 字段 | |------|------| | 生产单号 | billNo | | 生产令号 | **productionOrderNo** 或 sclh | | 计划完工 | planFinishDate | | 未入库数量 | notInstockQty | **在途扁平列表**(`row.transitDrillRows`,含 MO+PO 混合):按 `sourceType` 分列——`采购在途` 用 `productionOrderNo` + `deliveryDate`;`生产在途` 用 `productionOrderNo` + `planFinishDate`。 ### 4.4 投产量区(可选) 当 `inputQty > 0` 且重新请求后,展示 `data.deployRows`: | 列名 | 字段 | |------|------| | 物料编码 | materialCode | | 物料名称 | materialName | | 需投数量 | needQty | | 剩余投放 | remainDeployQty | max(0, 需投 − 可用) | --- ## 五、前端注意点(联调必读) 1. **不必填令号**:只传 `materialCode` 即可查 BOM 及指标。 2. **有令号时**:传 `productionOrderNo` 可把发货/在途按该令号收窄。 3. **在途下钻**:MO/PO 明细中可能出现其它令号(QB 等),勿假设全部等于当前令号。 4. **deployRows**:未传 `inputQty` 时恒为 `[]`。 5. **图号特殊字符**:`materialCode` 含 `/`、`()` 等须 URL 编码。 --- ## 六、错误处理 | code / msg | 处理 | |------------|------| | 非 200 | 展示 msg | | `请输入物料编码或生产令号` | search 未填 keyword | | `请填写物料编码或生产令号` | report 两个参数都未填 | | 401 | 重新登录拿 Token |