Browse Source

MesLaser 新增待打印队列接口,支持OP40客户端轮询打印
- mes_product_laser 增加字段:print_status / print_time / print_msg
- MesLaserService 新增:
· submitSteelSn(prodCode, steelSn) — PDA提交入口
内部固定 oprno=OP040 / lineSn=T9 / user=pda,PDA只需传2个参数
· listPending(lineSn, limit) — 按 print_status=0 FIFO 拉队列
· ackPrint(customerSn, result, msg) — 客户端上报打印结果
OK: 0→1 并写 print_time;NG: 保留 0 并记录 msg,允许下次重试
- MesLaserController 新增 submitSteelSn / pendingPrint / printAck 三个接口
- application.yml 追加 3 条 anon 白名单

wangxichen 2 ngày trước cách đây
mục cha
commit
54230651ee

+ 32 - 0
src/main/java/com/jeesite/modules/mes/entity/MesProductLaser.java

@@ -23,6 +23,9 @@ import java.util.Date;
 		@Column(name="steel_sn", attrName="steelSn", label="钢印码", queryType=QueryType.LIKE),
 		@Column(name="oprno", attrName="oprno", label="工位号", queryType=QueryType.LIKE),
 		@Column(name="line_sn", attrName="lineSn", label="产线编号", queryType=QueryType.LIKE),
+		@Column(name="print_status", attrName="printStatus", label="打印状态", queryType=QueryType.EQ),
+		@Column(name="print_time", attrName="printTime", label="打印完成时间"),
+		@Column(name="print_msg", attrName="printMsg", label="打印失败原因"),
 		@Column(name="create_by", attrName="createBy", label="创建人", isUpdate=false, isQuery=false),
 		@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false, isUpdateForce=true),
 		@Column(name="update_by", attrName="updateBy", label="更新人", isQuery=false),
