sunxianglong 2 месяцев назад
Родитель
Сommit
92275bb972
22 измененных файлов с 1934 добавлено и 115 удалено
  1. 15 0
      src/main/java/com/jeesite/modules/mes/dao/MesProductQmzcDao.java
  2. 2 2
      src/main/java/com/jeesite/modules/mes/dao/MesProductTjDao.java
  3. 187 0
      src/main/java/com/jeesite/modules/mes/entity/MesProductQmzc.java
  4. 19 27
      src/main/java/com/jeesite/modules/mes/entity/MesProductTj.java
  5. 81 0
      src/main/java/com/jeesite/modules/mes/service/MesProductQmzcService.java
  6. 2 2
      src/main/java/com/jeesite/modules/mes/service/MesProductTjService.java
  7. 18 0
      src/main/java/com/jeesite/modules/mes/web/MesOrderSnController.java
  8. 19 0
      src/main/java/com/jeesite/modules/mes/web/MesOrderSnJjController.java
  9. 43 0
      src/main/java/com/jeesite/modules/mes/web/MesProductCmtDataController.java
  10. 97 0
      src/main/java/com/jeesite/modules/mes/web/MesProductQmzcController.java
  11. 4 52
      src/main/java/com/jeesite/modules/mes/web/MesProductTjController.java
  12. 344 0
      src/main/java/com/jeesite/modules/scheduling/FrameworkQmScheduling.java
  13. 322 0
      src/main/java/com/jeesite/modules/scheduling/ProductTjBScheduling.java
  14. 322 0
      src/main/java/com/jeesite/modules/scheduling/ProductTjScheduling.java
  15. 22 0
      src/main/resources/config/application.yml
  16. 15 0
      src/main/resources/mappings/modules/mes/MesProductQmzcDao.xml
  17. 69 0
      src/main/resources/views/modules/mes/mesProductCmtDataDetail.html
  18. 8 6
      src/main/resources/views/modules/mes/mesProductCmtDataList.html
  19. 172 0
      src/main/resources/views/modules/mes/mesProductQmzcForm.html
  20. 149 0
      src/main/resources/views/modules/mes/mesProductQmzcList.html
  21. 12 12
      src/main/resources/views/modules/mes/mesProductTjForm.html
  22. 12 14
      src/main/resources/views/modules/mes/mesProductTjList.html

+ 15 - 0
src/main/java/com/jeesite/modules/mes/dao/MesProductQmzcDao.java

@@ -0,0 +1,15 @@
+package com.jeesite.modules.mes.dao;
+
+import com.jeesite.common.dao.CrudDao;
+import com.jeesite.common.mybatis.annotation.MyBatisDao;
+import com.jeesite.modules.mes.entity.MesProductQmzc;
+
+/**
+ * 总成气密数据表DAO接口
+ * @author sxl
+ * @version 2026-08-25
+ */
+@MyBatisDao
+public interface MesProductQmzcDao extends CrudDao<MesProductQmzc> {
+	
+}

+ 2 - 2
src/main/java/com/jeesite/modules/mes/dao/MesProductTjDao.java

@@ -6,8 +6,8 @@ import com.jeesite.modules.mes.entity.MesProductTj;
 
 /**
  * 涂胶数据DAO接口
- * @author liuwei
- * @version 2026-08-14
+ * @author sxl
+ * @version 2026-08-23
  */
 @MyBatisDao
 public interface MesProductTjDao extends CrudDao<MesProductTj> {

+ 187 - 0
src/main/java/com/jeesite/modules/mes/entity/MesProductQmzc.java

@@ -0,0 +1,187 @@
+package com.jeesite.modules.mes.entity;
+
+import javax.validation.constraints.Size;
+
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.Table;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
+
+/**
+ * 总成气密数据表Entity
+ * @author sxl
+ * @version 2026-08-25
+ */
+@Table(name="mes_product_qmzc", alias="a", label="总成气密数据表信息", columns={
+		@Column(name="id", attrName="id", label="id", isPK=true),
+		@Column(name="ylb_cqsj", attrName="ylbCqsj", label="液冷板充气时间"),
+		@Column(name="ylb_cssj", attrName="ylbCssj", label="液冷板测试时间"),
+		@Column(name="ylb_cqyl", attrName="ylbCqyl", label="液冷板充气压力"),
+		@Column(name="ylb_wdyl", attrName="ylbWdyl", label="液冷板稳定压力"),
+		@Column(name="ylb_leak", attrName="ylbLeak", label="液冷板泄漏里"),
+		@Column(name="ylb_bysj", attrName="ylbBysj", label="夜冷板保压时间"),
+		@Column(name="cqsj", attrName="cqsj", label="框架架充气时间"),
+		@Column(name="cssj", attrName="cssj", label="框架测试时间"),
+		@Column(name="cqya", attrName="cqya", label="框架充气压力"),
+		@Column(name="wdyl", attrName="wdyl", label="框架稳定压力"),
+		@Column(name="leak", attrName="leak", label="框架泄漏里"),
+		@Column(name="bysj", attrName="bysj", label="框架保压时间"),
+		@Column(name="create_by", attrName="createBy", label="创建人", isUpdate=false, isQuery=false),
+		@Column(name="result", attrName="result", label="框架测试结果"),
+		@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false, isUpdateForce=true),
+		@Column(name="ylb_result", attrName="ylbResult", label="水冷板测试结果"),
+	}, orderBy="a.id DESC"
+)
+public class MesProductQmzc extends DataEntity<MesProductQmzc> {
+	
+	private static final long serialVersionUID = 1L;
+	private String ylbCqsj;		// 液冷板充气时间
+	private String ylbCssj;		// 液冷板测试时间
+	private String ylbCqyl;		// 液冷板充气压力
+	private String ylbWdyl;		// 液冷板稳定压力
+	private String ylbLeak;		// 液冷板泄漏里
+	private String ylbBysj;		// 夜冷板保压时间
+	private String cqsj;		// 框架架充气时间
+	private String cssj;		// 框架测试时间
+	private String cqya;		// 框架充气压力
+	private String wdyl;		// 框架稳定压力
+	private String leak;		// 框架泄漏里
+	private String bysj;		// 框架保压时间
+	private String result;		// 框架测试结果
+	private String ylbResult;		// 水冷板测试结果
+
+	public MesProductQmzc() {
+		this(null);
+	}
+	
+	public MesProductQmzc(String id){
+		super(id);
+	}
+	
+	@Size(min=0, max=255, message="液冷板充气时间长度不能超过 255 个字符")
+	public String getYlbCqsj() {
+		return ylbCqsj;
+	}
+
+	public void setYlbCqsj(String ylbCqsj) {
+		this.ylbCqsj = ylbCqsj;
+	}
+	
+	@Size(min=0, max=255, message="液冷板测试时间长度不能超过 255 个字符")
+	public String getYlbCssj() {
+		return ylbCssj;
+	}
+
+	public void setYlbCssj(String ylbCssj) {
+		this.ylbCssj = ylbCssj;
+	}
+	
+	@Size(min=0, max=255, message="液冷板充气压力长度不能超过 255 个字符")
+	public String getYlbCqyl() {
+		return ylbCqyl;
+	}
+
+	public void setYlbCqyl(String ylbCqyl) {
+		this.ylbCqyl = ylbCqyl;
+	}
+	
+	@Size(min=0, max=255, message="液冷板稳定压力长度不能超过 255 个字符")
+	public String getYlbWdyl() {
+		return ylbWdyl;
+	}
+
+	public void setYlbWdyl(String ylbWdyl) {
+		this.ylbWdyl = ylbWdyl;
+	}
+	
+	@Size(min=0, max=255, message="液冷板泄漏里长度不能超过 255 个字符")
+	public String getYlbLeak() {
+		return ylbLeak;
+	}
+
+	public void setYlbLeak(String ylbLeak) {
+		this.ylbLeak = ylbLeak;
+	}
+	
+	@Size(min=0, max=255, message="夜冷板保压时间长度不能超过 255 个字符")
+	public String getYlbBysj() {
+		return ylbBysj;
+	}
+
+	public void setYlbBysj(String ylbBysj) {
+		this.ylbBysj = ylbBysj;
+	}
+	
+	@Size(min=0, max=255, message="框架架充气时间长度不能超过 255 个字符")
+	public String getCqsj() {
+		return cqsj;
+	}
+
+	public void setCqsj(String cqsj) {
+		this.cqsj = cqsj;
+	}
+	
+	@Size(min=0, max=255, message="框架测试时间长度不能超过 255 个字符")
+	public String getCssj() {
+		return cssj;
+	}
+
+	public void setCssj(String cssj) {
+		this.cssj = cssj;
+	}
+	
+	@Size(min=0, max=255, message="框架充气压力长度不能超过 255 个字符")
+	public String getCqya() {
+		return cqya;
+	}
+
+	public void setCqya(String cqya) {
+		this.cqya = cqya;
+	}
+	
+	@Size(min=0, max=255, message="框架稳定压力长度不能超过 255 个字符")
+	public String getWdyl() {
+		return wdyl;
+	}
+
+	public void setWdyl(String wdyl) {
+		this.wdyl = wdyl;
+	}
+	
+	@Size(min=0, max=255, message="框架泄漏里长度不能超过 255 个字符")
+	public String getLeak() {
+		return leak;
+	}
+
+	public void setLeak(String leak) {
+		this.leak = leak;
+	}
+	
+	@Size(min=0, max=255, message="框架保压时间长度不能超过 255 个字符")
+	public String getBysj() {
+		return bysj;
+	}
+
+	public void setBysj(String bysj) {
+		this.bysj = bysj;
+	}
+	
+	@Size(min=0, max=255, message="框架测试结果长度不能超过 255 个字符")
+	public String getResult() {
+		return result;
+	}
+
+	public void setResult(String result) {
+		this.result = result;
+	}
+	
+	@Size(min=0, max=255, message="水冷板测试结果长度不能超过 255 个字符")
+	public String getYlbResult() {
+		return ylbResult;
+	}
+
+	public void setYlbResult(String ylbResult) {
+		this.ylbResult = ylbResult;
+	}
+	
+}

+ 19 - 27
src/main/java/com/jeesite/modules/mes/entity/MesProductTj.java

