feat:子卷重量维护

This commit is contained in:
2026-08-19 10:31:10 +08:00
parent 3a74a3f598
commit f77503b798
10 changed files with 115 additions and 20 deletions

View File

@@ -0,0 +1,21 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>子卷重量维护 - PDA 原型</title>
<style>
:root{--orange:#ff6b00;--orange-deep:#ef5d00;--orange-soft:#fff1e7;--ink:#303744;--muted:#8992a2;--line:#e4e8ed;--bg:#f3f5f7;--green:#21a267;--red:#df3d4d}*{box-sizing:border-box}html,body{height:100%;margin:0;font:13px/1.5 "Microsoft YaHei","Segoe UI",sans-serif;color:var(--ink);background:#dfe3e7}button,input{font:inherit}.stage{height:100%;display:grid;place-items:center}.device{position:relative;width:360px;height:640px;overflow:hidden;display:flex;flex-direction:column;border-radius:17px;background:var(--bg);box-shadow:0 10px 30px rgba(20,28,40,.18)}.topbar{height:47px;flex:none;display:grid;grid-template-columns:46px 1fr 46px;align-items:center;background:var(--orange);color:#fff}.topbar h1{margin:0;text-align:center;font-size:14px;font-weight:500}.icon-btn{height:47px;border:0;background:transparent;color:#fff;font-size:21px;cursor:pointer}.content{flex:1;min-height:0;overflow:auto;padding:11px 14px 88px}.field{margin-bottom:9px}.field label{display:block;margin-bottom:4px;color:#7e8797;font-size:11px}.query-row{display:grid;grid-template-columns:1fr 66px;gap:8px}.control{width:100%;height:40px;padding:0 11px;border:1px solid #dfe4e9;border-radius:8px;outline:0;background:#fff;color:var(--ink)}.control:focus{border-color:var(--orange);box-shadow:0 0 0 2px rgba(255,107,0,.13)}.query-btn{border:0;border-radius:8px;background:var(--orange);color:#fff;cursor:pointer}.section-title{height:34px;display:flex;align-items:center;gap:7px;font-weight:700}.section-title:before{content:"";width:3px;height:17px;border-radius:2px;background:var(--orange)}.roll-card{padding:12px;border:1px solid var(--line);border-radius:11px;background:#fff}.card-top{display:flex;align-items:flex-start;justify-content:space-between;padding-bottom:10px;border-bottom:1px solid var(--line)}.card-top small,.info label{display:block;color:var(--muted);font-size:11px}.roll-no{font-size:17px;font-weight:500}.status-tag{padding:5px 9px;border-radius:14px;background:var(--orange-soft);color:var(--orange);font-size:11px}.info-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px 18px;padding:10px 0}.info span{font-size:12px}.weight-form{margin-top:2px;padding-top:11px;border-top:1px dashed #e1e5ea}.weight-heading{display:flex;justify-content:space-between;align-items:center;margin-bottom:9px}.weight-heading strong{font-size:12px}.weight-heading span{color:#9aa2af;font-size:10px}.weight-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}.weight-field label{display:block;margin-bottom:5px;color:#7d8796;font-size:11px}.unit-input{position:relative}.unit-input input{height:46px;padding:0 34px 0 10px;border-color:#ffad77;font-size:17px;font-weight:600}.unit-input span{position:absolute;right:10px;top:50%;color:#929baa;font-size:11px;transform:translateY(-50%)}.error{min-height:17px;margin:5px 0 0;color:var(--red);font-size:10px}.hint{margin:8px 0 0;text-align:center;color:#929aa9;font-size:11px}.empty{padding:58px 16px;text-align:center;border:1px dashed #d6dce3;border-radius:11px;background:#fff;color:#99a2af}.empty i{display:block;margin-bottom:7px;color:#f5a46b;font-size:28px;font-style:normal}.bottom{position:absolute;z-index:3;left:0;right:0;bottom:0;height:73px;padding:10px 14px;display:grid;grid-template-columns:88px 1fr;gap:8px;border-top:1px solid var(--line);background:#fff}.bottom button{height:46px;border-radius:8px;cursor:pointer}.clear{border:1px solid var(--orange);background:#fff;color:var(--orange)}.submit{border:0;background:var(--orange);color:#fff;font-weight:600}.submit:disabled{background:#ffc299;cursor:not-allowed}.mask{position:absolute;z-index:10;inset:0;display:grid;place-items:center;padding:27px;background:rgba(24,31,41,.43)}.mask.hidden{display:none}.dialog{width:100%;padding:18px;border-radius:12px;background:#fff}.dialog h3{margin:0 0 8px;font-size:15px}.dialog p{margin:0;color:#7e8795;line-height:1.7}.change-list{margin-top:11px;padding:9px 10px;border-radius:8px;background:#f7f8fa}.change-list div{display:flex;justify-content:space-between;margin:3px 0}.change-list b{font-weight:500;color:var(--orange)}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}.dialog-actions button{height:35px;padding:0 17px;border-radius:7px}.secondary{border:1px solid #ddd;background:#fff}.primary{border:0;background:var(--orange);color:#fff}.toast{position:absolute;z-index:20;top:56px;left:50%;padding:9px 13px;border-radius:8px;background:#fff;box-shadow:0 5px 18px rgba(0,0,0,.18);white-space:nowrap;opacity:0;transform:translate(-50%,-8px);transition:.2s}.toast.show{opacity:1;transform:translate(-50%,0)}.toast b{margin-right:5px;color:var(--green)}@media(max-width:380px){.device{width:100%;height:100%;border-radius:0}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}
</style>
</head>
<body>
<div class="stage"><main class="device"><header class="topbar"><button class="icon-btn" aria-label="返回"></button><h1>子卷重量维护</h1><button class="icon-btn" aria-label="首页"></button></header><section class="content"><div class="field"><label for="pointCode">点位码</label><div class="query-row"><input class="control" id="pointCode" value="DW-A03-08" placeholder="扫描或输入点位码" autocomplete="off"><button class="query-btn" id="queryBtn">查询</button></div></div><div class="section-title">子卷信息</div><div id="rollPanel"></div><p class="hint" id="hint">信息已加载,可修改重量后提交</p></section><footer class="bottom"><button class="clear" id="clearBtn">清空</button><button class="submit" id="submitBtn">确认提交</button></footer><div class="mask hidden" id="mask"><section class="dialog"><h3>确认修改重量?</h3><p id="dialogText"></p><div class="change-list"><div><span>子卷重量</span><b id="confirmRollWeight"></b></div><div><span>管芯重量</span><b id="confirmCoreWeight"></b></div></div><div class="dialog-actions"><button class="secondary" id="cancelBtn">取消</button><button class="primary" id="okBtn">确认提交</button></div></section></div><div class="toast" id="toast"><b></b><span id="toastText"></span></div></main></div>
<script>
const $=id=>document.getElementById(id);const records={"DW-A03-08":{roll:"ZJ-260814-03",erp:"ERP-20260814-0186",rack:"J-03-08",task:"RW-260814-0068",weight:"518.60",coreWeight:"12.40"},"DW-A03-09":{roll:"ZJ-260814-05",erp:"ERP-20260814-0192",rack:"J-03-09",task:"RW-260814-0071",weight:"506.25",coreWeight:"11.80"}};let current={point:"DW-A03-08",...records["DW-A03-08"]};
function render(){if(!current){$('rollPanel').innerHTML='<div class="empty"><i>▣</i>请扫描或输入点位码查询</div>';$('hint').textContent='等待查询点位信息';$('submitBtn').disabled=true;return}$('submitBtn').disabled=false;$('rollPanel').innerHTML=`<article class="roll-card"><div class="card-top"><div><small>子卷号</small><strong class="roll-no">${current.roll}</strong></div><span class="status-tag">已查询</span></div><div class="info-grid"><div class="info"><label>ERP 卷号</label><span>${current.erp}</span></div><div class="info"><label>架子号</label><span>${current.rack}</span></div><div class="info"><label>点位码</label><span>${current.point}</span></div><div class="info"><label>任务号</label><span>${current.task}</span></div></div><div class="weight-form"><div class="weight-heading"><strong>重量维护</strong><span>单位kg</span></div><div class="weight-grid"><div class="weight-field"><label for="rollWeight">子卷重量</label><div class="unit-input"><input class="control" id="rollWeight" type="number" min="0.01" step="0.01" inputmode="decimal" value="${current.weight}"><span>kg</span></div></div><div class="weight-field"><label for="coreWeight">管芯重量</label><div class="unit-input"><input class="control" id="coreWeight" type="number" min="0.01" step="0.01" inputmode="decimal" value="${current.coreWeight}"><span>kg</span></div></div></div><p class="error" id="weightError"></p></div></article>`;$('rollWeight').oninput=validate;$('coreWeight').oninput=validate;$('hint').textContent='信息已加载,可修改重量后提交'}
function validate(){if(!current)return false;const roll=Number($('rollWeight').value),core=Number($('coreWeight').value);let msg='';if(!roll||roll<=0||!core||core<=0)msg='请输入大于 0 的重量';else if(core>=roll)msg='管芯重量必须小于子卷重量';$('weightError').textContent=msg;$('submitBtn').disabled=!!msg;return !msg}
$('queryBtn').onclick=query;$('pointCode').onkeydown=e=>{if(e.key==='Enter')query()};function query(){const point=$('pointCode').value.trim().toUpperCase();if(!point)return showToast('请输入点位码');if(!records[point]){current=null;render();showToast('未查询到点位对应的子卷');return}current={point,...records[point]};render();showToast('子卷信息加载成功')}
$('clearBtn').onclick=()=>{current=null;$('pointCode').value='';render();$('pointCode').focus()};$('submitBtn').onclick=()=>{if(!validate())return;const roll=Number($('rollWeight').value).toFixed(2),core=Number($('coreWeight').value).toFixed(2);$('dialogText').textContent=`子卷 ${current.roll} 的重量将更新为:`;$('confirmRollWeight').textContent=`${roll} kg`;$('confirmCoreWeight').textContent=`${core} kg`;$('mask').classList.remove('hidden')};$('cancelBtn').onclick=()=>$('mask').classList.add('hidden');$('okBtn').onclick=()=>{current.weight=Number($('rollWeight').value).toFixed(2);current.coreWeight=Number($('coreWeight').value).toFixed(2);records[current.point]={...records[current.point],weight:current.weight,coreWeight:current.coreWeight};$('mask').classList.add('hidden');render();showToast('重量修改提交成功')};document.querySelectorAll('.icon-btn').forEach(btn=>btn.onclick=()=>showToast(btn.getAttribute('aria-label')+'为原型演示'));function showToast(text){$('toastText').textContent=text;$('toast').classList.add('show');setTimeout(()=>$('toast').classList.remove('show'),1800)}render();
</script>
</body>
</html>

View File

@@ -61,6 +61,7 @@ public interface ErrorCodeConstants {
ErrorCode POINT_EXECUTE_REFUGE = new ErrorCode(200008, "{}的点位不允许操作{}");
ErrorCode PACKAGE_POINT_UNQUALIFIED_EMPTY_NOT_EXISTS = new ErrorCode(200009, "没有可用的不合格空位");
ErrorCode PACKAGE_POINT_CHECK_FAILED_TASK_CREATE_FAILED = new ErrorCode(200010, "创建质检不合格AGV任务失败");
ErrorCode PACKAGE_SLITTING_PLAN_NOT_EXISTS = new ErrorCode(200011, "未查询到对应的子卷信息");
// ========== 子卷包装关系 ==========
ErrorCode SUB_PACKAGE_RELATION_NOT_EXISTS = new ErrorCode(300001, "子卷包装关系不存在");

View File

@@ -1,9 +1,10 @@
package cn.code.nl.module.lms.controller.pda;
package cn.code.nl.module.lms.controller.pda.boxpackage;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.module.lms.controller.pda.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.vo.QueryPackagePointInfoReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.QueryPackagePointInfoReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import cn.code.nl.module.lms.service.packagepoint.PackagePdaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -33,12 +34,6 @@ public class PackagePdaController {
@Resource
private PackagePdaService packagePdaService;
/**
* 根据点位编码查询装箱区点位信息
*
* @param manaQualityCheckPdaReqVO 查询参数
* @return 点位编码子卷号和载具号
*/
@PostMapping("/query-point-info")
@Operation(summary = "查询点位信息")
@PermitAll
@@ -48,8 +43,6 @@ public class PackagePdaController {
return success(packagePoint);
}
@PostMapping("/quality-check")
@Operation(summary = "人工质检")
@PermitAll
@@ -58,4 +51,12 @@ public class PackagePdaController {
return success("操作成功!");
}
@PostMapping("/update-weight")
@Operation(summary = "维护重量")
@PermitAll
public CommonResult<String> executeUpdateWeight(@Valid @RequestBody UpdateWeightPdaReqVO weightPdaReqVO) {
packagePdaService.executeUpdateWeight(weightPdaReqVO);
return success("操作成功!");
}
}

View File

@@ -1,4 +1,4 @@
package cn.code.nl.module.lms.controller.pda.vo;
package cn.code.nl.module.lms.controller.pda.boxpackage.vo;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

View File

@@ -1,4 +1,4 @@
package cn.code.nl.module.lms.controller.pda.vo;
package cn.code.nl.module.lms.controller.pda.boxpackage.vo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

View File

@@ -0,0 +1,27 @@
package cn.code.nl.module.lms.controller.pda.boxpackage.vo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
/**
*
* 重量维护
* @Author: liyongde
* @Date: 2026/8/19 9:36
*/
@Data
public class UpdateWeightPdaReqVO {
/** 点位编码 */
private String pointCode;
/** 子卷号 */
@NotEmpty(message = "子卷号不能为空")
private String containerName;
/** 子卷重量 */
private String rollWeight;
/** 管芯重量 */
private String tubeWeight;
}

View File

@@ -0,0 +1,6 @@
/**
*
* @Author: liyongde
* @Date: 2026/8/19 9:32
*/
package cn.code.nl.module.lms.controller.pda;

View File

@@ -1,7 +1,8 @@
package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.module.lms.controller.pda.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import jakarta.validation.Valid;
/**
@@ -24,4 +25,10 @@ public interface PackagePdaService {
* @param manaQualityCheckPdaReqVO
*/
void executeManualQualityCheck(@Valid ManaQualityCheckPdaReqVO manaQualityCheckPdaReqVO);
/**
* 维护重量
* @param weightPdaReqVO
*/
void executeUpdateWeight(@Valid UpdateWeightPdaReqVO weightPdaReqVO);
}

View File

@@ -2,8 +2,10 @@ package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.framework.common.exception.ServiceException;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.module.lms.controller.pda.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.vo.PackagePointPdaRespVO;
import cn.code.nl.framework.security.core.util.SecurityFrameworkUtils;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO;
import cn.code.nl.module.lms.dal.dataobject.slittingproductionplan.SlittingproductionplanDO;
import cn.code.nl.module.lms.dal.mysql.packagepoint.PackagePointMapper;
@@ -24,6 +26,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
@@ -44,7 +47,7 @@ public class PackagePdaServiceImpl implements PackagePdaService {
private static final String NO_TASK = "无任务";
/** 无重量信息 */
private static final String NO_WEIGHT_INFO = "无信息";
private static final String NO_WEIGHT_INFO = "0.0";
/** 未绑定子卷信息 */
private static final String UNBOUND_CONTAINER_INFO = "未绑定子卷信息";
@@ -175,6 +178,35 @@ public class PackagePdaServiceImpl implements PackagePdaService {
}
}
@Override
public void executeUpdateWeight(UpdateWeightPdaReqVO weightPdaReqVO) {
log.info("用户给 {} 修改重量 {}", SecurityFrameworkUtils.getLoginUserNickname(), weightPdaReqVO);
// 根据子卷号或 ERP 子卷号查询分切生产计划
SlittingproductionplanDO slittingPlan = slittingproductionplanMapper
.selectByContainerName(weightPdaReqVO.getContainerName());
if (slittingPlan == null) {
throw exception(PACKAGE_SLITTING_PLAN_NOT_EXISTS);
}
// 只维护用户输入且大于零的重量
SlittingproductionplanDO updatePlan = new SlittingproductionplanDO();
updatePlan.setWorkorderId(slittingPlan.getWorkorderId());
boolean needUpdate = false;
if (StrUtil.isNotBlank(weightPdaReqVO.getRollWeight())
&& new BigDecimal(weightPdaReqVO.getRollWeight()).compareTo(BigDecimal.ZERO) > 0) {
updatePlan.setWeight(weightPdaReqVO.getRollWeight());
needUpdate = true;
}
if (StrUtil.isNotBlank(weightPdaReqVO.getTubeWeight())
&& new BigDecimal(weightPdaReqVO.getTubeWeight()).compareTo(BigDecimal.ZERO) > 0) {
updatePlan.setPaperWeight(weightPdaReqVO.getTubeWeight());
needUpdate = true;
}
if (needUpdate) {
slittingproductionplanMapper.updateById(updatePlan);
}
}
/**
* 执行人工质检合格操作
*