@@ -37,6 +40,9 @@ public class MesProductLaser extends DataEntity<MesProductLaser> {
 	private String steelSn;
 	private String oprno;
 	private String lineSn;
+	private Integer printStatus;
+	private Date printTime;
+	private String printMsg;
 	private Date createDate;
 	private Date updateDate;
 
@@ -102,6 +108,32 @@ public class MesProductLaser extends DataEntity<MesProductLaser> {
 		this.lineSn = lineSn;
 	}
 
+	public Integer getPrintStatus() {
+		return printStatus;
+	}
+
+	public void setPrintStatus(Integer printStatus) {
+		this.printStatus = printStatus;
+	}
+
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	public Date getPrintTime() {
+		return printTime;
+	}
+
+	public void setPrintTime(Date printTime) {
+		this.printTime = printTime;
+	}
+
+	@Size(min=0, max=200, message="打印失败原因长度不能超过 200 个字符")
+	public String getPrintMsg() {
+		return printMsg;
+	}
+
+	public void setPrintMsg(String printMsg) {
+		this.printMsg = printMsg;
+	}
+
 	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	@Override
 	public Date getCreateDate() {

+ 49 - 3
src/main/java/com/jeesite/modules/mes/service/MesLaserService.java

@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
@@ -73,15 +74,60 @@ public class MesLaserService {
 
 		String customerSn = genCustomerSn(prodCode, prefix);
 
-		// 绑定保存
+		// 绑定保存,同时入待打印队列 print_status=0
 		jdbcTemplate.update(
-				"INSERT INTO mes_product_laser(id,prod_code,customer_sn,steel_sn,oprno,line_sn,create_by,create_date,update_by,update_date) " +
-						"VALUES (?,?,?,?,?,?,?,now(),?,now())",
+				"INSERT INTO mes_product_laser(id,prod_code,customer_sn,steel_sn,oprno,line_sn,print_status,create_by,create_date,update_by,update_date) " +
+						"VALUES (?,?,?,?,?,?,0,?,now(),?,now())",
 				UUID.randomUUID().toString().replace("-", ""), prodCode, customerSn, steelSn, oprno, lineSn, userCode, userCode);
 
 		return customerSn;
 	}
 
+	// ==== 新流程:PDA 提交钢印码 + OP40 客户端轮询打印 ====
+
+	/**
+	 * PDA 提交钢印码入口:生成客户码、绑定并入待打印队列。
+	 * PDA 端只传 prodCode 和 steelSn,其他固定:oprno=OP040 / lineSn=T9 / user=pda。
+	 */
+	public String submitSteelSn(String prodCode, String steelSn) {
+		return genAndBindCustomerSn(prodCode, steelSn, "OP040", "T9", "pda");
+	}
+
+	/**
+	 * 拉取指定产线的待打印记录(print_status=0),按创建时间升序 FIFO。
+	 */
+	public List<Map<String, Object>> listPending(String lineSn, int limit) {
+		if (limit <= 0 || limit > 100) {
+			limit = 10;
+		}
+		String sql = "SELECT customer_sn, steel_sn, prod_code, oprno, line_sn, create_date "
+				+ "FROM mes_product_laser WHERE print_status = 0 AND line_sn = ? "
+				+ "ORDER BY create_date ASC LIMIT " + limit;
+		List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, lineSn);
+		if (rows == null) {
+			return new ArrayList<>();
+		}
+		return rows;
+	}
+
+	/**
+	 * 客户端上报打印结果。
+	 * result=OK:print_status 0→1,写入 print_time;
+	 * result=NG:保留 0,记录 print_msg,下次轮询会再拉到,允许重试。
+	 */
+	public int ackPrint(String customerSn, String result, String msg) {
+		if ("OK".equalsIgnoreCase(result)) {
+			return jdbcTemplate.update(
+					"UPDATE mes_product_laser SET print_status=1, print_time=now(), print_msg=NULL, update_date=now() "
+							+ "WHERE customer_sn=? AND print_status=0",
+					customerSn);
+		}
+		// NG 不改状态,只更新失败原因
+		return jdbcTemplate.update(
+				"UPDATE mes_product_laser SET print_msg=?, update_date=now() WHERE customer_sn=?",
+				msg == null ? "" : msg, customerSn);
+	}
+
 	/**
 	 * 解绑钢印码和客户码映射。客户码建档数据保留,只删除 mes_product_laser 对应关系。
 	 * @param steelSn 钢印码

+ 112 - 0
src/main/java/com/jeesite/modules/mes/web/MesLaserController.java

@@ -1,5 +1,9 @@
 package com.jeesite.modules.mes.web;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import javax.servlet.http.HttpServletRequest;
 
 import com.jeesite.common.lang.StringUtils;
@@ -10,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import com.jeesite.common.config.Global;
@@ -101,4 +106,111 @@ public class MesLaserController extends BaseController {
 
 		return resp;
 	}
+
+	// ==== 新流程:PDA 提交 + OP40 客户端轮询打印 ====
+
+	/**
+	 * PDA 端提交钢印码:服务端生成客户码,绑定并入待打印队列。
+	 * 请求参数(form):steelSn / prodCode
+	 * 返回 data.customerSn(21位客户码)
+	 * 说明:lineSn 和 user 由服务端固定填入(lineSn=T9,user=pda),PDA 端不用传。
+	 */
+	@PostMapping(value = "submitSteelSn")
+	@ResponseBody
+	public CommonResp<Map<String, String>> submitSteelSn(HttpServletRequest request) {
+		CommonResp<Map<String, String>> resp = new CommonResp<>();
+		String steelSn = request.getParameter("steelSn");
+		String prodCode = request.getParameter("prodCode");
+
+		if (StringUtils.isEmpty(steelSn)) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage("steelSn 不能为空");
+			return resp;
+		}
+		if (StringUtils.isEmpty(prodCode)) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage("prodCode 不能为空");
+			return resp;
+		}
+		try {
+			String customerSn = mesLaserService.submitSteelSn(prodCode, steelSn);
+			Map<String, String> data = new HashMap<>();
+			data.put("customerSn", customerSn);
+			resp.setData(data);
+			resp.setResult(Global.TRUE);
+			resp.setMessage("提交成功");
+		} catch (ServiceException e) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage(e.getMessage());
+		} catch (Exception e) {
+			logger.error("PDA 提交钢印码失败:steelSn=" + steelSn, e);
+			resp.setResult(Global.FALSE);
+			resp.setMessage("提交失败:" + e.getMessage());
+		}
+		return resp;
+	}
+
+	/**
+	 * OP40 客户端拉取待打印列表(FIFO,按创建时间升序)。
+	 * @param lineSn 产线编号,例 T9
+	 * @param limit 单次条数上限,默认 10
+	 * @return data 列表元素含 customerSn / steelSn / prodCode / oprno / createDate
+	 */
+	@RequestMapping(value = "pendingPrint")
+	@ResponseBody
+	public CommonResp<List<Map<String, Object>>> pendingPrint(
+			@RequestParam("lineSn") String lineSn,
+			@RequestParam(value = "limit", required = false, defaultValue = "10") int limit) {
+		CommonResp<List<Map<String, Object>>> resp = new CommonResp<>();
+		if (StringUtils.isEmpty(lineSn)) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage("lineSn 不能为空");
+			return resp;
+		}
+		try {
+			List<Map<String, Object>> list = mesLaserService.listPending(lineSn, limit);
+			resp.setData(list);
+			resp.setResult(Global.TRUE);
+			resp.setMessage("OK");
+		} catch (Exception e) {
+			logger.error("拉取待打印列表失败:lineSn=" + lineSn, e);
+			resp.setResult(Global.FALSE);
+			resp.setMessage("拉取失败:" + e.getMessage());
+		}
+		return resp;
+	}
+
+	/**
+	 * OP40 客户端上报打印结果。
+	 * 请求参数(form):customerSn / result=OK|NG / msg(失败原因,可选)
+	 */
+	@PostMapping(value = "printAck")
+	@ResponseBody
+	public CommonResp printAck(HttpServletRequest request) {
+		CommonResp<String> resp = new CommonResp<>();
+		String customerSn = request.getParameter("customerSn");
+		String result = request.getParameter("result");
+		String msg = request.getParameter("msg");
+
+		if (StringUtils.isEmpty(customerSn)) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage("customerSn 不能为空");
+			return resp;
+		}
+		if (!"OK".equalsIgnoreCase(result) && !"NG".equalsIgnoreCase(result)) {
+			resp.setResult(Global.FALSE);
+			resp.setMessage("result 只能是 OK/NG");
+			return resp;
+		}
+		try {
+			int rows = mesLaserService.ackPrint(customerSn, result, msg);
+			resp.setResult(Global.TRUE);
+			resp.setMessage("ack 已接收,影响行数 " + rows);
+		} catch (Exception e) {
+			logger.error("打印结果 ack 失败:customerSn=" + customerSn, e);
+			resp.setResult(Global.FALSE);
+			resp.setMessage("ack 失败:" + e.getMessage());
+		}
+		return resp;
+	}
 }

+ 3 - 0
src/main/resources/config/application.yml

@@ -645,6 +645,9 @@ shiro:
     ${adminPath}/mes/mesMaterialPrebind/bind = anon
     ${adminPath}/mes/mesLaser/genCustomerSn = anon
     ${adminPath}/mes/mesLaser/unbindSteelSn = anon
+    ${adminPath}/mes/mesLaser/submitSteelSn = anon
+    ${adminPath}/mes/mesLaser/pendingPrint = anon
+    ${adminPath}/mes/mesLaser/printAck = anon
     ${adminPath}/mes/mesProductPush/test = anon
     ${adminPath}/mes/mesProcessCheckRecord/check = anon
     ${adminPath}/mes/mesProductRecord/work = anon