@@ -5,33 +5,32 @@ import javax.validation.constraints.Size;
 import com.jeesite.common.entity.DataEntity;
 import com.jeesite.common.mybatis.annotation.Column;
 import com.jeesite.common.mybatis.annotation.Table;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
 
 /**
  * 涂胶数据Entity
- * @author liuwei
- * @version 2026-08-14
+ * @author sxl
+ * @version 2026-08-23
  */
 @Table(name="mes_product_tj", alias="a", label="涂胶数据信息", columns={
 		@Column(name="id", attrName="id", label="id", isPK=true),
 		@Column(name="sn", attrName="sn", label="工件码"),
-		@Column(name="line_sn", attrName="lineSn", label="产线编号"),
 		@Column(name="oprno", attrName="oprno", label="工位号"),
-		@Column(name="tj_speed", attrName="tjSpeed", label="涂胶速度", isUpdateForce=true),
-		@Column(name="tj_length", attrName="tjLength", label="涂胶长度", isUpdateForce=true),
-		@Column(name="tj_data", attrName="tjData", label="涂胶数据"),
+		@Column(name="tj_speed", attrName="tjSpeed", label="涂胶速度"),
+		@Column(name="tj_length", attrName="tjLength", label="涂胶长度"),
+		@Column(name="tj_data", attrName="tjData", label="涂胶序号"),
 		@Column(name="create_by", attrName="createBy", label="create_by", isUpdate=false, isQuery=false),
-		@Column(name="create_date", attrName="createDate", label="上传时间", isUpdate=false, isQuery=false),
+		@Column(name="create_date", attrName="createDate", label="上传时间", isUpdate=false, isQuery=false, isUpdateForce=true),
 	}, orderBy="a.id DESC"
 )
 public class MesProductTj extends DataEntity<MesProductTj> {
 	
 	private static final long serialVersionUID = 1L;
 	private String sn;		// 工件码
-	private String lineSn;		// 产线编号
 	private String oprno;		// 工位号
-	private Double tjSpeed;		// 涂胶速度
-	private Double tjLength;		// 涂胶长度
-	private String tjData;		// 涂胶数据 序号#速度#长度#...
+	private String tjSpeed;		// 涂胶速度
+	private String tjLength;		// 涂胶长度
+	private String tjData;		// 涂胶序号
 
 	public MesProductTj() {
 		this(null);
@@ -41,7 +40,7 @@ public class MesProductTj extends DataEntity<MesProductTj> {
 		super(id);
 	}
 	
-	@Size(min=0, max=255, message="工件码长度不能超过 255 个字符")
+	@Size(min=0, max=64, message="工件码长度不能超过 64 个字符")
 	public String getSn() {
 		return sn;
 	}
@@ -50,15 +49,6 @@ public class MesProductTj extends DataEntity<MesProductTj> {
 		this.sn = sn;
 	}
 	
-	@Size(min=0, max=255, message="产线编号长度不能超过 255 个字符")
-	public String getLineSn() {
-		return lineSn;
-	}
-
-	public void setLineSn(String lineSn) {
-		this.lineSn = lineSn;
-	}
-	
 	@Size(min=0, max=255, message="工位号长度不能超过 255 个字符")
 	public String getOprno() {
 		return oprno;
@@ -68,23 +58,25 @@ public class MesProductTj extends DataEntity<MesProductTj> {
 		this.oprno = oprno;
 	}
 	
-	public Double getTjSpeed() {
+	@Size(min=0, max=255, message="涂胶速度长度不能超过 255 个字符")
+	public String getTjSpeed() {
 		return tjSpeed;
 	}
 
-	public void setTjSpeed(Double tjSpeed) {
+	public void setTjSpeed(String tjSpeed) {
 		this.tjSpeed = tjSpeed;
 	}
 	
-	public Double getTjLength() {
+	@Size(min=0, max=255, message="涂胶长度长度不能超过 255 个字符")
+	public String getTjLength() {
 		return tjLength;
 	}
 
-	public void setTjLength(Double tjLength) {
+	public void setTjLength(String tjLength) {
 		this.tjLength = tjLength;
 	}
-
-	@Size(min=0, max=2000, message="涂胶数据长度不能超过 2000 个字符")
+	
+	@Size(min=0, max=2000, message="涂胶序号长度不能超过 2000 个字符")
 	public String getTjData() {
 		return tjData;
 	}

+ 81 - 0
src/main/java/com/jeesite/modules/mes/service/MesProductQmzcService.java

@@ -0,0 +1,81 @@
+package com.jeesite.modules.mes.service;
+
+import java.util.List;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.modules.mes.entity.MesProductQmzc;
+import com.jeesite.modules.mes.dao.MesProductQmzcDao;
+
+/**
+ * 总成气密数据表Service
+ * @author sxl
+ * @version 2026-08-25
+ */
+@Service
+public class MesProductQmzcService extends CrudService<MesProductQmzcDao, MesProductQmzc> {
+	
+	/**
+	 * 获取单条数据
+	 * @param mesProductQmzc
+	 * @return
+	 */
+	@Override
+	public MesProductQmzc get(MesProductQmzc mesProductQmzc) {
+		return super.get(mesProductQmzc);
+	}
+	
+	/**
+	 * 查询分页数据
+	 * @param mesProductQmzc 查询条件
+	 * @param mesProductQmzc.page 分页对象
+	 * @return
+	 */
+	@Override
+	public Page<MesProductQmzc> findPage(MesProductQmzc mesProductQmzc) {
+		return super.findPage(mesProductQmzc);
+	}
+	
+	/**
+	 * 查询列表数据
+	 * @param mesProductQmzc
+	 * @return
+	 */
+	@Override
+	public List<MesProductQmzc> findList(MesProductQmzc mesProductQmzc) {
+		return super.findList(mesProductQmzc);
+	}
+	
+	/**
+	 * 保存数据(插入或更新)
+	 * @param mesProductQmzc
+	 */
+	@Override
+	@Transactional
+	public void save(MesProductQmzc mesProductQmzc) {
+		super.save(mesProductQmzc);
+	}
+	
+	/**
+	 * 更新状态
+	 * @param mesProductQmzc
+	 */
+	@Override
+	@Transactional
+	public void updateStatus(MesProductQmzc mesProductQmzc) {
+		super.updateStatus(mesProductQmzc);
+	}
+	
+	/**
+	 * 删除数据
+	 * @param mesProductQmzc
+	 */
+	@Override
+	@Transactional
+	public void delete(MesProductQmzc mesProductQmzc) {
+		super.delete(mesProductQmzc);
+	}
+	
+}

+ 2 - 2
src/main/java/com/jeesite/modules/mes/service/MesProductTjService.java

@@ -11,8 +11,8 @@ import com.jeesite.modules.mes.dao.MesProductTjDao;
 
 /**
  * 涂胶数据Service
- * @author liuwei
- * @version 2026-08-14
+ * @author sxl
+ * @version 2026-08-23
  */
 @Service
 public class MesProductTjService extends CrudService<MesProductTjDao, MesProductTj> {

+ 18 - 0
src/main/java/com/jeesite/modules/mes/web/MesOrderSnController.java

@@ -184,6 +184,24 @@ public class MesOrderSnController extends BaseController {
 			return renderResult(Global.FALSE, text("该工件已和生产订单绑定!"));
 		}
 
+		// 校验已绑定数量是否已达订单生产数量,相同则不允许再绑定
+		MesProductOrder orderQuery = new MesProductOrder();
+		orderQuery.setSn(mesOrderSn.getOrderId());
+		List<MesProductOrder> orderList = mesProductOrderService.findList(orderQuery);
+		if (orderList == null || orderList.isEmpty() || ObjectUtils.isEmpty(orderList.get(0))) {
+			return renderResult(Global.FALSE, text("生产订单不存在!"));
+		}
+		Integer orderNums = orderList.get(0).getNums();
+		if (orderNums == null) {
+			return renderResult(Global.FALSE, text("生产订单数量未配置!"));
+		}
+		MesOrderSn boundQuery = new MesOrderSn();
+		boundQuery.setOrderId(mesOrderSn.getOrderId());
+		long boundCount = mesOrderSnService.findCount(boundQuery);
+		if (boundCount >= orderNums) {
+			return renderResult(Global.FALSE, text("该订单已绑定数量已达生产数量,不允许再绑定!"));
+		}
+
 		try {
 			mesOrderSnService.save(mesOrderSn);
 			// 绑定成功后,将 OP100 工位结果提交为 OK

+ 19 - 0
src/main/java/com/jeesite/modules/mes/web/MesOrderSnJjController.java

@@ -173,6 +173,25 @@ public class MesOrderSnJjController extends BaseController {
 		if (!list.isEmpty()) {
 			return renderResult(Global.FALSE, text("该工件已和机加订单绑定!"));
 		}
+
+		// 校验已绑定数量是否已达订单生产数量,相同则不允许再绑定
+		MesProductOrder orderQuery = new MesProductOrder();
+		orderQuery.setSn(mesOrderSnJj.getOrderJj());
+		List<MesProductOrder> orderList = mesProductOrderService.findList(orderQuery);
+		if (orderList == null || orderList.isEmpty() || ObjectUtils.isEmpty(orderList.get(0))) {
+			return renderResult(Global.FALSE, text("生产订单不存在!"));
+		}
+		Integer orderNums = orderList.get(0).getNums();
+		if (orderNums == null) {
+			return renderResult(Global.FALSE, text("生产订单数量未配置!"));
+		}
+		MesOrderSnJj boundQuery = new MesOrderSnJj();
+		boundQuery.setOrderJj(mesOrderSnJj.getOrderJj());
+		long boundCount = mesOrderSnJjService.findCount(boundQuery);
+		if (boundCount >= orderNums) {
+			return renderResult(Global.FALSE, text("该订单已绑定数量已达生产数量,不允许再绑定!"));
+		}
+
 		mesOrderSnJjService.save(mesOrderSnJj);
 		return renderResult(Global.TRUE, text("保存成功!"));
 	}

+ 43 - 0
src/main/java/com/jeesite/modules/mes/web/MesProductCmtDataController.java

@@ -1,6 +1,9 @@
 package com.jeesite.modules.mes.web;
 
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -76,6 +79,17 @@ public class MesProductCmtDataController extends BaseController {
 	}
 
 	/**
+	 * 详情页:按 # 拆分展示送丝速度、电流、电压
+	 */
+	@RequiresPermissions("mes:mesProductCmtData:view")
+	@RequestMapping(value = "detail")
+	public String detail(MesProductCmtData mesProductCmtData, Model model) {
+		model.addAttribute("mesProductCmtData", mesProductCmtData);
+		model.addAttribute("detailRows", buildDetailRows(mesProductCmtData));
+		return "modules/mes/mesProductCmtDataDetail";
+	}
+
+	/**
 	 * 保存数据
 	 */
 	@RequiresPermissions("mes:mesProductCmtData:edit")
@@ -144,5 +158,34 @@ public class MesProductCmtDataController extends BaseController {
 		mesProductCmtDataService.save(entity);
 		return renderResult(Global.TRUE, text("操作成功!"));
 	}
+
+	/**
+	 * 将 # 分隔的过程参数拆成逐行数据
+	 */
+	private List<Map<String, String>> buildDetailRows(MesProductCmtData data) {
+		List<Map<String, String>> rows = new ArrayList<>();
+		if (data == null) {
+			return rows;
+		}
+		String[] ssSpeeds = splitByHash(data.getSsSpeed());
+		String[] currents = splitByHash(data.getCurrent());
+		String[] voltages = splitByHash(data.getVoltage());
+		int max = Math.max(ssSpeeds.length, Math.max(currents.length, voltages.length));
+		for (int i = 0; i < max; i++) {
+			Map<String, String> row = new LinkedHashMap<>();
+			row.put("ssSpeed", i < ssSpeeds.length ? ssSpeeds[i] : "");
+			row.put("current", i < currents.length ? currents[i] : "");
+			row.put("voltage", i < voltages.length ? voltages[i] : "");
+			rows.add(row);
+		}
+		return rows;
+	}
+
+	private String[] splitByHash(String value) {
+		if (StringUtils.isBlank(value)) {
+			return new String[0];
+		}
+		return value.trim().split("#", -1);
+	}
 	
 }

+ 97 - 0
src/main/java/com/jeesite/modules/mes/web/MesProductQmzcController.java

@@ -0,0 +1,97 @@
+package com.jeesite.modules.mes.web;
+
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.jeesite.common.config.Global;
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.web.BaseController;
+import com.jeesite.modules.mes.entity.MesProductQmzc;
+import com.jeesite.modules.mes.service.MesProductQmzcService;
+
+/**
+ * 总成气密数据表Controller
+ * @author sxl
+ * @version 2026-08-25
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesProductQmzc")
+public class MesProductQmzcController extends BaseController {
+
+	@Autowired
+	private MesProductQmzcService mesProductQmzcService;
+	
+	/**
+	 * 获取数据
+	 */
+	@ModelAttribute
+	public MesProductQmzc get(String id, boolean isNewRecord) {
+		return mesProductQmzcService.get(id, isNewRecord);
+	}
+	
+	/**
+	 * 查询列表
+	 */
+	@RequiresPermissions("mes:mesProductQmzc:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesProductQmzc mesProductQmzc, Model model) {
+		model.addAttribute("mesProductQmzc", mesProductQmzc);
+		return "modules/mes/mesProductQmzcList";
+	}
+	
+	/**
+	 * 查询列表数据
+	 */
+	@RequiresPermissions("mes:mesProductQmzc:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesProductQmzc> listData(MesProductQmzc mesProductQmzc, HttpServletRequest request, HttpServletResponse response) {
+		mesProductQmzc.setPage(new Page<>(request, response));
+		Page<MesProductQmzc> page = mesProductQmzcService.findPage(mesProductQmzc);
+		return page;
+	}
+
+	/**
+	 * 查看编辑表单
+	 */
+	@RequiresPermissions("mes:mesProductQmzc:view")
+	@RequestMapping(value = "form")
+	public String form(MesProductQmzc mesProductQmzc, Model model) {
+		model.addAttribute("mesProductQmzc", mesProductQmzc);
+		return "modules/mes/mesProductQmzcForm";
+	}
+
+	/**
+	 * 保存数据
+	 */
+	@RequiresPermissions("mes:mesProductQmzc:edit")
+	@PostMapping(value = "save")
+	@ResponseBody
+	public String save(@Validated MesProductQmzc mesProductQmzc) {
+		mesProductQmzcService.save(mesProductQmzc);
+		return renderResult(Global.TRUE, text("保存总成气密数据表成功!"));
+	}
+	
+	/**
+	 * 删除数据
+	 */
+	@RequiresPermissions("mes:mesProductQmzc:edit")
+	@RequestMapping(value = "delete")
+	@ResponseBody
+	public String delete(MesProductQmzc mesProductQmzc) {
+		mesProductQmzcService.delete(mesProductQmzc);
+		return renderResult(Global.TRUE, text("删除总成气密数据表成功!"));
+	}
+	
+}

+ 4 - 52
src/main/java/com/jeesite/modules/mes/web/MesProductTjController.java

@@ -1,5 +1,6 @@
 package com.jeesite.modules.mes.web;
 
+import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -15,16 +16,14 @@ import org.springframework.web.bind.annotation.ResponseBody;
 
 import com.jeesite.common.config.Global;
 import com.jeesite.common.entity.Page;
-import com.jeesite.common.lang.StringUtils;
 import com.jeesite.common.web.BaseController;
 import com.jeesite.modules.mes.entity.MesProductTj;
-import com.jeesite.modules.mes.resp.CommonResp;
 import com.jeesite.modules.mes.service.MesProductTjService;
 
 /**
  * 涂胶数据Controller
- * @author liuwei
- * @version 2026-08-14
+ * @author sxl
+ * @version 2026-08-23
  */
 @Controller
 @RequestMapping(value = "${adminPath}/mes/mesProductTj")
@@ -94,52 +93,5 @@ public class MesProductTjController extends BaseController {
 		mesProductTjService.delete(mesProductTj);
 		return renderResult(Global.TRUE, text("删除涂胶数据成功!"));
 	}
-
-	/**
-	 * 设备端上传涂胶长串(序号#速度#长度#...),整段写入 tj_data
-	 */
-	@ResponseBody
-	@PostMapping(value = "upload")
-	public CommonResp<String> upload(HttpServletRequest request) {
-		CommonResp<String> resp = new CommonResp<>();
-		String sn = request.getParameter("sn");
-		String lineSn = request.getParameter("lineSn");
-		String oprno = request.getParameter("oprno");
-		String tjData = request.getParameter("tjData");
-		if (StringUtils.isBlank(sn) || StringUtils.isBlank(lineSn) || StringUtils.isBlank(oprno)) {
-			resp.setResult(Global.FALSE);
-			resp.setMessage("参数错误");
-			return resp;
-		}
-		if (StringUtils.isNotBlank(tjData)) {
-			tjData = tjData.trim();
-			String[] parts = tjData.split("#", -1);
-			if (parts.length % 3 != 0) {
-				resp.setResult(Global.FALSE);
-				resp.setMessage("涂胶数据格式错误,应为 序号#速度#长度#...");
-				return resp;
-			}
-			if (tjData.length() > 2000) {
-				resp.setResult(Global.FALSE);
-				resp.setMessage("涂胶数据超长");
-				return resp;
-			}
-		}
-		try {
-			MesProductTj entity = new MesProductTj();
-			entity.setSn(sn.trim());
-			entity.setLineSn(lineSn.trim());
-			entity.setOprno(oprno.trim());
-			entity.setTjData(tjData);
-			mesProductTjService.save(entity);
-			resp.setResult(Global.TRUE);
-			resp.setMessage("上传成功");
-		} catch (Exception e) {
-			logger.error("涂胶数据上传失败 sn={}", sn, e);
-			resp.setResult(Global.FALSE);
-			resp.setMessage("上传失败");
-		}
-		return resp;
-	}
 	
-}
+}

+ 344 - 0
src/main/java/com/jeesite/modules/scheduling/FrameworkQmScheduling.java

@@ -0,0 +1,344 @@
+package com.jeesite.modules.scheduling;
+
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+import com.jeesite.common.config.Global;
+import com.jeesite.common.lang.ObjectUtils;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.modules.mes.entity.MesLine;
+import com.jeesite.modules.mes.entity.MesProduct;
+import com.jeesite.modules.mes.entity.MesProductQmzc;
+import com.jeesite.modules.mes.resp.BindMaterialResp;
+import com.jeesite.modules.mes.resp.ParamsResp;
+import com.jeesite.modules.mes.service.MesLineService;
+import com.jeesite.modules.mes.service.MesProductQmzcService;
+import com.jeesite.modules.mes.service.MesProductRecordService;
+import com.jeesite.modules.mes.service.MesProductService;
+import com.jeesite.modules.mes.web.MesProductRecordController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 框架气密 S7 采集与质量握手(OP360)。
+ * <pre>
+ * DB200 点位:
+ *   0.0   质量校验通过反馈(MES 写 true)
+ *   2.0   框架码 String[30]
+ *   34.0  扫码反馈信号
+ *   36.0  液冷板充气时间 Real
+ *   40.0  液冷板测试时间 Real
+ *   44.0  液冷板充气压力 Real
+ *   48.0  液冷板稳定压力 Real
+ *   52.0  液冷板泄漏量 Real
+ *   56.0  框架充气时间 Real
+ *   60.0  框架测试时间 Real
+ *   64.0  框架充气压力 Real
+ *   68.0  框架稳定压力 Real
+ *   72.0  框架泄露量 Real
+ *   76.0  过程数据采集触发
+ *   78.0  液冷板保压时间 Real
+ *   82.0  框架保压时间 Real
+ *   86.0  液冷板判定结果 Bool
+ *   86.1  框架判定结果 Bool
+ *
+ * 配置(application.yml):
+ *   mes.framework.qm.enabled   是否启用(默认 false)
+ *   mes.framework.qm.plc.ip      PLC IP,默认 192.168.1.100
+ *   mes.framework.qm.oprno       工位号,默认 OP360
+ *   mes.framework.qm.lineSn      产线编号,默认 XT
+ * </pre>
+ */
+@Configuration
+@EnableScheduling
+public class FrameworkQmScheduling {
+
+	private static final Logger logger = LoggerFactory.getLogger(FrameworkQmScheduling.class);
+
+	private static final String ADDR_QUALITY_PASS = "DB200.0.0";
+	private static final String ADDR_SN = "DB200.2.0";
+	private static final int SN_LENGTH = 30;
+	private static final String ADDR_SCAN_FEEDBACK = "DB200.34.0";
+
+	private static final String ADDR_YLB_INFLATION_TIME = "DB200.36.0";
+	private static final String ADDR_YLB_TEST_TIME = "DB200.40.0";
+	private static final String ADDR_YLB_INFLATION_PRESSURE = "DB200.44.0";
+	private static final String ADDR_YLB_STABLE_PRESSURE = "DB200.48.0";
+	private static final String ADDR_YLB_LEAK = "DB200.52.0";
+	private static final String ADDR_YLB_HOLD_TIME = "DB200.78.0";
+
+	private static final String ADDR_INFLATION_TIME = "DB200.56.0";
+	private static final String ADDR_TEST_TIME = "DB200.60.0";
+	private static final String ADDR_INFLATION_PRESSURE = "DB200.64.0";
+	private static final String ADDR_STABLE_PRESSURE = "DB200.68.0";
+	private static final String ADDR_LEAK_AMOUNT = "DB200.72.0";
+	private static final String ADDR_COLLECT_FLAG = "DB200.76.0";
+	private static final String ADDR_HOLD_TIME = "DB200.82.0";
+	private static final String ADDR_YLB_JUDGE_RESULT = "DB200.86.0";
+	private static final String ADDR_JUDGE_RESULT = "DB200.86.1";
+
+	private static final String DEFAULT_PLC_IP = "192.168.1.100";
+	private static final String DEFAULT_OPRNO = "OP360";
+	private static final String DEFAULT_LINE_SN = "XT";
+
+	@Autowired
+	private MesProductRecordController mesProductRecordController;
+	@Autowired
+	private MesProductService mesProductService;
+	@Autowired
+	private MesLineService mesLineService;
+	@Autowired
+	private MesProductQmzcService mesProductQmzcService;
+	@Autowired
+	private MesProductRecordService mesProductRecordService;
+
+	private final AtomicBoolean running = new AtomicBoolean(false);
+	private volatile String lastCheckedSn;
+	private volatile String lastKnownSn;
+
+	@Scheduled(fixedRate = 1000)
+	public void collect() {
+		String enabled = Global.getConfig("mes.framework.qm.enabled");
+		if (StringUtils.isBlank(enabled) || !"true".equalsIgnoreCase(enabled.trim())) {
+			return;
+		}
+		runOnce();
+	}
+
+	/**
+	 * 直接执行一轮(供测试调用)
+	 */
+	public void runOnce() {
+		if (!running.compareAndSet(false, true)) {
+			return;
+		}
+		String ip = getPlcIp();
+		S7PLC s7PLC = null;
+		try {
+			s7PLC = new S7PLC(EPlcType.S1200, ip);
+			handleScanFeedback(s7PLC);
+			handleCollectTrigger(s7PLC);
+		} catch (Exception e) {
+			logger.error("框架气密S7任务失败[{}]:{}", ip, e.getMessage());
+		} finally {
+			if (s7PLC != null) {
+				try {
+					s7PLC.close();
+				} catch (Exception ignore) {
+				}
+			}
+			running.set(false);
+		}
+	}
+
+	/**
+	 * 扫码反馈为 true:读框架码 → 质量校验 → 通过则写 DB200.0.0=true
+	 */
+	private void handleScanFeedback(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_SCAN_FEEDBACK)) {
+			return;
+		}
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			return;
+		}
+		lastKnownSn = sn;
+		if (sn.equals(lastCheckedSn)) {
+			return;
+		}
+
+		boolean pass = doQualityCheck(sn);
+		if (pass) {
+			s7PLC.writeBoolean(ADDR_QUALITY_PASS, true);
+			logger.info("框架气密质量校验通过 sn={},已写 {}=true", sn, ADDR_QUALITY_PASS);
+		} else {
+			logger.warn("框架气密质量校验未通过 sn={}", sn);
+		}
+		lastCheckedSn = sn;
+	}
+
+	/**
+	 * 采集触发为 true:读过程参数 → 落库 mes_product_qmzc → 提交 OP360 工位结果 → 清触发位
+	 */
+	private void handleCollectTrigger(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_COLLECT_FLAG)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("框架气密采集失败:无工件码,保持 {}=true 待重试", ADDR_COLLECT_FLAG);
+			return;
+		}
+		lastKnownSn = sn;
+
+		float ylbInflationTime = s7PLC.readFloat32(ADDR_YLB_INFLATION_TIME);
+		float ylbTestTime = s7PLC.readFloat32(ADDR_YLB_TEST_TIME);
+		float ylbInflationPressure = s7PLC.readFloat32(ADDR_YLB_INFLATION_PRESSURE);
+		float ylbStablePressure = s7PLC.readFloat32(ADDR_YLB_STABLE_PRESSURE);
+		float ylbLeak = s7PLC.readFloat32(ADDR_YLB_LEAK);
+		float ylbHoldTime = s7PLC.readFloat32(ADDR_YLB_HOLD_TIME);
+
+		float inflationTime = s7PLC.readFloat32(ADDR_INFLATION_TIME);
+		float testTime = s7PLC.readFloat32(ADDR_TEST_TIME);
+		float inflationPressure = s7PLC.readFloat32(ADDR_INFLATION_PRESSURE);
+		float stablePressure = s7PLC.readFloat32(ADDR_STABLE_PRESSURE);
+		float leakAmount = s7PLC.readFloat32(ADDR_LEAK_AMOUNT);
+		float holdTime = s7PLC.readFloat32(ADDR_HOLD_TIME);
+		boolean ylbJudgePass = s7PLC.readBoolean(ADDR_YLB_JUDGE_RESULT);
+		boolean judgePass = s7PLC.readBoolean(ADDR_JUDGE_RESULT);
+		String ylbStationResult = ylbJudgePass ? "OK" : "NG";
+		String stationResult = judgePass ? "OK" : "NG";
+
+		logger.info("框架气密采集 sn={} 液冷板[充气时间={} 测试时间={} 充气压力={} 稳定压力={} 泄漏量={} 保压时间={} 判定={}] "
+						+ "框架[充气时间={} 测试时间={} 充气压力={} 稳定压力={} 泄露量={} 保压时间={} 判定={}]",
+				sn, ylbInflationTime, ylbTestTime, ylbInflationPressure, ylbStablePressure, ylbLeak, ylbHoldTime, ylbStationResult,
+				inflationTime, testTime, inflationPressure, stablePressure, leakAmount, holdTime, stationResult);
+
+		if (!saveQmzcData(ylbInflationTime, ylbTestTime, ylbInflationPressure, ylbStablePressure, ylbLeak, ylbHoldTime,
+				inflationTime, testTime, inflationPressure, stablePressure, leakAmount, holdTime,
+				ylbStationResult, stationResult)) {
+			logger.error("框架气密数据保存失败,保持 {}=true 待重试 sn={}", ADDR_COLLECT_FLAG, sn);
+			return;
+		}
+		if (!submitStationResult(sn, stationResult)) {
+			logger.error("框架气密工位结果提交失败,保持 {}=true 待重试 sn={}", ADDR_COLLECT_FLAG, sn);
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_COLLECT_FLAG, false);
+		logger.info("框架气密采集完成 sn={} result={},已将 {} 置 false", sn, stationResult, ADDR_COLLECT_FLAG);
+	}
+
+	private boolean saveQmzcData(float ylbInflationTime, float ylbTestTime, float ylbInflationPressure,
+			float ylbStablePressure, float ylbLeak, float ylbHoldTime,
+			float inflationTime, float testTime, float inflationPressure, float stablePressure,
+			float leakAmount, float holdTime, String ylbStationResult, String stationResult) {
+		try {
+			MesProductQmzc entity = new MesProductQmzc();
+			entity.setYlbCqsj(fmt(ylbInflationTime));
+			entity.setYlbCssj(fmt(ylbTestTime));
+			entity.setYlbCqyl(fmt(ylbInflationPressure));
+			entity.setYlbWdyl(fmt(ylbStablePressure));
+			entity.setYlbLeak(fmt(ylbLeak));
+			entity.setYlbBysj(fmt(ylbHoldTime));
+			entity.setYlbResult(ylbStationResult);
+			entity.setCqsj(fmt(inflationTime));
+			entity.setCssj(fmt(testTime));
+			entity.setCqya(fmt(inflationPressure));
+			entity.setWdyl(fmt(stablePressure));
+			entity.setLeak(fmt(leakAmount));
+			entity.setBysj(fmt(holdTime));
+			entity.setResult(stationResult);
+			mesProductQmzcService.save(entity);
+			return true;
+		} catch (Exception e) {
+			logger.error("框架气密数据保存异常:{}", e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean submitStationResult(String sn, String result) {
+		try {
+			String oprno = getOprno();
+			if (oprno.length() == 5) {
+				oprno = oprno + "A";
+			}
+			String lineSn = getLineSn(sn);
+			if (StringUtils.isBlank(lineSn)) {
+				logger.warn("框架气密工位结果提交失败:无法解析产线编号 sn={}", sn);
+				return false;
+			}
+			List<ParamsResp> params = new ArrayList<>();
+			List<BindMaterialResp> bmlists = new ArrayList<>();
+			mesProductRecordService.updateRecordResult(sn, oprno, "100000", "", result,
+					"", params, lineSn, true, bmlists, null);
+			logger.info("框架气密工位结果已提交 sn={} oprno={} result={}", sn, oprno, result);
+			return true;
+		} catch (Exception e) {
+			logger.error("框架气密工位结果提交异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean doQualityCheck(String sn) {
+		String oprno = getOprno();
+		String oldOprno = oprno.length() == 5 ? oprno + "A" : oprno;
+		String lineSn = getLineSn(sn);
+		if (StringUtils.isBlank(lineSn)) {
+			logger.warn("框架气密质量校验失败:无法解析产线编号 sn={}", sn);
+			return false;
+		}
+		try {
+			String ret = mesProductRecordController.checkQualityCommon(oldOprno, sn, lineSn, "");
+			if (StringUtils.isBlank(ret) || ret.length() < 5) {
+				return false;
+			}
+			return "UD".equals(ret.substring(3, 5));
+		} catch (Exception e) {
+			logger.error("框架气密质量校验异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private String getLineSn(String sn) {
+		String lineSn = Global.getConfig("mes.framework.qm.lineSn");
+		if (StringUtils.isNotBlank(lineSn)) {
+			return lineSn.trim();
+		}
+		MesProduct product = mesProductService.findBySn(sn);
+		if (ObjectUtils.isEmpty(product) || StringUtils.isBlank(product.getCate())) {
+			return DEFAULT_LINE_SN;
+		}
+		MesLine query = new MesLine();
+		query.setProductCate(product.getCate());
+		query.setStatus("0");
+		MesLine line = mesLineService.findInfo(query);
+		if (ObjectUtils.isEmpty(line) || StringUtils.isBlank(line.getSn())) {
+			return DEFAULT_LINE_SN;
+		}
+		return line.getSn();
+	}
+
+	private String readWorkpieceCode(S7PLC s7PLC) {
+		String raw = s7PLC.readString(ADDR_SN, SN_LENGTH);
+		if (StringUtils.isBlank(raw)) {
+			return null;
+		}
+		StringBuilder sb = new StringBuilder(raw.length());
+		for (int i = 0; i < raw.length(); i++) {
+			char c = raw.charAt(i);
+			if (c == 0 || c == ' ') {
+				continue;
+			}
+			if (c >= 32 && c < 127) {
+				sb.append(c);
+			}
+		}
+		return sb.toString().trim();
+	}
+
+	private String getPlcIp() {
+		String ip = Global.getConfig("mes.framework.qm.plc.ip");
+		return StringUtils.isBlank(ip) ? DEFAULT_PLC_IP : ip.trim();
+	}
+
+	private String getOprno() {
+		String oprno = Global.getConfig("mes.framework.qm.oprno");
+		return StringUtils.isBlank(oprno) ? DEFAULT_OPRNO : oprno.trim();
+	}
+
+	private static String fmt(float val) {
+		return String.format("%.3f", val);
+	}
+}

+ 322 - 0
src/main/java/com/jeesite/modules/scheduling/ProductTjBScheduling.java

@@ -0,0 +1,322 @@
+package com.jeesite.modules.scheduling;
+
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+import com.jeesite.common.config.Global;
+import com.jeesite.common.lang.ObjectUtils;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.modules.mes.entity.MesLine;
+import com.jeesite.modules.mes.entity.MesProduct;
+import com.jeesite.modules.mes.entity.MesProductTj;
+import com.jeesite.modules.mes.resp.BindMaterialResp;
+import com.jeesite.modules.mes.resp.ParamsResp;
+import com.jeesite.modules.mes.service.MesLineService;
+import com.jeesite.modules.mes.service.MesProductRecordService;
+import com.jeesite.modules.mes.service.MesProductService;
+import com.jeesite.modules.mes.service.MesProductTjService;
+import com.jeesite.modules.mes.web.MesProductRecordController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 涂胶 S7 采集与质量握手(OP240B)。
+ * <pre>
+ * DB1300 点位:
+ *   32.0   框架码 String[30]
+ *   64.1   扫码反馈信号
+ *   64.3   质量校验通过反馈(校验通过 MES 写 true,工位完成后 MES 写 false)
+ *   64.5   整体完成信号
+ *   74.0   涂胶数据采集触发
+ *   76.0   涂胶序号 Word
+ *   78.0   涂胶速度 Real
+ *   82.0   涂胶长度 Word
+ *
+ * 配置(application.yml):
+ *   mes.tj.b.enabled       是否启用(默认 false)
+ *   mes.tj.b.plc.ip        PLC IP,默认 10.0.40.100
+ *   mes.tj.b.oprno         工位号,默认 OP240B
+ *   mes.tj.b.lineSn        产线编号,默认 XT
+ * </pre>
+ */
+@Configuration
+@EnableScheduling
+public class ProductTjBScheduling {
+
+	private static final Logger logger = LoggerFactory.getLogger(ProductTjBScheduling.class);
+
+	private static final String ADDR_SN = "DB1300.32.0";
+	private static final int SN_LENGTH = 30;
+	private static final String ADDR_SCAN_FEEDBACK = "DB1300.64.1";
+	private static final String ADDR_QUALITY_PASS = "DB1300.64.3";
+	private static final String ADDR_COMPLETE = "DB1300.64.5";
+	private static final String ADDR_GLUE_COLLECT = "DB1300.74.0";
+	private static final String ADDR_GLUE_SEQ = "DB1300.76.0";
+	private static final String ADDR_GLUE_SPEED = "DB1300.78.0";
+	private static final String ADDR_GLUE_LENGTH = "DB1300.82.0";
+
+	private static final String DEFAULT_PLC_IP = "10.0.40.100";
+	private static final String DEFAULT_OPRNO = "OP240B";
+	private static final String DEFAULT_LINE_SN = "XT";
+
+	@Autowired
+	private MesProductRecordController mesProductRecordController;
+	@Autowired
+	private MesProductService mesProductService;
+	@Autowired
+	private MesLineService mesLineService;
+	@Autowired
+	private MesProductTjService mesProductTjService;
+	@Autowired
+	private MesProductRecordService mesProductRecordService;
+
+	private final AtomicBoolean running = new AtomicBoolean(false);
+	private volatile String lastCheckedSn;
+	private volatile String lastKnownSn;
+	private volatile String lastCompletedSn;
+
+	@Scheduled(fixedRate = 1000)
+	public void collect() {
+		String enabled = Global.getConfig("mes.tj.b.enabled");
+		if (StringUtils.isBlank(enabled) || !"true".equalsIgnoreCase(enabled.trim())) {
+			return;
+		}
+		runOnce();
+	}
+
+	/**
+	 * 直接执行一轮(供测试调用)
+	 */
+	public void runOnce() {
+		if (!running.compareAndSet(false, true)) {
+			return;
+		}
+		String ip = getPlcIp();
+		S7PLC s7PLC = null;
+		try {
+			s7PLC = new S7PLC(EPlcType.S1200, ip);
+			handleScanFeedback(s7PLC);
+			handleGlueCollect(s7PLC);
+			handleComplete(s7PLC);
+		} catch (Exception e) {
+			logger.error("涂胶B S7任务失败[{}]:{}", ip, e.getMessage());
+		} finally {
+			if (s7PLC != null) {
+				try {
+					s7PLC.close();
+				} catch (Exception ignore) {
+				}
+			}
+			running.set(false);
+		}
+	}
+
+	/**
+	 * 扫码反馈为 true:读框架码 → 质量校验 → 通过则写 DB1300.64.3=true
+	 */
+	private void handleScanFeedback(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_SCAN_FEEDBACK)) {
+			lastCheckedSn = null;
+			lastCompletedSn = null;
+			return;
+		}
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			return;
+		}
+		lastKnownSn = sn;
+		if (sn.equals(lastCheckedSn)) {
+			return;
+		}
+
+		boolean pass = doQualityCheck(sn);
+		if (pass) {
+			s7PLC.writeBoolean(ADDR_QUALITY_PASS, true);
+			logger.info("涂胶B质量校验通过 sn={},已写 {}=true", sn, ADDR_QUALITY_PASS);
+		} else {
+			logger.warn("涂胶B质量校验未通过 sn={}", sn);
+		}
+		lastCheckedSn = sn;
+	}
+
+	/**
+	 * 涂胶采集触发为 true:读涂胶参数 → 落库 mes_product_tj → 清触发位
+	 */
+	private void handleGlueCollect(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_GLUE_COLLECT)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("涂胶B数据采集失败:无工件码,保持 {}=true 待重试", ADDR_GLUE_COLLECT);
+			return;
+		}
+		lastKnownSn = sn;
+
+		int glueSeq = s7PLC.readUInt16(ADDR_GLUE_SEQ);
+		float glueSpeed = s7PLC.readFloat32(ADDR_GLUE_SPEED);
+		int glueLength = s7PLC.readUInt16(ADDR_GLUE_LENGTH);
+
+		logger.info("涂胶B数据采集 sn={} 序号={} 速度={} 长度={}", sn, glueSeq, glueSpeed, glueLength);
+
+		if (!saveTjData(sn, glueSeq, glueSpeed, glueLength)) {
+			logger.error("涂胶B数据保存失败,保持 {}=true 待重试 sn={}", ADDR_GLUE_COLLECT, sn);
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_GLUE_COLLECT, false);
+		logger.info("涂胶B数据采集完成 sn={} 序号={},已将 {} 置 false", sn, glueSeq, ADDR_GLUE_COLLECT);
+	}
+
+	/**
+	 * 整体完成信号为 true:提交 OP240B 工位 OK → 成功后将 DB1300.64.3 置 false
+	 */
+	private void handleComplete(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_COMPLETE)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("涂胶B工位完成提交失败:无工件码,保持 {}=true 待重试", ADDR_COMPLETE);
+			return;
+		}
+		if (sn.equals(lastCompletedSn)) {
+			return;
+		}
+
+		if (!submitStationResult(sn, "OK")) {
+			logger.error("涂胶B工位结果提交失败,保持信号待重试 sn={}", sn);
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_QUALITY_PASS, false);
+		lastCompletedSn = sn;
+		lastCheckedSn = null;
+		logger.info("涂胶B工位完成 sn={},已提交 OK 并将 {} 置 false", sn, ADDR_QUALITY_PASS);
+	}
+
+	private boolean saveTjData(String sn, int glueSeq, float glueSpeed, int glueLength) {
+		try {
+			MesProductTj entity = new MesProductTj();
+			entity.setSn(sn);
+			entity.setOprno(getOprno());
+			entity.setTjData(String.valueOf(glueSeq));
+			entity.setTjSpeed(fmt(glueSpeed));
+			entity.setTjLength(String.valueOf(glueLength));
+			mesProductTjService.save(entity);
+			return true;
+		} catch (Exception e) {
+			logger.error("涂胶B数据保存异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean submitStationResult(String sn, String result) {
+		try {
+			String oprno = getOprno();
+			if (oprno.length() == 5) {
+				oprno = oprno + "A";
+			}
+			String lineSn = getLineSn(sn);
+			if (StringUtils.isBlank(lineSn)) {
+				logger.warn("涂胶B工位结果提交失败:无法解析产线编号 sn={}", sn);
+				return false;
+			}
+			List<ParamsResp> params = new ArrayList<>();
+			List<BindMaterialResp> bmlists = new ArrayList<>();
+			mesProductRecordService.updateRecordResult(sn, oprno, "100000", "", result,
+					"", params, lineSn, true, bmlists, null);
+			logger.info("涂胶B工位结果已提交 sn={} oprno={} result={}", sn, oprno, result);
+			return true;
+		} catch (Exception e) {
+			logger.error("涂胶B工位结果提交异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean doQualityCheck(String sn) {
+		String oprno = getOprno();
+		String checkOprno = oprno.length() == 5 ? oprno + "A" : oprno;
+		String lineSn = getLineSn(sn);
+		if (StringUtils.isBlank(lineSn)) {
+			logger.warn("涂胶B质量校验失败:无法解析产线编号 sn={}", sn);
+			return false;
+		}
+		try {
+			String ret = mesProductRecordController.checkQualityCommon(checkOprno, sn, lineSn, "");
+			if (StringUtils.isBlank(ret) || ret.length() < 5) {
+				return false;
+			}
+			return "UD".equals(ret.substring(3, 5));
+		} catch (Exception e) {
+			logger.error("涂胶B质量校验异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private String getLineSn(String sn) {
+		String lineSn = Global.getConfig("mes.tj.b.lineSn");
+		if (StringUtils.isNotBlank(lineSn)) {
+			return lineSn.trim();
+		}
+		MesProduct product = mesProductService.findBySn(sn);
+		if (ObjectUtils.isEmpty(product) || StringUtils.isBlank(product.getCate())) {
+			return DEFAULT_LINE_SN;
+		}
+		MesLine query = new MesLine();
+		query.setProductCate(product.getCate());
+		query.setStatus("0");
+		MesLine line = mesLineService.findInfo(query);
+		if (ObjectUtils.isEmpty(line) || StringUtils.isBlank(line.getSn())) {
+			return DEFAULT_LINE_SN;
+		}
+		return line.getSn();
+	}
+
+	private String readWorkpieceCode(S7PLC s7PLC) {
+		String raw = s7PLC.readString(ADDR_SN, SN_LENGTH);
+		if (StringUtils.isBlank(raw)) {
+			return null;
+		}
+		StringBuilder sb = new StringBuilder(raw.length());
+		for (int i = 0; i < raw.length(); i++) {
+			char c = raw.charAt(i);
+			if (c == 0 || c == ' ') {
+				continue;
+			}
+			if (c >= 32 && c < 127) {
+				sb.append(c);
+			}
+		}
+		return sb.toString().trim();
+	}
+
+	private String getPlcIp() {
+		String ip = Global.getConfig("mes.tj.b.plc.ip");
+		return StringUtils.isBlank(ip) ? DEFAULT_PLC_IP : ip.trim();
+	}
+
+	private String getOprno() {
+		String oprno = Global.getConfig("mes.tj.b.oprno");
+		return StringUtils.isBlank(oprno) ? DEFAULT_OPRNO : oprno.trim();
+	}
+
+	private static String fmt(float val) {
+		return String.format("%.3f", val);
+	}
+}

+ 322 - 0
src/main/java/com/jeesite/modules/scheduling/ProductTjScheduling.java

@@ -0,0 +1,322 @@
+package com.jeesite.modules.scheduling;
+
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+import com.jeesite.common.config.Global;
+import com.jeesite.common.lang.ObjectUtils;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.modules.mes.entity.MesLine;
+import com.jeesite.modules.mes.entity.MesProduct;
+import com.jeesite.modules.mes.entity.MesProductTj;
+import com.jeesite.modules.mes.resp.BindMaterialResp;
+import com.jeesite.modules.mes.resp.ParamsResp;
+import com.jeesite.modules.mes.service.MesLineService;
+import com.jeesite.modules.mes.service.MesProductRecordService;
+import com.jeesite.modules.mes.service.MesProductService;
+import com.jeesite.modules.mes.service.MesProductTjService;
+import com.jeesite.modules.mes.web.MesProductRecordController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 涂胶 S7 采集与质量握手(OP240)。
+ * <pre>
+ * DB1300 点位:
+ *   0.0    框架码 String[30]
+ *   64.0   扫码反馈信号
+ *   64.2   质量校验通过反馈(校验通过 MES 写 true,工位完成后 MES 写 false)
+ *   64.4   涂胶数据采集触发
+ *   64.5   整体完成信号
+ *   66.0   涂胶序号 Word
+ *   68.0   涂胶速度 Real
+ *   72.0   涂胶长度 Word
+ *
+ * 配置(application.yml):
+ *   mes.tj.enabled       是否启用(默认 false)
+ *   mes.tj.plc.ip        PLC IP,默认 10.0.40.100
+ *   mes.tj.oprno         工位号,默认 OP240
+ *   mes.tj.lineSn        产线编号,默认 XT
+ * </pre>
+ */
+@Configuration
+@EnableScheduling
+public class ProductTjScheduling {
+
+	private static final Logger logger = LoggerFactory.getLogger(ProductTjScheduling.class);
+
+	private static final String ADDR_SN = "DB1300.0.0";
+	private static final int SN_LENGTH = 30;
+	private static final String ADDR_SCAN_FEEDBACK = "DB1300.64.0";
+	private static final String ADDR_QUALITY_PASS = "DB1300.64.2";
+	private static final String ADDR_GLUE_COLLECT = "DB1300.64.4";
+	private static final String ADDR_COMPLETE = "DB1300.64.5";
+	private static final String ADDR_GLUE_SEQ = "DB1300.66.0";
+	private static final String ADDR_GLUE_SPEED = "DB1300.68.0";
+	private static final String ADDR_GLUE_LENGTH = "DB1300.72.0";
+
+	private static final String DEFAULT_PLC_IP = "10.0.40.100";
+	private static final String DEFAULT_OPRNO = "OP240";
+	private static final String DEFAULT_LINE_SN = "XT";
+
+	@Autowired
+	private MesProductRecordController mesProductRecordController;
+	@Autowired
+	private MesProductService mesProductService;
+	@Autowired
+	private MesLineService mesLineService;
+	@Autowired
+	private MesProductTjService mesProductTjService;
+	@Autowired
+	private MesProductRecordService mesProductRecordService;
+
+	private final AtomicBoolean running = new AtomicBoolean(false);
+	private volatile String lastCheckedSn;
+	private volatile String lastKnownSn;
+	private volatile String lastCompletedSn;
+
+	@Scheduled(fixedRate = 1000)
+	public void collect() {
+		String enabled = Global.getConfig("mes.tj.enabled");
+		if (StringUtils.isBlank(enabled) || !"true".equalsIgnoreCase(enabled.trim())) {
+			return;
+		}
+		runOnce();
+	}
+
+	/**
+	 * 直接执行一轮(供测试调用)
+	 */
+	public void runOnce() {
+		if (!running.compareAndSet(false, true)) {
+			return;
+		}
+		String ip = getPlcIp();
+		S7PLC s7PLC = null;
+		try {
+			s7PLC = new S7PLC(EPlcType.S1200, ip);
+			handleScanFeedback(s7PLC);
+			handleGlueCollect(s7PLC);
+			handleComplete(s7PLC);
+		} catch (Exception e) {
+			logger.error("涂胶S7任务失败[{}]:{}", ip, e.getMessage());
+		} finally {
+			if (s7PLC != null) {
+				try {
+					s7PLC.close();
+				} catch (Exception ignore) {
+				}
+			}
+			running.set(false);
+		}
+	}
+
+	/**
+	 * 扫码反馈为 true:读框架码 → 质量校验 → 通过则写 DB1300.64.2=true
+	 */
+	private void handleScanFeedback(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_SCAN_FEEDBACK)) {
+			lastCheckedSn = null;
+			lastCompletedSn = null;
+			return;
+		}
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			return;
+		}
+		lastKnownSn = sn;
+		if (sn.equals(lastCheckedSn)) {
+			return;
+		}
+
+		boolean pass = doQualityCheck(sn);
+		if (pass) {
+			s7PLC.writeBoolean(ADDR_QUALITY_PASS, true);
+			logger.info("涂胶质量校验通过 sn={},已写 {}=true", sn, ADDR_QUALITY_PASS);
+		} else {
+			logger.warn("涂胶质量校验未通过 sn={}", sn);
+		}
+		lastCheckedSn = sn;
+	}
+
+	/**
+	 * 涂胶采集触发为 true:读涂胶参数 → 落库 mes_product_tj → 清触发位
+	 */
+	private void handleGlueCollect(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_GLUE_COLLECT)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("涂胶数据采集失败:无工件码,保持 {}=true 待重试", ADDR_GLUE_COLLECT);
+			return;
+		}
+		lastKnownSn = sn;
+
+		int glueSeq = s7PLC.readUInt16(ADDR_GLUE_SEQ);
+		float glueSpeed = s7PLC.readFloat32(ADDR_GLUE_SPEED);
+		int glueLength = s7PLC.readUInt16(ADDR_GLUE_LENGTH);
+
+		logger.info("涂胶数据采集 sn={} 序号={} 速度={} 长度={}", sn, glueSeq, glueSpeed, glueLength);
+
+		if (!saveTjData(sn, glueSeq, glueSpeed, glueLength)) {
+			logger.error("涂胶数据保存失败,保持 {}=true 待重试 sn={}", ADDR_GLUE_COLLECT, sn);
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_GLUE_COLLECT, false);
+		logger.info("涂胶数据采集完成 sn={} 序号={},已将 {} 置 false", sn, glueSeq, ADDR_GLUE_COLLECT);
+	}
+
+	/**
+	 * 整体完成信号为 true:提交 OP240 工位 OK → 成功后将 DB1300.64.2 置 false
+	 */
+	private void handleComplete(S7PLC s7PLC) {
+		if (!s7PLC.readBoolean(ADDR_COMPLETE)) {
+			return;
+		}
+
+		String sn = readWorkpieceCode(s7PLC);
+		if (StringUtils.isBlank(sn)) {
+			sn = lastKnownSn;
+		}
+		if (StringUtils.isBlank(sn)) {
+			logger.error("涂胶工位完成提交失败:无工件码,保持 {}=true 待重试", ADDR_COMPLETE);
+			return;
+		}
+		if (sn.equals(lastCompletedSn)) {
+			return;
+		}
+
+		if (!submitStationResult(sn, "OK")) {
+			logger.error("涂胶工位结果提交失败,保持信号待重试 sn={}", sn);
+			return;
+		}
+
+		s7PLC.writeBoolean(ADDR_QUALITY_PASS, false);
+		lastCompletedSn = sn;
+		lastCheckedSn = null;
+		logger.info("涂胶工位完成 sn={},已提交 OK 并将 {} 置 false", sn, ADDR_QUALITY_PASS);
+	}
+
+	private boolean saveTjData(String sn, int glueSeq, float glueSpeed, int glueLength) {
+		try {
+			MesProductTj entity = new MesProductTj();
+			entity.setSn(sn);
+			entity.setOprno(getOprno());
+			entity.setTjData(String.valueOf(glueSeq));
+			entity.setTjSpeed(fmt(glueSpeed));
+			entity.setTjLength(String.valueOf(glueLength));
+			mesProductTjService.save(entity);
+			return true;
+		} catch (Exception e) {
+			logger.error("涂胶数据保存异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean submitStationResult(String sn, String result) {
+		try {
+			String oprno = getOprno();
+			if (oprno.length() == 5) {
+				oprno = oprno + "A";
+			}
+			String lineSn = getLineSn(sn);
+			if (StringUtils.isBlank(lineSn)) {
+				logger.warn("涂胶工位结果提交失败:无法解析产线编号 sn={}", sn);
+				return false;
+			}
+			List<ParamsResp> params = new ArrayList<>();
+			List<BindMaterialResp> bmlists = new ArrayList<>();
+			mesProductRecordService.updateRecordResult(sn, oprno, "100000", "", result,
+					"", params, lineSn, true, bmlists, null);
+			logger.info("涂胶工位结果已提交 sn={} oprno={} result={}", sn, oprno, result);
+			return true;
+		} catch (Exception e) {
+			logger.error("涂胶工位结果提交异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private boolean doQualityCheck(String sn) {
+		String oprno = getOprno();
+		String oldOprno = oprno.length() == 5 ? oprno + "A" : oprno;
+		String lineSn = getLineSn(sn);
+		if (StringUtils.isBlank(lineSn)) {
+			logger.warn("涂胶质量校验失败:无法解析产线编号 sn={}", sn);
+			return false;
+		}
+		try {
+			String ret = mesProductRecordController.checkQualityCommon(oldOprno, sn, lineSn, "");
+			if (StringUtils.isBlank(ret) || ret.length() < 5) {
+				return false;
+			}
+			return "UD".equals(ret.substring(3, 5));
+		} catch (Exception e) {
+			logger.error("涂胶质量校验异常 sn={}:{}", sn, e.getMessage());
+			return false;
+		}
+	}
+
+	private String getLineSn(String sn) {
+		String lineSn = Global.getConfig("mes.tj.lineSn");
+		if (StringUtils.isNotBlank(lineSn)) {
+			return lineSn.trim();
+		}
+		MesProduct product = mesProductService.findBySn(sn);
+		if (ObjectUtils.isEmpty(product) || StringUtils.isBlank(product.getCate())) {
+			return DEFAULT_LINE_SN;
+		}
+		MesLine query = new MesLine();
+		query.setProductCate(product.getCate());
+		query.setStatus("0");
+		MesLine line = mesLineService.findInfo(query);
+		if (ObjectUtils.isEmpty(line) || StringUtils.isBlank(line.getSn())) {
+			return DEFAULT_LINE_SN;
+		}
+		return line.getSn();
+	}
+
+	private String readWorkpieceCode(S7PLC s7PLC) {
+		String raw = s7PLC.readString(ADDR_SN, SN_LENGTH);
+		if (StringUtils.isBlank(raw)) {
+			return null;
+		}
+		StringBuilder sb = new StringBuilder(raw.length());
+		for (int i = 0; i < raw.length(); i++) {
+			char c = raw.charAt(i);
+			if (c == 0 || c == ' ') {
+				continue;
+			}
+			if (c >= 32 && c < 127) {
+				sb.append(c);
+			}
+		}
+		return sb.toString().trim();
+	}
+
+	private String getPlcIp() {
+		String ip = Global.getConfig("mes.tj.plc.ip");
+		return StringUtils.isBlank(ip) ? DEFAULT_PLC_IP : ip.trim();
+	}
+
+	private String getOprno() {
+		String oprno = Global.getConfig("mes.tj.oprno");
+		return StringUtils.isBlank(oprno) ? DEFAULT_OPRNO : oprno.trim();
+	}
+
+	private static String fmt(float val) {
+		return String.format("%.3f", val);
+	}
+}

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

@@ -1111,3 +1111,25 @@ mes:
       unitId: 1
       oprno:          # 工位号,必填,例如 OP210A
       lineSn:         # 产线编号,可空(空则按工件类型自动解析)
+  # 框架气密 S7 采集(OP360)
+  framework:
+    qm:
+      enabled: true
+      plc:
+        ip: 192.168.1.100
+      oprno: OP360
+      lineSn: XT
+  # 涂胶 S7 采集(OP240)
+  tj:
+    enabled: true
+    plc:
+      ip: 10.0.40.100
+    oprno: OP240
+    lineSn: XT
+    # 涂胶 S7 采集(OP240B)
+    b:
+      enabled: true
+      plc:
+        ip: 10.0.40.100
+      oprno: OP240B
+      lineSn: XT

+ 15 - 0
src/main/resources/mappings/modules/mes/MesProductQmzcDao.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeesite.modules.mes.dao.MesProductQmzcDao">
+	
+	<!-- 查询数据
+	<select id="findList" resultType="MesProductQmzc">
+		SELECT ${sqlMap.column.toSql()}
+		FROM ${sqlMap.table.toSql()}
+		<where>
+			${sqlMap.where.toSql()}
+		</where>
+		ORDER BY ${sqlMap.order.toSql()}
+	</select> -->
+	
+</mapper>

+ 69 - 0
src/main/resources/views/modules/mes/mesProductCmtDataDetail.html

@@ -0,0 +1,69 @@
+<% layout('/layouts/default.html', {title: 'CMT过程参数详情', libs: []}){ %>
+<style>
+	.table.table-bordered th.mpc-header { width: 140px; background: #f9f9f9; }
+	.param-table th { white-space: nowrap; background: #f5f5f5; text-align: center; }
+	.param-table td { text-align: center; word-break: break-all; }
+</style>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header with-border">
+			<div class="box-title">
+				<i class="fa icon-eye"></i> ${text('CMT过程参数详情')}
+			</div>
+			<div class="box-tools pull-right">
+				<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
+			</div>
+		</div>
+		<div class="box-body">
+			<div class="form-unit">${text('基本信息')}</div>
+			<table class="table table-bordered">
+				<tr>
+					<th class="mpc-header">${text('工件码')}</th>
+					<td>${mesProductCmtData.sn}</td>
+					<th class="mpc-header">${text('工位号')}</th>
+					<td>${mesProductCmtData.oprno}</td>
+				</tr>
+				<tr>
+					<th class="mpc-header">${text('创建时间')}</th>
+					<td colspan="3">${@DateUtils.formatDateTime(mesProductCmtData.createDate)}</td>
+				</tr>
+			</table>
+
+			<div class="form-unit">${text('过程参数明细')}</div>
+			<% if(detailRows == null || detailRows.~size == 0){ %>
+				<div class="alert alert-info" style="margin:0;">${text('暂无参数数据')}</div>
+			<% } else { %>
+				<div style="overflow-x:auto;">
+					<table class="table table-bordered param-table">
+						<thead>
+							<tr>
+								<th style="width:80px;">${text('序号')}</th>
+								<th>${text('送丝速度')}</th>
+								<th>${text('电流')}</th>
+								<th>${text('电压')}</th>
+							</tr>
+						</thead>
+						<tbody>
+							<% for(var row in detailRows){ %>
+							<tr>
+								<td>${rowLP.index}</td>
+								<td>${row.ssSpeed != null && row.ssSpeed != '' ? row.ssSpeed : '-'}</td>
+								<td>${row.current != null && row.current != '' ? row.current : '-'}</td>
+								<td>${row.voltage != null && row.voltage != '' ? row.voltage : '-'}</td>
+							</tr>
+							<% } %>
+						</tbody>
+					</table>
+				</div>
+			<% } %>
+		</div>
+		<div class="box-footer">
+			<div class="row">
+				<div class="col-sm-offset-2 col-sm-10">
+					<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="js.closeCurrentTabPage()"><i class="fa fa-reply-all"></i> ${text('关 闭')}</button>
+				</div>
+			</div>
+		</div>
+	</div>
+</div>
+<% } %>

+ 8 - 6
src/main/resources/views/modules/mes/mesProductCmtDataList.html

@@ -62,15 +62,17 @@
 $('#dataGrid').dataGrid({
 	searchForm: $("#searchForm"),
 	columnModel: [
-		{header:'${text("工件码")}', name:'sn', index:'a.sn', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
-			return '<a href="${ctx}/mes/mesProductCmtData/form?id='+row.id+'" class="btnList" data-title="${text("编辑cmt过程参数表")}">'+(val||row.id)+'</a>';
+		{header:'${text("工件码")}', name:'sn', index:'a.sn', width:220, align:"left", frozen:true, formatter: function(val, obj, row, act){
+			return '<a href="${ctx}/mes/mesProductCmtData/detail?id='+row.id+'" class="btnList" data-title="${text("CMT过程参数详情")}">'+(val||row.id)+'</a>';
 		}},
-		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:150, align:"left"},
-		{header:'${text("送丝速度")}', name:'ssSpeed', index:'a.ss_speed', width:150, align:"left"},
-		{header:'${text("电流")}', name:'current', index:'a.current', width:150, align:"left"},
-		{header:'${text("电压")}', name:'voltage', index:'a.voltage', width:150, align:"left"},
+		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:120, align:"left"},
+		{header:'${text("送丝速度")}', name:'ssSpeed', index:'a.ss_speed', width:180, align:"left"},
+		{header:'${text("电流")}', name:'current', index:'a.current', width:180, align:"left"},
+		{header:'${text("电压")}', name:'voltage', index:'a.voltage', width:180, align:"left"},
+		{header:'${text("创建时间")}', name:'createDate', index:'a.create_date', width:150, align:"center"},
 		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
 			var actions = [];
+			actions.push('<a href="${ctx}/mes/mesProductCmtData/detail?id='+row.id+'" class="btnList" title="${text("详情")}"><i class="fa fa-fw fa-eye"></i></a>&nbsp;');
 			//<% if(hasPermi('mes:mesProductCmtData:edit')){ %>
 				actions.push('<a href="${ctx}/mes/mesProductCmtData/form?id='+row.id+'" class="btnList" title="${text("编辑cmt过程参数表")}"><i class="fa fa-pencil"></i></a>&nbsp;');
 				actions.push('<a href="${ctx}/mes/mesProductCmtData/delete?id='+row.id+'" class="btnList" title="${text("删除cmt过程参数表")}" data-confirm="${text("确认要删除该cmt过程参数表吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');

+ 172 - 0
src/main/resources/views/modules/mes/mesProductQmzcForm.html

@@ -0,0 +1,172 @@
+<% layout('/layouts/default.html', {title: '总成气密数据表管理', libs: ['validate']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header with-border">
+			<div class="box-title">
+				<i class="fa icon-note"></i> ${text(mesProductQmzc.isNewRecord ? '新增总成气密数据表' : '编辑总成气密数据表')}
+			</div>
+			<div class="box-tools pull-right">
+				<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
+			</div>
+		</div>
+		<#form:form id="inputForm" model="${mesProductQmzc}" action="${ctx}/mes/mesProductQmzc/save" method="post" class="form-horizontal">
+			<div class="box-body">
+				<div class="form-unit">${text('基本信息')}</div>
+				<#form:hidden path="id"/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('液冷板充气时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbCqsj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('液冷板测试时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbCssj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('液冷板充气压力')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbCqyl" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('液冷板稳定压力')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbWdyl" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('液冷板泄漏里')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbLeak" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('夜冷板保压时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbBysj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架架充气时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="cqsj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架测试时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="cssj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架充气压力')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="cqya" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架稳定压力')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="wdyl" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架泄漏里')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="leak" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架保压时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="bysj" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('框架测试结果')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="result" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('水冷板测试结果')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="ylbResult" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div class="box-footer">
+				<div class="row">
+					<div class="col-sm-offset-2 col-sm-10">
+						<% if (hasPermi('mes:mesProductQmzc:edit')){ %>
+							<button type="submit" class="btn btn-sm btn-primary" id="btnSubmit"><i class="fa fa-check"></i> ${text('保 存')}</button>&nbsp;
+						<% } %>
+						<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="js.closeCurrentTabPage()"><i class="fa fa-reply-all"></i> ${text('关 闭')}</button>
+					</div>
+				</div>
+			</div>
+		</#form:form>
+	</div>
+</div>
+<% } %>
+<script>
+$("#inputForm").validate({
+	submitHandler: function(form){
+		js.ajaxSubmitForm($(form), function(data){
+			js.showMessage(data.message);
+			if(data.result == Global.TRUE){
+				js.closeCurrentTabPage(function(contentWindow){
+					contentWindow.page();
+				});
+			}
+		}, "json");
+    }
+});
+</script>

+ 149 - 0
src/main/resources/views/modules/mes/mesProductQmzcList.html

@@ -0,0 +1,149 @@
+<% layout('/layouts/default.html', {title: '总成气密数据表管理', libs: ['dataGrid']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header">
+			<div class="box-title">
+				<i class="fa icon-notebook"></i> ${text('总成气密数据表管理')}
+			</div>
+			<div class="box-tools pull-right">
+				<a href="#" class="btn btn-default" id="btnSearch" title="${text('查询')}"><i class="fa fa-filter"></i> ${text('查询')}</a>
+				<% if(hasPermi('mes:mesProductQmzc:edit')){ %>
+					<a href="${ctx}/mes/mesProductQmzc/form" class="btn btn-default btnTool" title="${text('新增总成气密数据表')}"><i class="fa fa-plus"></i> ${text('新增')}</a>
+				<% } %>
+				<a href="#" class="btn btn-default" id="btnSetting" title="${text('设置')}"><i class="fa fa-navicon"></i></a>
+			</div>
+		</div>
+		<div class="box-body">
+			<#form:form id="searchForm" model="${mesProductQmzc}" action="${ctx}/mes/mesProductQmzc/listData" method="post" class="form-inline hide"
+					data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
+				<div class="form-group">
+					<label class="control-label">${text('液冷板充气时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbCqsj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('液冷板测试时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbCssj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('液冷板充气压力')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbCqyl" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('液冷板稳定压力')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbWdyl" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('液冷板泄漏里')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbLeak" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('夜冷板保压时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbBysj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架架充气时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="cqsj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架测试时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="cssj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架充气压力')}:</label>
+					<div class="control-inline">
+						<#form:input path="cqya" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架稳定压力')}:</label>
+					<div class="control-inline">
+						<#form:input path="wdyl" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架泄漏里')}:</label>
+					<div class="control-inline">
+						<#form:input path="leak" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架保压时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="bysj" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('框架测试结果')}:</label>
+					<div class="control-inline">
+						<#form:input path="result" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('水冷板测试结果')}:</label>
+					<div class="control-inline">
+						<#form:input path="ylbResult" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
+					<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
+				</div>
+			</#form:form>
+			<table id="dataGrid"></table>
+			<div id="dataGridPage"></div>
+		</div>
+	</div>
+</div>
+<% } %>
+<script>
+// 初始化DataGrid对象
+$('#dataGrid').dataGrid({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("液冷板充气时间")}', name:'ylbCqsj', index:'a.ylb_cqsj', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
+			return '<a href="${ctx}/mes/mesProductQmzc/form?id='+row.id+'" class="btnList" data-title="${text("编辑总成气密数据表")}">'+(val||row.id)+'</a>';
+		}},
+		{header:'${text("液冷板测试时间")}', name:'ylbCssj', index:'a.ylb_cssj', width:150, align:"left"},
+		{header:'${text("液冷板充气压力")}', name:'ylbCqyl', index:'a.ylb_cqyl', width:150, align:"left"},
+		{header:'${text("液冷板稳定压力")}', name:'ylbWdyl', index:'a.ylb_wdyl', width:150, align:"left"},
+		{header:'${text("液冷板泄漏里")}', name:'ylbLeak', index:'a.ylb_leak', width:150, align:"left"},
+		{header:'${text("夜冷板保压时间")}', name:'ylbBysj', index:'a.ylb_bysj', width:150, align:"left"},
+		{header:'${text("框架架充气时间")}', name:'cqsj', index:'a.cqsj', width:150, align:"left"},
+		{header:'${text("框架测试时间")}', name:'cssj', index:'a.cssj', width:150, align:"left"},
+		{header:'${text("框架充气压力")}', name:'cqya', index:'a.cqya', width:150, align:"left"},
+		{header:'${text("框架稳定压力")}', name:'wdyl', index:'a.wdyl', width:150, align:"left"},
+		{header:'${text("框架泄漏里")}', name:'leak', index:'a.leak', width:150, align:"left"},
+		{header:'${text("框架保压时间")}', name:'bysj', index:'a.bysj', width:150, align:"left"},
+		{header:'${text("框架测试结果")}', name:'result', index:'a.result', width:150, align:"left"},
+		{header:'${text("水冷板测试结果")}', name:'ylbResult', index:'a.ylb_result', width:150, align:"left"},
+		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
+			var actions = [];
+			//<% if(hasPermi('mes:mesProductQmzc:edit')){ %>
+				actions.push('<a href="${ctx}/mes/mesProductQmzc/form?id='+row.id+'" class="btnList" title="${text("编辑总成气密数据表")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesProductQmzc/delete?id='+row.id+'" class="btnList" title="${text("删除总成气密数据表")}" data-confirm="${text("确认要删除该总成气密数据表吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+			//<% } %>
+			return actions.join('');
+		}}
+	],
+	// 加载成功后执行事件
+	ajaxSuccess: function(data){
+		
+	}
+});
+</script>

+ 12 - 12
src/main/resources/views/modules/mes/mesProductTjForm.html

@@ -19,43 +19,43 @@
 							<label class="control-label col-sm-4" title="">
 								<span class="required hide">*</span> ${text('工件码')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="sn" maxlength="255" class="form-control"/>
+								<#form:input path="sn" maxlength="64" class="form-control"/>
 							</div>
 						</div>
 					</div>
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
-								<span class="required hide">*</span> ${text('产线编号')}:<i class="fa icon-question hide"></i></label>
+								<span class="required hide">*</span> ${text('工位号')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="lineSn" maxlength="255" class="form-control"/>
+								<#form:input path="oprno" maxlength="255" class="form-control"/>
 							</div>
 						</div>
 					</div>
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
-								<span class="required hide">*</span> ${text('工位号')}:<i class="fa icon-question hide"></i></label>
+								<span class="required hide">*</span> ${text('涂胶速度')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="oprno" maxlength="64" class="form-control"/>
+								<#form:input path="tjSpeed" maxlength="255" class="form-control"/>
 							</div>
 						</div>
 					</div>
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
-								<span class="required hide">*</span> ${text('涂胶速度')}:<i class="fa icon-question hide"></i></label>
+								<span class="required hide">*</span> ${text('涂胶长度')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="tjSpeed" class="form-control number"/>
+								<#form:input path="tjLength" maxlength="255" class="form-control"/>
 							</div>
 						</div>
 					</div>
-					<div class="col-xs-12">
+					<div class="col-xs-6">
 						<div class="form-group">
-							<label class="control-label col-sm-2" title="">
-								<span class="required hide">*</span> ${text('涂胶数据')}:<i class="fa icon-question hide"></i></label>
-							<div class="col-sm-10">
-								<#form:textarea path="tjData" rows="3" maxlength="2000" class="form-control" placeholder="序号#速度#长度#..."/>
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('涂胶序号')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="tjData" maxlength="2000" class="form-control"/>
 							</div>
 						</div>
 					</div>

+ 12 - 14
src/main/resources/views/modules/mes/mesProductTjList.html

@@ -19,29 +19,29 @@
 				<div class="form-group">
 					<label class="control-label">${text('工件码')}:</label>
 					<div class="control-inline">
-						<#form:input path="sn" maxlength="255" class="form-control width-120"/>
+						<#form:input path="sn" maxlength="64" class="form-control width-120"/>
 					</div>
 				</div>
 				<div class="form-group">
-					<label class="control-label">${text('产线编号')}:</label>
+					<label class="control-label">${text('工位号')}:</label>
 					<div class="control-inline">
-						<#form:input path="lineSn" maxlength="255" class="form-control width-120"/>
+						<#form:input path="oprno" maxlength="255" class="form-control width-120"/>
 					</div>
 				</div>
 				<div class="form-group">
-					<label class="control-label">${text('工位号')}:</label>
+					<label class="control-label">${text('涂胶速度')}:</label>
 					<div class="control-inline">
-						<#form:input path="oprno" maxlength="64" class="form-control width-120"/>
+						<#form:input path="tjSpeed" maxlength="255" class="form-control width-120"/>
 					</div>
 				</div>
 				<div class="form-group">
-					<label class="control-label">${text('涂胶速度')}:</label>
+					<label class="control-label">${text('涂胶长度')}:</label>
 					<div class="control-inline">
-						<#form:input path="tjSpeed" class="form-control width-120"/>
+						<#form:input path="tjLength" maxlength="255" class="form-control width-120"/>
 					</div>
 				</div>
 				<div class="form-group">
-					<label class="control-label">${text('涂胶数据')}:</label>
+					<label class="control-label">${text('涂胶序号')}:</label>
 					<div class="control-inline">
 						<#form:input path="tjData" maxlength="2000" class="form-control width-120"/>
 					</div>
@@ -65,12 +65,10 @@ $('#dataGrid').dataGrid({
 		{header:'${text("工件码")}', name:'sn', index:'a.sn', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
 			return '<a href="${ctx}/mes/mesProductTj/form?id='+row.id+'" class="btnList" data-title="${text("编辑涂胶数据")}">'+(val||row.id)+'</a>';
 		}},
-		{header:'${text("产线编号")}', name:'lineSn', index:'a.line_sn', width:150, align:"left"},
-		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:150, align:"center"},
-		{header:'${text("涂胶速度")}', name:'tjSpeed', index:'a.tj_speed', width:150, align:"right", formatter: function(val, obj, row, act){
-			return js.formatNumber(val, 2, false, ''); // 数值类型格式化 (原始数值, 小数位数, 是否千分位, 默认值,金额情况下设置0.00);
-		}},
-		{header:'${text("涂胶数据")}', name:'tjData', index:'a.tj_data', width:280, align:"left"},
+		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:150, align:"left"},
+		{header:'${text("涂胶速度")}', name:'tjSpeed', index:'a.tj_speed', width:150, align:"left"},
+		{header:'${text("涂胶长度")}', name:'tjLength', index:'a.tj_length', width:150, align:"left"},
+		{header:'${text("涂胶序号")}', name:'tjData', index:'a.tj_data', width:150, align:"left"},
 		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
 			var actions = [];
 			//<% if(hasPermi('mes:mesProductTj:edit')){ %>