Przeglądaj źródła

近期优化+来料检上传文件

hou 3 tygodni temu
rodzic
commit
aa0d1d8d10
54 zmienionych plików z 1922 dodań i 165 usunięć
  1. BIN
      MesMaterialPrebindController.javap.txt
  2. 82 0
      db/mysql/mes_device_maintenance.sql
  3. 10 0
      db/mysql/mes_line_process_material_consume_nums.sql
  4. 5 0
      db/mysql/mes_product_dbj_record_item_consume_nums.sql
  5. 23 0
      db/mysql/mes_product_fsw_menu.sql
  6. 15 2
      mes_cloud_199_0y7a.sql
  7. 13 0
      src/main/java/com/jeesite/modules/mes/dao/MesDeviceMaintenancePlanDao.java
  8. 13 0
      src/main/java/com/jeesite/modules/mes/dao/MesDeviceMaintenanceRecordDao.java
  9. 92 0
      src/main/java/com/jeesite/modules/mes/entity/MesDeviceMaintenancePlan.java
  10. 115 0
      src/main/java/com/jeesite/modules/mes/entity/MesDeviceMaintenanceRecord.java
  11. 10 0
      src/main/java/com/jeesite/modules/mes/entity/MesLineProcessMaterial.java
  12. 9 0
      src/main/java/com/jeesite/modules/mes/entity/MesMaterialCheckRecordItems.java
  13. 1 1
      src/main/java/com/jeesite/modules/mes/entity/MesMaterialKcLog.java
  14. 1 0
      src/main/java/com/jeesite/modules/mes/entity/MesMaterialRkRecord.java
  15. 10 0
      src/main/java/com/jeesite/modules/mes/entity/MesProductDbjRecordItem.java
  16. 9 0
      src/main/java/com/jeesite/modules/mes/resp/BindMaterialResp.java
  17. 81 0
      src/main/java/com/jeesite/modules/mes/service/MesDeviceMaintenancePlanService.java
  18. 110 0
      src/main/java/com/jeesite/modules/mes/service/MesDeviceMaintenanceRecordService.java
  19. 1 0
      src/main/java/com/jeesite/modules/mes/service/MesLineProcessMaterialService.java
  20. 34 2
      src/main/java/com/jeesite/modules/mes/service/MesMaterialCheckService.java
  21. 28 0
      src/main/java/com/jeesite/modules/mes/service/MesMaterialPrebindService.java
  22. 52 0
      src/main/java/com/jeesite/modules/mes/service/MesProductDbjRecordService.java
  23. 26 9
      src/main/java/com/jeesite/modules/mes/service/MesProductRecordService.java
  24. 102 0
      src/main/java/com/jeesite/modules/mes/web/MesDeviceMaintenancePlanController.java
  25. 116 0
      src/main/java/com/jeesite/modules/mes/web/MesDeviceMaintenanceRecordController.java
  26. 2 9
      src/main/java/com/jeesite/modules/mes/web/MesElectricTorqueController.java
  27. 110 58
      src/main/java/com/jeesite/modules/mes/web/MesMaterialCheckRecordController.java
  28. 37 4
      src/main/java/com/jeesite/modules/mes/web/MesMaterialPrebindController.java
  29. 22 7
      src/main/java/com/jeesite/modules/mes/web/MesMaterialRkRecordController.java
  30. 53 1
      src/main/java/com/jeesite/modules/mes/web/MesProductFswController.java
  31. 31 2
      src/main/java/com/jeesite/modules/mes/web/MesProductRecordController.java
  32. 2 0
      src/main/java/com/jeesite/modules/utils/ErrorMsg.java
  33. 1 0
      src/main/resources/config/application.yml
  34. 5 0
      src/main/resources/mappings/modules/mes/MesDeviceMaintenancePlanDao.xml
  35. 5 0
      src/main/resources/mappings/modules/mes/MesDeviceMaintenanceRecordDao.xml
  36. 86 0
      src/main/resources/views/modules/mes/mesDeviceMaintenancePlanForm.html
  37. 83 0
      src/main/resources/views/modules/mes/mesDeviceMaintenancePlanList.html
  38. 74 0
      src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordForm.html
  39. 62 0
      src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordList.html
  40. 59 0
      src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordStation.html
  41. 9 0
      src/main/resources/views/modules/mes/mesLineProcessMaterialForm.html
  42. 1 0
      src/main/resources/views/modules/mes/mesLineProcessMaterialList.html
  43. 44 2
      src/main/resources/views/modules/mes/mesMaterialCheckForm.html
  44. 89 9
      src/main/resources/views/modules/mes/mesMaterialCheckRecordForm.html
  45. 71 9
      src/main/resources/views/modules/mes/mesMaterialCheckRecordForm2.html
  46. 67 17
      src/main/resources/views/modules/mes/mesMaterialCheckRecordFormEdit.html
  47. 15 5
      src/main/resources/views/modules/mes/mesMaterialCheckRecordInfo.html
  48. 3 1
      src/main/resources/views/modules/mes/mesProductDbjRecordInfo.html
  49. 26 20
      src/main/resources/views/modules/mes/mesProductList.html
  50. 1 1
      src/main/resources/views/modules/mes/mesScreen5.html
  51. 2 2
      src/main/resources/views/modules/mes/mesScreen6.html
  52. 2 2
      src/main/resources/views/modules/mes/mesScreen7.html
  53. 1 1
      src/main/resources/views/modules/mes/mesScreen8.html
  54. 1 1
      src/main/resources/views/modules/mes/mesScreen9.html

BIN
MesMaterialPrebindController.javap.txt


+ 82 - 0
db/mysql/mes_device_maintenance.sql

@@ -0,0 +1,82 @@
+-- ============================================================
+-- 工位设备保养:建表 + 菜单 + 角色权限 + OP030 示例计划
+-- 数据库:mes_cloud_199_0y7a
+-- ============================================================
+
+-- ----------------------------
+-- 1. 数据表
+-- ----------------------------
+CREATE TABLE IF NOT EXISTS `mes_device_maintenance_plan` (
+  `id` varchar(64) NOT NULL COMMENT '编号',
+  `title` varchar(100) DEFAULT NULL COMMENT '计划名称',
+  `line_sn` varchar(100) NOT NULL COMMENT '产线编号',
+  `oprno` varchar(20) NOT NULL COMMENT '工位号',
+  `interval_days` int NOT NULL COMMENT '保养周期(天)',
+  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
+  `status` char(1) NOT NULL DEFAULT '0' COMMENT '状态(0正常 1删除 2停用)',
+  `create_by` varchar(64) NOT NULL COMMENT '创建者',
+  `create_date` datetime NOT NULL COMMENT '创建时间',
+  `update_by` varchar(64) NOT NULL COMMENT '更新者',
+  `update_date` datetime NOT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  KEY `idx_mdm_plan_line_oprno` (`line_sn`,`oprno`,`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工位设备保养计划';
+
+CREATE TABLE IF NOT EXISTS `mes_device_maintenance_record` (
+  `id` varchar(64) NOT NULL COMMENT '编号',
+  `plan_id` varchar(64) DEFAULT NULL COMMENT '保养计划',
+  `line_sn` varchar(100) NOT NULL COMMENT '产线编号',
+  `oprno` varchar(20) NOT NULL COMMENT '工位号',
+  `content` varchar(500) DEFAULT NULL COMMENT '保养内容',
+  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
+  `create_by` varchar(64) NOT NULL COMMENT '保养人员',
+  `create_date` datetime NOT NULL COMMENT '保养时间',
+  `update_by` varchar(64) NOT NULL COMMENT '更新者',
+  `update_date` datetime NOT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  KEY `idx_mdm_record_line_oprno` (`line_sn`,`oprno`,`create_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工位设备保养记录';
+
+-- ----------------------------
+-- 2. 菜单(设备管理 > 工位保养)
+-- menu_code 说明:
+--   2068001000000000100  工位保养(目录)
+--   2068001000000000101  保养计划
+--   2068001000000000102  保养记录
+-- ----------------------------
+DELETE FROM `js_sys_role_menu` WHERE `menu_code` IN ('2068001000000000100','2068001000000000101','2068001000000000102');
+DELETE FROM `js_sys_menu` WHERE `menu_code` IN ('2068001000000000100','2068001000000000101','2068001000000000102');
+
+INSERT INTO `js_sys_menu`
+(`menu_code`, `parent_code`, `parent_codes`, `tree_sort`, `tree_sorts`, `tree_leaf`, `tree_level`, `tree_names`, `menu_name`, `menu_type`, `menu_href`, `menu_target`, `menu_icon`, `menu_color`, `menu_title`, `permission`, `weight`, `is_show`, `sys_code`, `module_codes`, `component`, `params`, `status`, `create_by`, `create_date`, `update_by`, `update_date`, `remarks`)
+VALUES
+('2068001000000000100', '1582259848270577664', '0,1582259848270577664,', 405, '0000009170,0000000405,', '0', 1, '设备管理/工位保养', '工位保养', '1', '', '', 'fa fa-wrench', '', '', '', 40, '1', 'default', 'app', NULL, NULL, '0', 'system', NOW(), 'system', NOW(), '工位周期性保养(按天拦截加工)'),
+('2068001000000000101', '2068001000000000100', '0,1582259848270577664,2068001000000000100,', 30, '0000009170,0000000405,0000000030,', '1', 2, '设备管理/工位保养/保养计划', '保养计划', '1', '/mes/mesDeviceMaintenancePlan/list', '', '', '', '', 'mes:mesDeviceMaintenancePlan:view,mes:mesDeviceMaintenancePlan:edit', 40, '1', 'default', 'core', NULL, NULL, '0', 'system', NOW(), 'system', NOW(), ''),
+('2068001000000000102', '2068001000000000100', '0,1582259848270577664,2068001000000000100,', 60, '0000009170,0000000405,0000000060,', '1', 2, '设备管理/工位保养/保养记录', '保养记录', '1', '/mes/mesDeviceMaintenanceRecord/list', '', '', '', '', 'mes:mesDeviceMaintenanceRecord:view,mes:mesDeviceMaintenanceRecord:edit', 40, '1', 'default', 'core', NULL, NULL, '0', 'system', NOW(), 'system', NOW(), '');
+
+-- ----------------------------
+-- 3. 角色菜单授权
+-- 凡已拥有「设备管理」下任意子菜单的角色,自动授权工位保养(三件套)
+-- ----------------------------
+INSERT IGNORE INTO `js_sys_role_menu` (`role_code`, `menu_code`)
+SELECT DISTINCT rm.`role_code`, m.`menu_code`
+FROM `js_sys_role_menu` rm
+INNER JOIN `js_sys_menu` dm ON dm.`menu_code` = rm.`menu_code`
+  AND dm.`parent_code` = '1582259848270577664'
+  AND dm.`status` = '0'
+CROSS JOIN (
+  SELECT '2068001000000000100' AS menu_code UNION ALL
+  SELECT '2068001000000000101' UNION ALL
+  SELECT '2068001000000000102'
+) m;
+
+-- ----------------------------
+-- 4. OP030 示例保养计划(产线 XT,A/B 面分别配置)
+-- ----------------------------
+DELETE FROM `mes_device_maintenance_plan` WHERE `id` IN ('2068002000000000001','2068002000000000002');
+
+INSERT INTO `mes_device_maintenance_plan`
+(`id`, `title`, `line_sn`, `oprno`, `interval_days`, `remark`, `status`, `create_by`, `create_date`, `update_by`, `update_date`)
+VALUES
+('2068002000000000001', 'OP030A整站保养', 'XT', 'OP030A', 7, 'OP030 A面整站保养,到期拦截加工', '0', 'system', NOW(), 'system', NOW()),
+('2068002000000000002', 'OP030B整站保养', 'XT', 'OP030B', 7, 'OP030 B面整站保养,到期拦截加工', '0', 'system', NOW(), 'system', NOW());

+ 10 - 0
db/mysql/mes_line_process_material_consume_nums.sql

@@ -0,0 +1,10 @@
+-- 工序物料配置:新增单次消耗数量
+-- 数据库:mes_cloud_199_0y7a
+
+ALTER TABLE `mes_line_process_material`
+    ADD COLUMN `consume_nums` int(10) NULL DEFAULT 1 COMMENT '单次消耗数量' AFTER `nums`;
+
+UPDATE `mes_line_process_material` SET `consume_nums` = 1 WHERE `consume_nums` IS NULL;
+
+ALTER TABLE `mes_line_process_material`
+    MODIFY COLUMN `nums` int(10) NULL DEFAULT NULL COMMENT '数量';

+ 5 - 0
db/mysql/mes_product_dbj_record_item_consume_nums.sql

@@ -0,0 +1,5 @@
+-- 单部件加工过程参数:绑定物料消耗数量
+-- 数据库:mes_cloud_199_0y7a
+
+ALTER TABLE `mes_product_dbj_record_item`
+    ADD COLUMN `consume_nums` int(11) NULL DEFAULT NULL COMMENT '消耗数量' AFTER `craft_name`;

+ 23 - 0
db/mysql/mes_product_fsw_menu.sql

@@ -0,0 +1,23 @@
+-- FSW过程参数菜单(已有库执行本脚本即可)
+-- 路径:生产管理 -> 工艺过程参数 -> FSW过程参数
+
+INSERT INTO `js_sys_menu` VALUES (
+'2072000000000000001', '2042038662094802944', '0,1672118505143263232,2042038662094802944,',
+195, '0000009290,0000000660,0000000195,', '1', 2,
+'生产管理/工艺过程参数/FSW过程参数', 'FSW过程参数', '1', '/mes/mesProductFsw/list',
+'', '', '', '', 'mes:mesProductFsw:view,mes:mesProductFsw:edit',
+40, '1', 'default', 'core', NULL, NULL, '0',
+'system', NOW(), 'system', NOW(),
+'', '', '', '', '', '', '', '', '',
+NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+);
+
+INSERT INTO `js_sys_role_menu` (`role_code`, `menu_code`)
+SELECT rm.`role_code`, '2072000000000000001'
+FROM `js_sys_role_menu` rm
+WHERE rm.`menu_code` = '1796904137003200512'
+  AND NOT EXISTS (
+      SELECT 1 FROM `js_sys_role_menu` x
+      WHERE x.`role_code` = rm.`role_code`
+        AND x.`menu_code` = '2072000000000000001'
+  );

Plik diff jest za duży
+ 15 - 2
mes_cloud_199_0y7a.sql


+ 13 - 0
src/main/java/com/jeesite/modules/mes/dao/MesDeviceMaintenancePlanDao.java

@@ -0,0 +1,13 @@
+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.MesDeviceMaintenancePlan;
+
+/**
+ * 工位设备保养计划DAO
+ */
+@MyBatisDao
+public interface MesDeviceMaintenancePlanDao extends CrudDao<MesDeviceMaintenancePlan> {
+
+}

+ 13 - 0
src/main/java/com/jeesite/modules/mes/dao/MesDeviceMaintenanceRecordDao.java

@@ -0,0 +1,13 @@
+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.MesDeviceMaintenanceRecord;
+
+/**
+ * 工位设备保养记录DAO
+ */
+@MyBatisDao
+public interface MesDeviceMaintenanceRecordDao extends CrudDao<MesDeviceMaintenanceRecord> {
+
+}

+ 92 - 0
src/main/java/com/jeesite/modules/mes/entity/MesDeviceMaintenancePlan.java

@@ -0,0 +1,92 @@
+package com.jeesite.modules.mes.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+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
+ */
+@Table(name = "mes_device_maintenance_plan", alias = "a", label = "工位设备保养计划", columns = {
+		@Column(name = "id", attrName = "id", label = "id", isPK = true),
+		@Column(name = "title", attrName = "title", label = "计划名称", queryType = QueryType.LIKE),
+		@Column(name = "line_sn", attrName = "lineSn", label = "产线编号"),
+		@Column(name = "oprno", attrName = "oprno", label = "工位号", queryType = QueryType.LIKE),
+		@Column(name = "interval_days", attrName = "intervalDays", label = "保养周期(天)"),
+		@Column(name = "remark", attrName = "remark", label = "备注", queryType = QueryType.LIKE),
+		@Column(name = "status", attrName = "status", label = "状态", isUpdate = false),
+		@Column(name = "create_by", attrName = "createBy", label = "create_by", isUpdate = false, isQuery = false),
+		@Column(name = "create_date", attrName = "createDate", label = "create_date", isUpdate = false, isQuery = false, isUpdateForce = true),
+		@Column(name = "update_by", attrName = "updateBy", label = "update_by", isQuery = false),
+		@Column(name = "update_date", attrName = "updateDate", label = "update_date", isQuery = false, isUpdateForce = true),
+}, orderBy = "a.update_date DESC")
+public class MesDeviceMaintenancePlan extends DataEntity<MesDeviceMaintenancePlan> {
+
+	private static final long serialVersionUID = 1L;
+	private String title;
+	private String lineSn;
+	private String oprno;
+	private Integer intervalDays;
+	private String remark;
+
+	public MesDeviceMaintenancePlan() {
+		this(null);
+	}
+
+	public MesDeviceMaintenancePlan(String id) {
+		super(id);
+	}
+
+	@Size(min = 0, max = 100, message = "计划名称长度不能超过 100 个字符")
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	@NotBlank(message = "产线编号不能为空")
+	@Size(min = 0, max = 100, message = "产线编号长度不能超过 100 个字符")
+	public String getLineSn() {
+		return lineSn;
+	}
+
+	public void setLineSn(String lineSn) {
+		this.lineSn = lineSn;
+	}
+
+	@NotBlank(message = "工位号不能为空")
+	@Size(min = 0, max = 20, message = "工位号长度不能超过 20 个字符")
+	public String getOprno() {
+		return oprno;
+	}
+
+	public void setOprno(String oprno) {
+		this.oprno = oprno;
+	}
+
+	@NotNull(message = "保养周期不能为空")
+	public Integer getIntervalDays() {
+		return intervalDays;
+	}
+
+	public void setIntervalDays(Integer intervalDays) {
+		this.intervalDays = intervalDays;
+	}
+
+	@Size(min = 0, max = 255, message = "备注长度不能超过 255 个字符")
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+}

+ 115 - 0
src/main/java/com/jeesite/modules/mes/entity/MesDeviceMaintenanceRecord.java

@@ -0,0 +1,115 @@
+package com.jeesite.modules.mes.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.JoinTable;
+import com.jeesite.common.mybatis.annotation.Table;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
+
+/**
+ * 工位设备保养记录Entity
+ */
+@Table(name = "mes_device_maintenance_record", alias = "a", label = "工位设备保养记录", columns = {
+		@Column(name = "id", attrName = "id", label = "id", isPK = true),
+		@Column(name = "plan_id", attrName = "planId", label = "保养计划"),
+		@Column(name = "line_sn", attrName = "lineSn", label = "产线编号"),
+		@Column(name = "oprno", attrName = "oprno", label = "工位号", queryType = QueryType.LIKE),
+		@Column(name = "content", attrName = "content", label = "保养内容", queryType = QueryType.LIKE),
+		@Column(name = "remark", attrName = "remark", label = "备注", queryType = QueryType.LIKE),
+		@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 = "update_by", isQuery = false),
+		@Column(name = "update_date", attrName = "updateDate", label = "update_date", isQuery = false, isUpdateForce = true),
+}, joinTable = {
+		@JoinTable(type = JoinTable.Type.LEFT_JOIN, entity = MesDeviceMaintenancePlan.class, attrName = "this", alias = "b",
+				on = "b.id = a.plan_id", columns = {
+				@Column(name = "title", attrName = "planTitle", label = "计划名称"),
+				@Column(name = "interval_days", attrName = "intervalDays", label = "保养周期(天)"),
+		}),
+}, orderBy = "a.create_date DESC")
+public class MesDeviceMaintenanceRecord extends DataEntity<MesDeviceMaintenanceRecord> {
+
+	private static final long serialVersionUID = 1L;
+	private String planId;
+	private String lineSn;
+	private String oprno;
+	private String content;
+	private String remark;
+	private String planTitle;
+	private Integer intervalDays;
+
+	public MesDeviceMaintenanceRecord() {
+		this(null);
+	}
+
+	public MesDeviceMaintenanceRecord(String id) {
+		super(id);
+	}
+
+	@Size(min = 0, max = 64, message = "保养计划长度不能超过 64 个字符")
+	public String getPlanId() {
+		return planId;
+	}
+
+	public void setPlanId(String planId) {
+		this.planId = planId;
+	}
+
+	@NotBlank(message = "产线编号不能为空")
+	@Size(min = 0, max = 100, message = "产线编号长度不能超过 100 个字符")
+	public String getLineSn() {
+		return lineSn;
+	}
+
+	public void setLineSn(String lineSn) {
+		this.lineSn = lineSn;
+	}
+
+	@NotBlank(message = "工位号不能为空")
+	@Size(min = 0, max = 20, message = "工位号长度不能超过 20 个字符")
+	public String getOprno() {
+		return oprno;
+	}
+
+	public void setOprno(String oprno) {
+		this.oprno = oprno;
+	}
+
+	@Size(min = 0, max = 500, message = "保养内容长度不能超过 500 个字符")
+	public String getContent() {
+		return content;
+	}
+
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	@Size(min = 0, max = 255, message = "备注长度不能超过 255 个字符")
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+	public String getPlanTitle() {
+		return planTitle;
+	}
+
+	public void setPlanTitle(String planTitle) {
+		this.planTitle = planTitle;
+	}
+
+	public Integer getIntervalDays() {
+		return intervalDays;
+	}
+
+	public void setIntervalDays(Integer intervalDays) {
+		this.intervalDays = intervalDays;
+	}
+
+}

+ 10 - 0
src/main/java/com/jeesite/modules/mes/entity/MesLineProcessMaterial.java

@@ -19,6 +19,7 @@ import com.jeesite.common.mybatis.mapper.query.QueryType;
 		@Column(name="line_process_id", attrName="lineProcessId", label="工位"),
 		@Column(name="material_id", attrName="materialId", label="物料"),
 		@Column(name="nums", attrName="nums", label="数量", isUpdateForce=true),
+		@Column(name="consume_nums", attrName="consumeNums", label="单次消耗数量", isUpdateForce=true),
 		@Column(name="craft", attrName="craft", label="工艺号"),
 		@Column(name="create_by", attrName="createBy", label="create_by", isUpdate=false, isQuery=false),
 		@Column(name="status", attrName="status", label="状态"),
@@ -55,6 +56,7 @@ public class MesLineProcessMaterial extends DataEntity<MesLineProcessMaterial> {
 	private String lineProcessId;		// 工位
 	private String materialId;		// 物料
 	private Integer nums;		// 数量
+	private Integer consumeNums;		// 单次消耗数量
 	private String processTitle;
 	private String materialTitle;
 	private String erpSn;
@@ -99,6 +101,14 @@ public class MesLineProcessMaterial extends DataEntity<MesLineProcessMaterial> {
 		this.nums = nums;
 	}
 
+	public Integer getConsumeNums() {
+		return consumeNums;
+	}
+
+	public void setConsumeNums(Integer consumeNums) {
+		this.consumeNums = consumeNums;
+	}
+
 	public String getProcessTitle() {
 		return processTitle;
 	}

+ 9 - 0
src/main/java/com/jeesite/modules/mes/entity/MesMaterialCheckRecordItems.java

@@ -53,6 +53,7 @@ public class MesMaterialCheckRecordItems extends DataEntity<MesMaterialCheckReco
 	private String orgName;
 	private String result;
 	private List img = ListUtils.newArrayList();
+	private List perfFiles = ListUtils.newArrayList();
 	public MesMaterialCheckRecordItems() {
 		this(null);
 	}
@@ -151,6 +152,14 @@ public class MesMaterialCheckRecordItems extends DataEntity<MesMaterialCheckReco
 		this.img = img;
 	}
 
+	public List getPerfFiles() {
+		return perfFiles;
+	}
+
+	public void setPerfFiles(List perfFiles) {
+		this.perfFiles = perfFiles;
+	}
+
 	public String getResult() {
 		return result;
 	}

+ 1 - 1
src/main/java/com/jeesite/modules/mes/entity/MesMaterialKcLog.java

@@ -17,7 +17,7 @@ import java.util.Date;
  */
 @Table(name="mes_material_kc_log", alias="a", label="来料库存记录表信息", columns={
 		@Column(name="id", attrName="id", label="编号", isPK=true),
-		@Column(name="rk_record_id", attrName="rkRecordId", label="入库单id", isQuery=false),
+		@Column(name="rk_record_id", attrName="rkRecordId", label="入库单id"),
 		@Column(name="material_id", attrName="materialId", label="物料"),
 		@Column(name="batch_sn", attrName="batchSn", label="批次码"),
 		@Column(name="old_batch_sn", attrName="oldBatchSn", label="老批次码"),

+ 1 - 0
src/main/java/com/jeesite/modules/mes/entity/MesMaterialRkRecord.java

@@ -18,6 +18,7 @@ import java.util.List;
  */
 @Table(name="mes_material_rk_record", alias="a", label="来料入库单记录表信息", columns={
 		@Column(name="id", attrName="id", label="id", isPK=true),
+		@Column(name="check_record_id", attrName="checkRecordId", label="来料检查记录id", isQuery=false),
 		@Column(name="state", attrName="state", label="状态"),
 		@Column(name="type", attrName="type", label="类型"),
 		@Column(name="remark", attrName="remark", label="备注"),

+ 10 - 0
src/main/java/com/jeesite/modules/mes/entity/MesProductDbjRecordItem.java

@@ -16,6 +16,7 @@ import java.util.Date;
 		@Column(name = "record_id", attrName = "recordId", label = "主记录ID", queryType = QueryType.EQ),
 		@Column(name = "craft", attrName = "craft", label = "工艺号"),
 		@Column(name = "craft_name", attrName = "craftName", label = "物料名称"),
+		@Column(name = "consume_nums", attrName = "consumeNums", label = "消耗数量", isUpdateForce = true),
 		@Column(name = "result", attrName = "result", label = "结果"),
 		@Column(name = "val", attrName = "val", label = "参数值"),
 		@Column(name = "sort", attrName = "sort", label = "排序"),
@@ -27,6 +28,7 @@ public class MesProductDbjRecordItem extends DataEntity<MesProductDbjRecordItem>
 	private String recordId;
 	private String craft;
 	private String craftName;
+	private Integer consumeNums;
 	private String result;
 	private String val;
 	private Integer sort;
@@ -64,6 +66,14 @@ public class MesProductDbjRecordItem extends DataEntity<MesProductDbjRecordItem>
 		this.craftName = craftName;
 	}
 
+	public Integer getConsumeNums() {
+		return consumeNums;
+	}
+
+	public void setConsumeNums(Integer consumeNums) {
+		this.consumeNums = consumeNums;
+	}
+
 	public String getResult() {
 		return result;
 	}

+ 9 - 0
src/main/java/com/jeesite/modules/mes/resp/BindMaterialResp.java

@@ -10,6 +10,7 @@ public class BindMaterialResp {
     private String batchSn;
     private String lastTimes;
     private String type;
+    private Integer consumeNums;
     private MesMaterialPrebind mesMaterialPrebind;
 
     public String getMaterialId() {
@@ -60,6 +61,14 @@ public class BindMaterialResp {
         this.type = type;
     }
 
+    public Integer getConsumeNums() {
+        return consumeNums;
+    }
+
+    public void setConsumeNums(Integer consumeNums) {
+        this.consumeNums = consumeNums;
+    }
+
     public MesMaterialPrebind getMesMaterialPrebind() {
         return mesMaterialPrebind;
     }

+ 81 - 0
src/main/java/com/jeesite/modules/mes/service/MesDeviceMaintenancePlanService.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.lang.StringUtils;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.common.service.ServiceException;
+import com.jeesite.modules.mes.dao.MesDeviceMaintenancePlanDao;
+import com.jeesite.modules.mes.entity.MesDeviceMaintenancePlan;
+
+/**
+ * 工位设备保养计划Service
+ */
+@Service
+public class MesDeviceMaintenancePlanService extends CrudService<MesDeviceMaintenancePlanDao, MesDeviceMaintenancePlan> {
+
+	@Override
+	public MesDeviceMaintenancePlan get(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		return super.get(mesDeviceMaintenancePlan);
+	}
+
+	@Override
+	public Page<MesDeviceMaintenancePlan> findPage(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		return super.findPage(mesDeviceMaintenancePlan);
+	}
+
+	@Override
+	public List<MesDeviceMaintenancePlan> findList(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		return super.findList(mesDeviceMaintenancePlan);
+	}
+
+	public MesDeviceMaintenancePlan findByOprnoLineSn(String oprno, String lineSn) {
+		if (StringUtils.isEmpty(oprno) || StringUtils.isEmpty(lineSn)) {
+			return null;
+		}
+		MesDeviceMaintenancePlan query = new MesDeviceMaintenancePlan();
+		query.setOprno(oprno);
+		query.setLineSn(lineSn);
+		query.setStatus(MesDeviceMaintenancePlan.STATUS_NORMAL);
+		List<MesDeviceMaintenancePlan> list = findList(query);
+		return list.isEmpty() ? null : list.get(0);
+	}
+
+	@Override
+	@Transactional
+	public void save(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		if (StringUtils.isNotEmpty(mesDeviceMaintenancePlan.getOprno())
+				&& StringUtils.isNotEmpty(mesDeviceMaintenancePlan.getLineSn())) {
+			MesDeviceMaintenancePlan exists = new MesDeviceMaintenancePlan();
+			exists.getSqlMap().getWhere()
+					.and("a.oprno", QueryType.EQ, mesDeviceMaintenancePlan.getOprno())
+					.and("a.line_sn", QueryType.EQ, mesDeviceMaintenancePlan.getLineSn())
+					.and("a.status", QueryType.EQ, MesDeviceMaintenancePlan.STATUS_NORMAL);
+			if (StringUtils.isNotEmpty(mesDeviceMaintenancePlan.getId())) {
+				exists.getSqlMap().getWhere().and("a.id", QueryType.NE, mesDeviceMaintenancePlan.getId());
+			}
+			if (findCount(exists) > 0) {
+				throw new ServiceException("该产线工位已存在启用的保养计划");
+			}
+		}
+		super.save(mesDeviceMaintenancePlan);
+	}
+
+	@Override
+	@Transactional
+	public void updateStatus(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		super.updateStatus(mesDeviceMaintenancePlan);
+	}
+
+	@Override
+	@Transactional
+	public void delete(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		super.delete(mesDeviceMaintenancePlan);
+	}
+
+}

+ 110 - 0
src/main/java/com/jeesite/modules/mes/service/MesDeviceMaintenanceRecordService.java

@@ -0,0 +1,110 @@
+package com.jeesite.modules.mes.service;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.common.service.ServiceException;
+import com.jeesite.modules.mes.dao.MesDeviceMaintenanceRecordDao;
+import com.jeesite.modules.mes.entity.MesDeviceMaintenancePlan;
+import com.jeesite.modules.mes.entity.MesDeviceMaintenanceRecord;
+
+/**
+ * 工位设备保养记录Service
+ */
+@Service
+public class MesDeviceMaintenanceRecordService extends CrudService<MesDeviceMaintenanceRecordDao, MesDeviceMaintenanceRecord> {
+
+	@Autowired
+	private MesDeviceMaintenancePlanService mesDeviceMaintenancePlanService;
+
+	@Override
+	public MesDeviceMaintenanceRecord get(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		return super.get(mesDeviceMaintenanceRecord);
+	}
+
+	@Override
+	public Page<MesDeviceMaintenanceRecord> findPage(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		return super.findPage(mesDeviceMaintenanceRecord);
+	}
+
+	@Override
+	public List<MesDeviceMaintenanceRecord> findList(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		return super.findList(mesDeviceMaintenanceRecord);
+	}
+
+	public Date getLastMaintenanceDate(String oprno, String lineSn) {
+		if (StringUtils.isEmpty(oprno) || StringUtils.isEmpty(lineSn)) {
+			return null;
+		}
+		MesDeviceMaintenanceRecord query = new MesDeviceMaintenanceRecord();
+		query.setOprno(oprno);
+		query.setLineSn(lineSn);
+		query.setPage(new Page<>(1, 1));
+		Page<MesDeviceMaintenanceRecord> page = findPage(query);
+		if (page.getList().isEmpty()) {
+			return null;
+		}
+		return page.getList().get(0).getCreateDate();
+	}
+
+	/**
+	 * 检查工位保养是否在有效期内
+	 */
+	public boolean checkMaintenance(String oprno, String lineSn) {
+		MesDeviceMaintenancePlan plan = mesDeviceMaintenancePlanService.findByOprnoLineSn(oprno, lineSn);
+		if (ObjectUtils.isEmpty(plan)) {
+			return true;
+		}
+		Integer intervalDays = plan.getIntervalDays();
+		if (intervalDays == null || intervalDays <= 0) {
+			return true;
+		}
+
+		Date lastDate = getLastMaintenanceDate(oprno, lineSn);
+		// 已配置计划但从未保养 → 必须先做保养
+		if (lastDate == null) {
+			return false;
+		}
+
+		LocalDate baselineDate = lastDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+		long days = ChronoUnit.DAYS.between(baselineDate, LocalDate.now());
+		return days < intervalDays;
+	}
+
+	@Transactional
+	public void addRecord(MesDeviceMaintenanceRecord record) {
+		if (StringUtils.isEmpty(record.getOprno()) || StringUtils.isEmpty(record.getLineSn())) {
+			throw new ServiceException("工位或产线不能为空");
+		}
+		MesDeviceMaintenancePlan plan = mesDeviceMaintenancePlanService.findByOprnoLineSn(record.getOprno(), record.getLineSn());
+		if (ObjectUtils.isEmpty(plan)) {
+			throw new ServiceException("该工位未配置保养计划");
+		}
+		record.setPlanId(plan.getId());
+		save(record);
+	}
+
+	@Override
+	@Transactional
+	public void save(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		super.save(mesDeviceMaintenanceRecord);
+	}
+
+	@Override
+	@Transactional
+	public void delete(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		super.delete(mesDeviceMaintenanceRecord);
+	}
+
+}

+ 1 - 0
src/main/java/com/jeesite/modules/mes/service/MesLineProcessMaterialService.java

@@ -127,6 +127,7 @@ public class MesLineProcessMaterialService extends CrudService<MesLineProcessMat
 			bindMaterialResp.setLastTimes("");
 			bindMaterialResp.setMesMaterialPrebind(null);
 			bindMaterialResp.setType(mesLineProcessMaterial1.getType());
+			bindMaterialResp.setConsumeNums(mesLineProcessMaterial1.getConsumeNums());
 			bindMaterialResp.setOprno(oldOprno);
 
 			if(!ListUtils.isEmpty(mmps)){

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

@@ -5,10 +5,14 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import com.jeesite.common.entity.Page;
+import com.jeesite.common.lang.StringUtils;
 import com.jeesite.common.service.CrudService;
 import com.jeesite.modules.mes.entity.MesMaterialCheck;
 import com.jeesite.modules.mes.dao.MesMaterialCheckDao;
 import com.jeesite.modules.file.utils.FileUploadUtils;
+import com.jeesite.modules.sys.entity.DictData;
+import com.jeesite.modules.sys.service.DictDataService;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 来料检查内容表Service
@@ -17,6 +21,20 @@ import com.jeesite.modules.file.utils.FileUploadUtils;
  */
 @Service
 public class MesMaterialCheckService extends CrudService<MesMaterialCheckDao, MesMaterialCheck> {
+
+	@Autowired
+	private DictDataService dictDataService;
+
+	private String getOrgDictValue(String label) {
+		DictData dictData = new DictData();
+		dictData.setDictType("mes_material_org");
+		dictData.setDictLabel(label);
+		List<DictData> list = dictDataService.findList(dictData);
+		if (list != null && !list.isEmpty()) {
+			return list.get(0).getDictValue();
+		}
+		return "";
+	}
 	
 	/**
 	 * 获取单条数据
@@ -56,9 +74,23 @@ public class MesMaterialCheckService extends CrudService<MesMaterialCheckDao, Me
 	@Override
 	@Transactional
 	public void save(MesMaterialCheck mesMaterialCheck) {
+		if (StringUtils.isBlank(mesMaterialCheck.getMinValue())) {
+			mesMaterialCheck.setMinValue(null);
+		}
+		if (StringUtils.isBlank(mesMaterialCheck.getMaxValue())) {
+			mesMaterialCheck.setMaxValue(null);
+		}
+		String perfOrg = getOrgDictValue("性能");
+		if (StringUtils.isNotBlank(perfOrg) && perfOrg.equals(mesMaterialCheck.getOrg())) {
+			mesMaterialCheck.setType(null);
+			mesMaterialCheck.setMinValue(null);
+			mesMaterialCheck.setMaxValue(null);
+		}
 		super.save(mesMaterialCheck);
-		// 保存上传图片
-		FileUploadUtils.saveFileUpload(mesMaterialCheck, mesMaterialCheck.getId(), "mesMaterialCheck_image");
+		// 性能项不需要保存参考图片
+		if (StringUtils.isBlank(perfOrg) || !perfOrg.equals(mesMaterialCheck.getOrg())) {
+			FileUploadUtils.saveFileUpload(mesMaterialCheck, mesMaterialCheck.getId(), "mesMaterialCheck_image");
+		}
 	}
 	
 	/**

+ 28 - 0
src/main/java/com/jeesite/modules/mes/service/MesMaterialPrebindService.java

@@ -9,9 +9,11 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import com.jeesite.common.entity.Page;
+import com.jeesite.common.lang.StringUtils;
 import com.jeesite.common.service.CrudService;
 import com.jeesite.modules.mes.entity.MesMaterialPrebind;
 import com.jeesite.modules.mes.dao.MesMaterialPrebindDao;
+import com.jeesite.modules.mes.resp.BindMaterialResp;
 
 /**
  * 工位绑定物料批次Service
@@ -88,5 +90,31 @@ public class MesMaterialPrebindService extends CrudService<MesMaterialPrebindDao
 	public void delete(MesMaterialPrebind mesMaterialPrebind) {
 		super.delete(mesMaterialPrebind);
 	}
+
+	/**
+	 * 过站时按工序物料配置的 consumeNums 扣减剩余次数,未配置时按 1 扣减。
+	 */
+	@Transactional
+	public void deductLastTimesByPass(BindMaterialResp bindMaterialResp) {
+		if (bindMaterialResp == null || StringUtils.isEmpty(bindMaterialResp.getBatchSn())) {
+			return;
+		}
+		String lastTimesStr = bindMaterialResp.getLastTimes();
+		if (StringUtils.isEmpty(lastTimesStr)) {
+			return;
+		}
+		int lastTimes = Integer.parseInt(lastTimesStr);
+		if (lastTimes <= 0) {
+			return;
+		}
+		int consumeNums = bindMaterialResp.getConsumeNums() != null && bindMaterialResp.getConsumeNums() > 0
+				? bindMaterialResp.getConsumeNums() : 1;
+		MesMaterialPrebind mesMaterialPrebind = bindMaterialResp.getMesMaterialPrebind();
+		if (mesMaterialPrebind == null) {
+			return;
+		}
+		mesMaterialPrebind.setLastTimes(Math.max(0, lastTimes - consumeNums));
+		update(mesMaterialPrebind);
+	}
 	
 }

+ 52 - 0
src/main/java/com/jeesite/modules/mes/service/MesProductDbjRecordService.java

@@ -105,6 +105,7 @@ public class MesProductDbjRecordService extends CrudService<MesProductDbjRecordD
 		}
 		List<MesProductDbjRecordItem> items = mesProductDbjRecordItemService.findByRecordId(record.getId());
 		enrichItemMaterialNames(items, record.getOprno(), record.getLineSn());
+		enrichItemConsumeNums(items, record.getOprno(), record.getLineSn());
 		return items;
 	}
 
@@ -174,6 +175,7 @@ public class MesProductDbjRecordService extends CrudService<MesProductDbjRecordD
 			return items;
 		}
 		Map<String, String> craftMaterialMap = buildCraftMaterialNameMap(oprno, lineSn, bmlists);
+		Map<String, Integer> craftConsumeMap = buildCraftConsumeMap(bmlists);
 		int sort = 0;
 		for (ParamsResp paramsResp : paramsResps) {
 			if (paramsResp == null || StringUtils.isEmpty(paramsResp.getCraft())) {
@@ -182,6 +184,7 @@ public class MesProductDbjRecordService extends CrudService<MesProductDbjRecordD
 			MesProductDbjRecordItem item = new MesProductDbjRecordItem();
 			item.setCraft(paramsResp.getCraft());
 			item.setCraftName(craftMaterialMap.get(paramsResp.getCraft()));
+			item.setConsumeNums(craftConsumeMap.get(paramsResp.getCraft()));
 			item.setResult(paramsResp.getResult());
 			item.setVal(paramsResp.getVal());
 			item.setSort(sort++);
@@ -202,6 +205,55 @@ public class MesProductDbjRecordService extends CrudService<MesProductDbjRecordD
 		}
 	}
 
+	private void enrichItemConsumeNums(List<MesProductDbjRecordItem> items, String oprno, String lineSn) {
+		if (ListUtils.isEmpty(items)) {
+			return;
+		}
+		Map<String, Integer> craftConsumeMap = buildCraftConsumeMapFromConfig(oprno, lineSn);
+		for (MesProductDbjRecordItem item : items) {
+			if (item.getConsumeNums() == null && StringUtils.isNotEmpty(item.getCraft())) {
+				item.setConsumeNums(craftConsumeMap.get(item.getCraft()));
+			}
+		}
+	}
+
+	private Map<String, Integer> buildCraftConsumeMap(List<BindMaterialResp> bmlists) {
+		Map<String, Integer> craftConsumeMap = new HashMap<>();
+		if (ListUtils.isEmpty(bmlists)) {
+			return craftConsumeMap;
+		}
+		for (BindMaterialResp bindMaterialResp : bmlists) {
+			if (StringUtils.isEmpty(bindMaterialResp.getCraft()) || StringUtils.isEmpty(bindMaterialResp.getBatchSn())) {
+				continue;
+			}
+			int consumeNums = bindMaterialResp.getConsumeNums() != null && bindMaterialResp.getConsumeNums() > 0
+					? bindMaterialResp.getConsumeNums() : 1;
+			craftConsumeMap.put(bindMaterialResp.getCraft(), consumeNums);
+		}
+		return craftConsumeMap;
+	}
+
+	private Map<String, Integer> buildCraftConsumeMapFromConfig(String oprno, String lineSn) {
+		Map<String, Integer> craftConsumeMap = new HashMap<>();
+		if (StringUtils.isEmpty(oprno) || StringUtils.isEmpty(lineSn)) {
+			return craftConsumeMap;
+		}
+		MesLineProcessMaterial query = new MesLineProcessMaterial();
+		query.setOprno(CommonUitl.formatOprno(oprno));
+		query.setLineSn(lineSn);
+		List<MesLineProcessMaterial> materials = mesLineProcessMaterialService.findList(query);
+		if (!ListUtils.isEmpty(materials)) {
+			for (MesLineProcessMaterial material : materials) {
+				if (StringUtils.isNotEmpty(material.getCraft())) {
+					int consumeNums = material.getConsumeNums() != null && material.getConsumeNums() > 0
+							? material.getConsumeNums() : 1;
+					craftConsumeMap.putIfAbsent(material.getCraft(), consumeNums);
+				}
+			}
+		}
+		return craftConsumeMap;
+	}
+
 	private Map<String, String> buildCraftMaterialNameMap(String oprno, String lineSn, List<BindMaterialResp> bmlists) {
 		Map<String, String> craftMaterialMap = new HashMap<>();
 		if (!ListUtils.isEmpty(bmlists)) {

+ 26 - 9
src/main/java/com/jeesite/modules/mes/service/MesProductRecordService.java

@@ -604,7 +604,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 			}
 		}
 
-
+		Map<String, Integer> craftConsumeMap = buildBindMaterialConsumeMap(bmlists);
 
 		if(!mesLineProcess1.getType().equals("3")){ // 单部件
 			// 更新过程参数
@@ -615,6 +615,9 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 						if(paramsResp.getCraft().equals(mesProductRecord.getCraft())){
 							mesProductRecord.setContent(paramsResp.getResult());
 							mesProductRecord.setMaterielSn(paramsResp.getVal());
+							if (craftConsumeMap.containsKey(paramsResp.getCraft())) {
+								mesProductRecord.setRemark(formatConsumeRemark(craftConsumeMap.get(paramsResp.getCraft())));
+							}
 							if(oldOprno.length() == 6){
 								mesProductRecord.setOprno(oldOprno);
 							}
@@ -759,14 +762,7 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 		// 更新绑定的物料
 		if(!ListUtils.isEmpty(bmlists)){
 			for (BindMaterialResp bindMaterialResp:bmlists){
-				if(!StringUtils.isEmpty(bindMaterialResp.getBatchSn())){
-					Integer lastTimes = Integer.valueOf(bindMaterialResp.getLastTimes());
-					if(lastTimes >= 1){ // 更新数量
-						MesMaterialPrebind mesMaterialPrebind = bindMaterialResp.getMesMaterialPrebind();
-						mesMaterialPrebind.setLastTimes(lastTimes - 1);
-						mesMaterialPrebindService.update(mesMaterialPrebind);
-					}
-				}
+				mesMaterialPrebindService.deductLastTimesByPass(bindMaterialResp);
 			}
 		}
 
@@ -1266,4 +1262,25 @@ public class MesProductRecordService extends CrudService<MesProductRecordDao, Me
 		query.getSqlMap().getWhere().and("oprno", QueryType.LIKE, fOprno);
 		return findList(query);
 	}
+
+	private Map<String, Integer> buildBindMaterialConsumeMap(List<BindMaterialResp> bmlists) {
+		Map<String, Integer> craftConsumeMap = new HashMap<>();
+		if (ListUtils.isEmpty(bmlists)) {
+			return craftConsumeMap;
+		}
+		for (BindMaterialResp bindMaterialResp : bmlists) {
+			if (StringUtils.isEmpty(bindMaterialResp.getCraft()) || StringUtils.isEmpty(bindMaterialResp.getBatchSn())) {
+				continue;
+			}
+			int consumeNums = bindMaterialResp.getConsumeNums() != null && bindMaterialResp.getConsumeNums() > 0
+					? bindMaterialResp.getConsumeNums() : 1;
+			craftConsumeMap.put(bindMaterialResp.getCraft(), consumeNums);
+		}
+		return craftConsumeMap;
+	}
+
+	private String formatConsumeRemark(Integer consumeNums) {
+		int consume = consumeNums != null && consumeNums > 0 ? consumeNums : 1;
+		return "消耗数量:" + consume;
+	}
 }

+ 102 - 0
src/main/java/com/jeesite/modules/mes/web/MesDeviceMaintenancePlanController.java

@@ -0,0 +1,102 @@
+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.MesDeviceMaintenancePlan;
+import com.jeesite.modules.mes.service.MesDeviceMaintenancePlanService;
+
+/**
+ * 工位设备保养计划Controller
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesDeviceMaintenancePlan")
+public class MesDeviceMaintenancePlanController extends BaseController {
+
+	@Autowired
+	private MesDeviceMaintenancePlanService mesDeviceMaintenancePlanService;
+
+	@ModelAttribute
+	public MesDeviceMaintenancePlan get(String id, boolean isNewRecord) {
+		return mesDeviceMaintenancePlanService.get(id, isNewRecord);
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesDeviceMaintenancePlan mesDeviceMaintenancePlan, Model model) {
+		model.addAttribute("mesDeviceMaintenancePlan", mesDeviceMaintenancePlan);
+		return "modules/mes/mesDeviceMaintenancePlanList";
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesDeviceMaintenancePlan> listData(MesDeviceMaintenancePlan mesDeviceMaintenancePlan,
+			HttpServletRequest request, HttpServletResponse response) {
+		mesDeviceMaintenancePlan.setPage(new Page<>(request, response));
+		return mesDeviceMaintenancePlanService.findPage(mesDeviceMaintenancePlan);
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:view")
+	@RequestMapping(value = "form")
+	public String form(MesDeviceMaintenancePlan mesDeviceMaintenancePlan, Model model) {
+		model.addAttribute("mesDeviceMaintenancePlan", mesDeviceMaintenancePlan);
+		return "modules/mes/mesDeviceMaintenancePlanForm";
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:edit")
+	@PostMapping(value = "save")
+	@ResponseBody
+	public String save(@Validated MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		mesDeviceMaintenancePlanService.save(mesDeviceMaintenancePlan);
+		return renderResult(Global.TRUE, text("保存保养计划成功!"));
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:edit")
+	@RequestMapping(value = "disable")
+	@ResponseBody
+	public String disable(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		mesDeviceMaintenancePlan.setStatus(MesDeviceMaintenancePlan.STATUS_DISABLE);
+		mesDeviceMaintenancePlanService.updateStatus(mesDeviceMaintenancePlan);
+		return renderResult(Global.TRUE, text("停用保养计划成功"));
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:edit")
+	@RequestMapping(value = "enable")
+	@ResponseBody
+	public String enable(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		mesDeviceMaintenancePlan.setStatus(MesDeviceMaintenancePlan.STATUS_NORMAL);
+		mesDeviceMaintenancePlanService.updateStatus(mesDeviceMaintenancePlan);
+		return renderResult(Global.TRUE, text("启用保养计划成功"));
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenancePlan:edit")
+	@RequestMapping(value = "delete")
+	@ResponseBody
+	public String delete(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		mesDeviceMaintenancePlanService.delete(mesDeviceMaintenancePlan);
+		return renderResult(Global.TRUE, text("删除保养计划成功!"));
+	}
+
+	@RequestMapping(value = "all")
+	@ResponseBody
+	public List<MesDeviceMaintenancePlan> all(MesDeviceMaintenancePlan mesDeviceMaintenancePlan) {
+		mesDeviceMaintenancePlan.setStatus(MesDeviceMaintenancePlan.STATUS_NORMAL);
+		return mesDeviceMaintenancePlanService.findList(mesDeviceMaintenancePlan);
+	}
+
+}

+ 116 - 0
src/main/java/com/jeesite/modules/mes/web/MesDeviceMaintenanceRecordController.java

@@ -0,0 +1,116 @@
+package com.jeesite.modules.mes.web;
+
+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.lang.StringUtils;
+import com.jeesite.common.service.ServiceException;
+import com.jeesite.common.web.BaseController;
+import com.jeesite.modules.mes.entity.MesDeviceMaintenancePlan;
+import com.jeesite.modules.mes.entity.MesDeviceMaintenanceRecord;
+import com.jeesite.modules.mes.service.MesDeviceMaintenancePlanService;
+import com.jeesite.modules.mes.service.MesDeviceMaintenanceRecordService;
+
+/**
+ * 工位设备保养记录Controller
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesDeviceMaintenanceRecord")
+public class MesDeviceMaintenanceRecordController extends BaseController {
+
+	@Autowired
+	private MesDeviceMaintenanceRecordService mesDeviceMaintenanceRecordService;
+
+	@Autowired
+	private MesDeviceMaintenancePlanService mesDeviceMaintenancePlanService;
+
+	@ModelAttribute
+	public MesDeviceMaintenanceRecord get(String id, boolean isNewRecord) {
+		return mesDeviceMaintenanceRecordService.get(id, isNewRecord);
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenanceRecord:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord, Model model) {
+		model.addAttribute("mesDeviceMaintenanceRecord", mesDeviceMaintenanceRecord);
+		return "modules/mes/mesDeviceMaintenanceRecordList";
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenanceRecord:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesDeviceMaintenanceRecord> listData(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord,
+			HttpServletRequest request, HttpServletResponse response) {
+		mesDeviceMaintenanceRecord.setPage(new Page<>(request, response));
+		return mesDeviceMaintenanceRecordService.findPage(mesDeviceMaintenanceRecord);
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenanceRecord:view")
+	@RequestMapping(value = "form")
+	public String form(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord, Model model) {
+		model.addAttribute("mesDeviceMaintenanceRecord", mesDeviceMaintenanceRecord);
+		model.addAttribute("mesDeviceMaintenancePlan", mesDeviceMaintenancePlanService.findList(new MesDeviceMaintenancePlan()));
+		return "modules/mes/mesDeviceMaintenanceRecordForm";
+	}
+
+	/**
+	 * 工位端保养录入页(WebView)
+	 */
+	@RequestMapping(value = "station")
+	public String station(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord, Model model) {
+		model.addAttribute("mesDeviceMaintenanceRecord", mesDeviceMaintenanceRecord);
+		MesDeviceMaintenancePlan planQuery = new MesDeviceMaintenancePlan();
+		planQuery.setStatus(MesDeviceMaintenancePlan.STATUS_NORMAL);
+		if (StringUtils.isNotEmpty(mesDeviceMaintenanceRecord.getLineSn())) {
+			planQuery.setLineSn(mesDeviceMaintenanceRecord.getLineSn());
+		}
+		if (StringUtils.isNotEmpty(mesDeviceMaintenanceRecord.getOprno())) {
+			planQuery.setOprno(mesDeviceMaintenanceRecord.getOprno());
+		}
+		model.addAttribute("mesDeviceMaintenancePlan", mesDeviceMaintenancePlanService.findList(planQuery));
+		return "modules/mes/mesDeviceMaintenanceRecordStation";
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenanceRecord:edit")
+	@PostMapping(value = "save")
+	@ResponseBody
+	public String save(@Validated MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		mesDeviceMaintenanceRecordService.addRecord(mesDeviceMaintenanceRecord);
+		return renderResult(Global.TRUE, text("保存保养记录成功!"));
+	}
+
+	/**
+	 * 工位客户端提交保养记录(无需图片)
+	 */
+	@PostMapping(value = "addRecord")
+	@ResponseBody
+	public String addRecord(@Validated MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		try {
+			mesDeviceMaintenanceRecordService.addRecord(mesDeviceMaintenanceRecord);
+			return renderResult(Global.TRUE, text("保养记录提交成功!"));
+		} catch (ServiceException e) {
+			return renderResult(Global.FALSE, e.getMessage());
+		}
+	}
+
+	@RequiresPermissions("mes:mesDeviceMaintenanceRecord:edit")
+	@RequestMapping(value = "delete")
+	@ResponseBody
+	public String delete(MesDeviceMaintenanceRecord mesDeviceMaintenanceRecord) {
+		mesDeviceMaintenanceRecordService.delete(mesDeviceMaintenanceRecord);
+		return renderResult(Global.TRUE, text("删除保养记录成功!"));
+	}
+
+}

+ 2 - 9
src/main/java/com/jeesite/modules/mes/web/MesElectricTorqueController.java

@@ -212,15 +212,8 @@ public class MesElectricTorqueController extends BaseController {
 			// 更新绑定的物料
 			if(!ListUtils.isEmpty(bmlists)){
 				for (BindMaterialResp bindMaterialResp:bmlists){
-					if(!StringUtils.isEmpty(bindMaterialResp.getBatchSn())){
-						Integer lastTimes = Integer.valueOf(bindMaterialResp.getLastTimes());
-						if(lastTimes >= 1){ // 更新数量
-							if(crafts.contains(bindMaterialResp.getCraft())){
-								MesMaterialPrebind mesMaterialPrebind = bindMaterialResp.getMesMaterialPrebind();
-								mesMaterialPrebind.setLastTimes(lastTimes - 1);
-								mesMaterialPrebindService.update(mesMaterialPrebind);
-							}
-						}
+					if(!StringUtils.isEmpty(bindMaterialResp.getBatchSn()) && crafts.contains(bindMaterialResp.getCraft())){
+						mesMaterialPrebindService.deductLastTimesByPass(bindMaterialResp);
 					}
 				}
 			}

+ 110 - 58
src/main/java/com/jeesite/modules/mes/web/MesMaterialCheckRecordController.java

@@ -21,7 +21,7 @@ import com.jeesite.modules.file.service.FileUploadService;
 import com.jeesite.modules.mes.entity.*;
 import com.jeesite.modules.mes.resp.CommonResp;
 import com.jeesite.modules.mes.service.*;
-import com.jeesite.modules.sys.dao.DictDataDao;
+import com.jeesite.modules.file.utils.FileUploadUtils;
 import com.jeesite.modules.sys.entity.DictData;
 import com.jeesite.modules.sys.entity.DictType;
 import com.jeesite.modules.sys.service.DictDataService;
@@ -172,7 +172,8 @@ public class MesMaterialCheckRecordController extends BaseController {
 		for (int i=0;i<mecheck.size();i=i+1){
 			MesMaterialCheckRecordItems mesMaterialCheckRecordItems = new MesMaterialCheckRecordItems();
 			mesMaterialCheckRecordItems.setRecordId(mesMaterialCheckRecord.getId());
-			mesMaterialCheckRecordItems.setCheckId(mecheck.getJSONObject(i).getString("id"));
+			String checkId = mecheck.getJSONObject(i).getString("id");
+			mesMaterialCheckRecordItems.setCheckId(checkId);
 			mesMaterialCheckRecordItems.setA1(mecheck.getJSONObject(i).getString("a1"));
 			mesMaterialCheckRecordItems.setA2(mecheck.getJSONObject(i).getString("a2"));
 			mesMaterialCheckRecordItems.setA3(mecheck.getJSONObject(i).getString("a3"));
@@ -180,6 +181,11 @@ public class MesMaterialCheckRecordController extends BaseController {
 			mesMaterialCheckRecordItems.setA5(mecheck.getJSONObject(i).getString("a5"));
 			mesMaterialCheckRecordItems.setResult(mecheck.getJSONObject(i).getString("result"));
 			mesMaterialCheckRecordItemsService.save(mesMaterialCheckRecordItems);
+			String org = mecheck.getJSONObject(i).getString("org");
+			if (StringUtils.isNotBlank(getPerfOrgValue()) && getPerfOrgValue().equals(org)) {
+				FileUploadUtils.saveFileUpload(mesMaterialCheckRecordItems, mesMaterialCheckRecordItems.getId(),
+						getPerfFileFieldName(checkId));
+			}
 		}
 		if(mesMaterialCheckRecord.getState().equals("1")){
 			MesMaterialRkRecord mesMaterialRkRecord = new MesMaterialRkRecord();
@@ -225,29 +231,9 @@ public class MesMaterialCheckRecordController extends BaseController {
 		String host = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/js";
 
 		for (MesMaterialCheckRecordItems item:mitList){
-			DictData dictData = new DictData();
-			dictData.setDictType("mes_material_org");
-			dictData.setDictValue(item.getOrg());
-			List<DictData> dic = dictDataService.findList(dictData);
-			if(!ListUtils.isEmpty(dic)){
-				item.setOrgName(dic.get(0).getDictLabel());
-			}
-
-			FileUpload fu = new FileUpload();
-			fu.setBizKey(item.getCheckId());
-			fu.setBizType("mesMaterialCheck_image");
-			List<FileUpload> finfo = fileUploadService.findList(fu);
-			List imgList = ListUtils.newArrayList();
-			for (FileUpload fi:finfo){
-				Map<String, Object> map1 = MapUtils.newHashMap();
-				map1.put("id",fi.getFileEntity().getFileId());
-				map1.put("url",host + fi.getFileUrl());
-				map1.put("name",fi.getFileName());
-				map1.put("size",fi.getFileEntity().getFileSize());
-
-				imgList.add(map1);
-			}
-			item.setImg(imgList);
+			fillOrgName(item);
+			loadCheckTemplateImages(item, host);
+			loadPerfFiles(item, host);
 		}
 
 		model.addAttribute("mitList", mitList);
@@ -496,29 +482,9 @@ public class MesMaterialCheckRecordController extends BaseController {
 		String host = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/js";
 
 		for (MesMaterialCheckRecordItems item:mitList){
-			DictData dictData = new DictData();
-			dictData.setDictType("mes_material_org");
-			dictData.setDictValue(item.getOrg());
-			List<DictData> dic = dictDataService.findList(dictData);
-			if(!ListUtils.isEmpty(dic)){
-				item.setOrgName(dic.get(0).getDictLabel());
-			}
-
-			FileUpload fu = new FileUpload();
-			fu.setBizKey(item.getCheckId());
-			fu.setBizType("mesMaterialCheck_image");
-			List<FileUpload> finfo = fileUploadService.findList(fu);
-			List imgList = ListUtils.newArrayList();
-			for (FileUpload fi:finfo){
-				Map<String, Object> map1 = MapUtils.newHashMap();
-				map1.put("id",fi.getFileEntity().getFileId());
-				map1.put("url",host + fi.getFileUrl());
-				map1.put("name",fi.getFileName());
-				map1.put("size",fi.getFileEntity().getFileSize());
-
-				imgList.add(map1);
-			}
-			item.setImg(imgList);
+			fillOrgName(item);
+			loadCheckTemplateImages(item, host);
+			loadPerfFiles(item, host);
 		}
 
 		resp.setData(mitList);
@@ -529,32 +495,118 @@ public class MesMaterialCheckRecordController extends BaseController {
 
 	// mesMaterialCheckRecordFormEdit.html 获取 options 数据接口
 	@GetMapping("getOptions")
-	public CommonResp<List<MesMaterialCheckRecordItems>> getOptions(String recordId){
+	public CommonResp<List<MesMaterialCheckRecordItems>> getOptions(String recordId, HttpServletRequest req){
 		CommonResp<List<MesMaterialCheckRecordItems>> resp = new CommonResp<>();
 		MesMaterialCheckRecordItems mci = new MesMaterialCheckRecordItems();
 		mci.setRecordId(recordId);
 		List<MesMaterialCheckRecordItems> mitList = mesMaterialCheckRecordItemsService.findList(mci);
+		String host = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/js";
 
 		for (MesMaterialCheckRecordItems item:mitList) {
-			DictData dictData = new DictData();
-			dictData.setDictType("mes_material_org");
-			dictData.setDictValue(item.getOrg());
-			List<DictData> dic = dictDataService.findList(dictData);
-			if (!ListUtils.isEmpty(dic)) {
-				item.setOrgName(dic.get(0).getDictLabel());
-			}
+			fillOrgName(item);
+			loadCheckTemplateImages(item, host);
+			loadPerfFiles(item, host);
 		}
 
 		resp.setData(mitList);
 		return resp;
 	}
 
+	private String perfOrgValue;
+
+	private String getPerfOrgValue() {
+		if (perfOrgValue == null) {
+			perfOrgValue = getOrgDictValue("性能");
+		}
+		return perfOrgValue;
+	}
+
+	private String getOrgDictValue(String label) {
+		DictData dictData = new DictData();
+		dictData.setDictType("mes_material_org");
+		dictData.setDictLabel(label);
+		List<DictData> dic = dictDataService.findList(dictData);
+		if (!ListUtils.isEmpty(dic)) {
+			return dic.get(0).getDictValue();
+		}
+		return "";
+	}
+
+	private String getPerfFileFieldName(String checkId) {
+		return "perfFileList[" + checkId + "].mesMaterialCheckRecord_file";
+	}
+
+	private void fillOrgName(MesMaterialCheckRecordItems item) {
+		DictData dictData = new DictData();
+		dictData.setDictType("mes_material_org");
+		dictData.setDictValue(item.getOrg());
+		List<DictData> dic = dictDataService.findList(dictData);
+		if (!ListUtils.isEmpty(dic)) {
+			item.setOrgName(dic.get(0).getDictLabel());
+		}
+	}
+
+	private void loadCheckTemplateImages(MesMaterialCheckRecordItems item, String host) {
+		FileUpload fu = new FileUpload();
+		fu.setBizKey(item.getCheckId());
+		fu.setBizType("mesMaterialCheck_image");
+		List<FileUpload> finfo = fileUploadService.findList(fu);
+		List imgList = ListUtils.newArrayList();
+		for (FileUpload fi : finfo) {
+			Map<String, Object> map1 = MapUtils.newHashMap();
+			map1.put("id", fi.getFileEntity().getFileId());
+			map1.put("url", host + fi.getFileUrl());
+			map1.put("name", fi.getFileName());
+			map1.put("size", fi.getFileEntity().getFileSize());
+			imgList.add(map1);
+		}
+		item.setImg(imgList);
+	}
+
+	private void loadPerfFiles(MesMaterialCheckRecordItems item, String host) {
+		FileUpload fu = new FileUpload();
+		fu.setBizKey(item.getId());
+		fu.setBizType("mesMaterialCheckRecord_file");
+		List<FileUpload> finfo = fileUploadService.findList(fu);
+		List fileList = ListUtils.newArrayList();
+		for (FileUpload fi : finfo) {
+			Map<String, Object> map1 = MapUtils.newHashMap();
+			map1.put("id", fi.getFileEntity().getFileId());
+			map1.put("url", host + fi.getFileUrl());
+			map1.put("name", fi.getFileName());
+			map1.put("size", fi.getFileEntity().getFileSize());
+			fileList.add(map1);
+		}
+		item.setPerfFiles(fileList);
+	}
+
 	// mesMaterialCheckRecordFormEdit.html  保存数据接口
 	@PostMapping("editSave")
-	public void editSave(@RequestBody List<MesMaterialCheckRecordItems> list){
-		for (MesMaterialCheckRecordItems items : list) {
+	@ResponseBody
+	@Transactional
+	public String editSave(HttpServletRequest req) {
+		String checkList = req.getParameter("checkList");
+		if (StringUtils.isBlank(checkList)) {
+			return renderResult(Global.FALSE, text("检查数据不能为空!"));
+		}
+		JSONArray mecheck = JSON.parseArray(checkList);
+		for (int i = 0; i < mecheck.size(); i++) {
+			MesMaterialCheckRecordItems items = new MesMaterialCheckRecordItems();
+			items.setId(mecheck.getJSONObject(i).getString("id"));
+			items.setA1(mecheck.getJSONObject(i).getString("a1"));
+			items.setA2(mecheck.getJSONObject(i).getString("a2"));
+			items.setA3(mecheck.getJSONObject(i).getString("a3"));
+			items.setA4(mecheck.getJSONObject(i).getString("a4"));
+			items.setA5(mecheck.getJSONObject(i).getString("a5"));
+			items.setResult(mecheck.getJSONObject(i).getString("result"));
 			mesMaterialCheckRecordItemsService.save(items);
+			String org = mecheck.getJSONObject(i).getString("org");
+			String checkId = mecheck.getJSONObject(i).getString("checkId");
+			if (StringUtils.isNotBlank(getPerfOrgValue()) && getPerfOrgValue().equals(org)) {
+				FileUploadUtils.saveFileUpload(items, items.getId(), getPerfFileFieldName(checkId));
+			}
 		}
+		return renderResult(Global.TRUE, text("保存成功!"));
 	}
 
 }

+ 37 - 4
src/main/java/com/jeesite/modules/mes/web/MesMaterialPrebindController.java

@@ -12,6 +12,8 @@ import com.jeesite.modules.mes.resp.BindMaterialResp;
 import com.jeesite.modules.mes.resp.CommonResp;
 import com.jeesite.modules.mes.service.MesLineProcessMaterialService;
 import com.jeesite.modules.mes.service.MesMaterialKcLogService;
+import com.jeesite.modules.mes.util.CommonUitl;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
@@ -112,7 +114,7 @@ public class MesMaterialPrebindController extends BaseController {
 			}
 			// 检查物料是否是本工位需要的
 			MesLineProcessMaterial mesLineProcessMaterial = new MesLineProcessMaterial();
-			mesLineProcessMaterial.setOprno(mesMaterialPrebind.getOprno());
+			mesLineProcessMaterial.setOprno(CommonUitl.formatOprno(mesMaterialPrebind.getOprno()));
 			mesLineProcessMaterial.setLineSn(mesMaterialPrebind.getLineSn());
 			List<MesLineProcessMaterial> lists = mesLineProcessMaterialService.findList(mesLineProcessMaterial);
 			if(!ListUtils.isEmpty(lists)){
@@ -135,19 +137,50 @@ public class MesMaterialPrebindController extends BaseController {
 		mesMaterialPrebind1.setOprno(mesMaterialPrebind.getOprno());
 		mesMaterialPrebind1.setCraft(craft);
 		MesMaterialPrebind mesMaterialPrebind2 = mesMaterialPrebindService.findInfo(mesMaterialPrebind1);
-		String lastTimes = Global.getConfig("mes.batch.last.times");
+		Integer lastTimes = resolveBindLastTimes(
+				mesMaterialPrebind.getOprno(),
+				mesMaterialPrebind.getLineSn(),
+				craft,
+				mesMaterialPrebind.getMaterialId());
 
 		if(!ObjectUtils.isEmpty(mesMaterialPrebind2)){
 			mesMaterialPrebind2.setBatchSn(mesMaterialPrebind.getBatchSn());
-			mesMaterialPrebind2.setLastTimes(Integer.valueOf(lastTimes));
+			mesMaterialPrebind2.setLastTimes(lastTimes);
 			mesMaterialPrebindService.save(mesMaterialPrebind2);
 		}else{
-			mesMaterialPrebind.setLastTimes(Integer.valueOf(lastTimes));
+			mesMaterialPrebind.setLastTimes(lastTimes);
 			mesMaterialPrebindService.save(mesMaterialPrebind);
 		}
 
 
 		return renderResult(Global.TRUE, text("操作成功!"));
 	}
+
+	/**
+	 * 绑定批次时,剩余次数优先取工序物料配置的 nums(数量);未配置时回退全局参数。
+	 */
+	private Integer resolveBindLastTimes(String oprno, String lineSn, String craft, String materialId) {
+		MesLineProcessMaterial query = new MesLineProcessMaterial();
+		query.setLineSn(lineSn);
+		query.getSqlMap().getWhere().and("b.oprno", QueryType.EQ, CommonUitl.formatOprno(oprno));
+		List<MesLineProcessMaterial> lists = mesLineProcessMaterialService.findList(query);
+		if (!ListUtils.isEmpty(lists)) {
+			for (MesLineProcessMaterial item : lists) {
+				if (craft != null && craft.equals(item.getCraft())
+						&& item.getNums() != null && item.getNums() > 0) {
+					return item.getNums();
+				}
+			}
+			if (materialId != null && !materialId.isEmpty()) {
+				for (MesLineProcessMaterial item : lists) {
+					if (materialId.equals(item.getMaterialId())
+							&& item.getNums() != null && item.getNums() > 0) {
+						return item.getNums();
+					}
+				}
+			}
+		}
+		return Integer.valueOf(Global.getConfig("mes.batch.last.times"));
+	}
 	
 }

+ 22 - 7
src/main/java/com/jeesite/modules/mes/web/MesMaterialRkRecordController.java

@@ -57,6 +57,8 @@ public class MesMaterialRkRecordController extends BaseController {
 	private MesMaterialKcLogService mesMaterialKcLogService;
 	@Autowired
 	private MesMaterialRkLogService mesMaterialRkLogService;
+	@Autowired
+	private MesMaterialCheckRecordService mesMaterialCheckRecordService;
 
 	/**
 	 * 获取数据
@@ -263,21 +265,22 @@ public class MesMaterialRkRecordController extends BaseController {
 		}
 
 		String expire = "";
-		if(materialInfo.getAging()==0){
+		Integer aging = materialInfo.getAging();
+		if (aging == null || aging == 0) {
 			expire = "2099-01-01 00:00:00";
-		}else {
+		} else {
 			Date now = new Date();
-			Date result = addMonths(now, materialInfo.getAging());
+			Date result = addMonths(now, aging);
 			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 			expire = sdf.format(result);
 		}
-		if(minfo.get(0).getType().equals("3")){
+		if ("3".equals(minfo.get(0).getType())) {
 			if(StringUtils.isEmpty(expireDate)){
 				return renderResult(Global.FALSE, text("当前入库单为余料入库,请输入寿命"));
 			}
 			expire = expireDate;
 		}
-		String orderNum = DateLocalUtils.getOrderNum();
+		String batchSn = resolveBatchSn(minfo.get(0));
 		/*if(materialInfo.getType().equals("2")){//精追物料
 		    if(StringUtils.isEmpty(isHave)){
 				return renderResult(Global.FALSE, text("当前物料精追类型,请选择是否有码"));
@@ -363,7 +366,7 @@ public class MesMaterialRkRecordController extends BaseController {
 		MesMaterialKcLog mesMaterialKcLog13 = new MesMaterialKcLog();
 		mesMaterialKcLog13.setRkRecordId(recordId);
 		mesMaterialKcLog13.setMaterialId(materialId);
-		mesMaterialKcLog13.setBatchSn(orderNum);
+		mesMaterialKcLog13.setBatchSn(batchSn);
 		mesMaterialKcLog13.setKwId(kwId);
 		mesMaterialKcLog13.setNums(rkRecordItems.get(0).getNums());
 		mesMaterialKcLog13.setExpireDate(expire);
@@ -373,7 +376,7 @@ public class MesMaterialRkRecordController extends BaseController {
 		MesMaterialRkLog mesMaterialRkLog = new MesMaterialRkLog();
 		mesMaterialRkLog.setRkRecordId(recordId);
 		mesMaterialRkLog.setMaterialId(materialId);
-		mesMaterialRkLog.setBatchSn(orderNum);
+		mesMaterialRkLog.setBatchSn(batchSn);
 		mesMaterialRkLog.setKwId(kwId);
 		mesMaterialRkLog.setNums(rkRecordItems.get(0).getNums());
 		mesMaterialRkLog.setExpireDate(expire);
@@ -408,4 +411,16 @@ public class MesMaterialRkRecordController extends BaseController {
 		cal.add(Calendar.MONTH, months);
 		return cal.getTime();
 	}
+
+	/** 来料检查关联的入库单使用来料码作为批次码,其余场景仍自动生成 */
+	private String resolveBatchSn(MesMaterialRkRecord rkRecord) {
+		if (StringUtils.isNotBlank(rkRecord.getCheckRecordId())) {
+			MesMaterialCheckRecord query = new MesMaterialCheckRecord(rkRecord.getCheckRecordId());
+			MesMaterialCheckRecord checkRecord = mesMaterialCheckRecordService.get(query);
+			if (checkRecord != null && StringUtils.isNotBlank(checkRecord.getSn())) {
+				return checkRecord.getSn().trim();
+			}
+		}
+		return DateLocalUtils.getOrderNum();
+	}
 }

+ 53 - 1
src/main/java/com/jeesite/modules/mes/web/MesProductFswController.java

@@ -8,6 +8,8 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.jeesite.common.lang.StringUtils;
+import com.jeesite.modules.mes.req.MesSearchDateReq;
+import com.jeesite.modules.mes.util.CommonUitl;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
@@ -51,6 +53,9 @@ public class MesProductFswController extends BaseController {
 	@RequiresPermissions("mes:mesProductFsw:view")
 	@RequestMapping(value = {"list", ""})
 	public String list(MesProductFsw mesProductFsw, Model model) {
+		MesSearchDateReq dateMap = CommonUitl.getSearchDate();
+		mesProductFsw.setCreateDate_gte(dateMap.getStartDate());
+		mesProductFsw.setCreateDate_lte(dateMap.getEndtDate());
 		model.addAttribute("mesProductFsw", mesProductFsw);
 		return "modules/mes/mesProductFswList";
 	}
@@ -122,5 +127,52 @@ public class MesProductFswController extends BaseController {
 
 		return renderResult(Global.TRUE, text("操作成功!"));
 	}
-	
+
+	/**
+	 * 批量接口保存数据(客户端定时上传)
+	 */
+	@PostMapping(value = "batchsave")
+	@ResponseBody
+	@Transactional
+	public String batchsave(HttpServletRequest request) {
+		String params = request.getParameter("params");
+		if (StringUtils.isEmpty(params)) {
+			return renderResult(Global.FALSE, text("参数错误!"));
+		}
+
+		JSONArray jsonArr = JSON.parseArray(params);
+		if (jsonArr.size() <= 0) {
+			return renderResult(Global.FALSE, text("参数错误!"));
+		}
+
+		for (int i = 0; i < jsonArr.size(); i++) {
+			JSONObject obj = jsonArr.getJSONObject(i);
+			String oprno = obj.getString("oprno");
+			String lineSn = obj.getString("lineSn");
+			String sn = obj.getString("sn");
+			String feedRate = obj.getString("feedRate");
+			String pressure = obj.getString("pressure");
+			String spindleSpeed = obj.getString("spindleSpeed");
+			String ucode = obj.getString("ucode");
+
+			if (StringUtils.isEmpty(feedRate) || StringUtils.isEmpty(pressure)
+					|| StringUtils.isEmpty(spindleSpeed) || StringUtils.isEmpty(oprno)
+					|| StringUtils.isEmpty(lineSn) || StringUtils.isEmpty(sn)) {
+				continue;
+			}
+
+			MesProductFsw mesProductFsw = new MesProductFsw();
+			mesProductFsw.setSn(sn);
+			mesProductFsw.setOprno(oprno);
+			mesProductFsw.setLineSn(lineSn);
+			mesProductFsw.setCreateBy(StringUtils.isEmpty(ucode) ? "system" : ucode);
+			mesProductFsw.setFeedRate(feedRate);
+			mesProductFsw.setPressure(pressure);
+			mesProductFsw.setSpindleSpeed(spindleSpeed);
+			mesProductFswService.save(mesProductFsw);
+		}
+
+		return renderResult(Global.TRUE, text("操作成功!"));
+	}
+
 }

+ 31 - 2
src/main/java/com/jeesite/modules/mes/web/MesProductRecordController.java

@@ -165,6 +165,9 @@ public class MesProductRecordController extends BaseController {
 	private MesProcessCheckRecordService mesProcessCheckRecordService;
 
 	@Autowired
+	private MesDeviceMaintenanceRecordService mesDeviceMaintenanceRecordService;
+
+	@Autowired
 	private MesProductQmService mesProductQmService;
 
 	@Autowired
@@ -746,6 +749,13 @@ public class MesProductRecordController extends BaseController {
 			return "RSDJ";  // 未进行开班点检
 		}
 
+		MesLineProcess curLineProcess = mesLineProcessService.findInfoByOprnoLineSn(oprno, lineSn);
+		if(!ObjectUtils.isEmpty(curLineProcess) && curLineProcess.getQuality().equals("1")){
+			if(!mesDeviceMaintenanceRecordService.checkMaintenance(oprno,lineSn)){
+				return "RSBY";  // 设备保养到期
+			}
+		}
+
 		MesProductRecord mpr = mesProductRecordService.findBySnCate(sn,cateSn);
 		if(!ObjectUtils.isEmpty(mpr)){
 			return "RSCF";  // 工件码重复
@@ -841,6 +851,13 @@ public class MesProductRecordController extends BaseController {
 			return "RSDJ";  // 未进行开班点检
 		}
 
+		MesLineProcess curLineProcess = mesLineProcessService.findInfoByOprnoLineSn(oprno, lineSn);
+		if(!ObjectUtils.isEmpty(curLineProcess) && curLineProcess.getQuality().equals("1")){
+			if(!mesDeviceMaintenanceRecordService.checkMaintenance(oprno,lineSn)){
+				return "RSBY";  // 设备保养到期
+			}
+		}
+
 		MesProductRecord mpr = mesProductRecordService.findBySnCate(sn,cateSn);
 		if(!ObjectUtils.isEmpty(mpr)){
 			return "RSCF";  // 工件码重复
@@ -1140,6 +1157,13 @@ public class MesProductRecordController extends BaseController {
 					return bs+"DJ";  // 未进行开班点检
 				}
 
+				// 防呆开启时检查设备保养
+				if(mesLineProcess1.getQuality().equals("1")){
+					if(!mesDeviceMaintenanceRecordService.checkMaintenance(oldOprno,lineSn)){
+						return bs+"BY";  // 设备保养到期或未做首次保养
+					}
+				}
+
 				// 2.检查开班样件点检
 				if(!mesProcessCheckRecordService.checkRecord(oldOprno,lineSn)){
 					return bs+"DJ";  // 未进行开班点检
@@ -1270,7 +1294,12 @@ public class MesProductRecordController extends BaseController {
 				return bs+"DJ";  // 未进行开班点检
 			}
 
-			// 3.判断物料批次是否符合绑定
+			// 3.检查设备保养
+			if(!mesDeviceMaintenanceRecordService.checkMaintenance(oldOprno,lineSn)){
+				return bs+"BY";  // 设备保养到期或未做首次保养
+			}
+
+			// 4.判断物料批次是否符合绑定
 			List<BindMaterialResp> bmlists = mesLineProcessMaterialService.getBindMaterial(oldOprno, lineSn);
 			// 该工位绑定了物料
 			if(!ListUtils.isEmpty(bmlists)){
@@ -3504,7 +3533,7 @@ private MesProductProdVisual2Service mesProductProdVisual2Service;
 		// 01;工号;序号(条码);工序名称(工位号);资源名称;设备编码;工治具编码;
 		String commandString = req.getParameter("commandString");
 		logger.info("commandString:"+commandString);
-		mesLogService.apisave2("OP350","XT",commandString,req);
+		mesLogService.apisave2("OP340","XT",commandString,req);
 
 		if (commandString == null || commandString.isEmpty()) {
 			return CommonUitl.getXml("NG;参数错误;");

+ 2 - 0
src/main/java/com/jeesite/modules/utils/ErrorMsg.java

@@ -30,6 +30,8 @@ public class ErrorMsg {
                 lmsg = "首件检查两小时内未检查,超时停机";
             }else if(processMsgRet.equalsIgnoreCase("DJ")) {
                 lmsg = "未进行开班点检";
+            }else if(processMsgRet.equalsIgnoreCase("BY")) {
+                lmsg = "设备保养到期,请先完成保养";
             }else if(processMsgRet.equalsIgnoreCase("BM")) {
                 lmsg = "未绑定物料";
             }else if(processMsgRet.equalsIgnoreCase("PL")) {

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

@@ -628,6 +628,7 @@ shiro:
     ${adminPath}/mes/mesProductRecord/yamao  = anon
     ${adminPath}/mes/mesProductRecord/currentProduct = anon
     ${adminPath}/mes/mesProductFsw/add = anon
+    ${adminPath}/mes/mesProductFsw/batchsave = anon
     ${adminPath}/mes/mesProductProd/batchsave = anon
     ${adminPath}/mes/mesProductRecord/cnccheck = anon
     ${adminPath}/mes/mesProductRecord/cncresult = anon

+ 5 - 0
src/main/resources/mappings/modules/mes/MesDeviceMaintenancePlanDao.xml

@@ -0,0 +1,5 @@
+<?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.MesDeviceMaintenancePlanDao">
+
+</mapper>

+ 5 - 0
src/main/resources/mappings/modules/mes/MesDeviceMaintenanceRecordDao.xml

@@ -0,0 +1,5 @@
+<?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.MesDeviceMaintenanceRecordDao">
+
+</mapper>

+ 86 - 0
src/main/resources/views/modules/mes/mesDeviceMaintenancePlanForm.html

@@ -0,0 +1,86 @@
+<% 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(mesDeviceMaintenancePlan.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="${mesDeviceMaintenancePlan}" action="${ctx}/mes/mesDeviceMaintenancePlan/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"><span class="required">*</span> ${text('产线编号')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="lineSn" maxlength="100" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4"><span class="required">*</span> ${text('工位号')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="oprno" maxlength="20" class="form-control required" placeholder="如 OP030A"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4">${text('计划名称')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="title" maxlength="100" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4"><span class="required">*</span> ${text('保养周期(天)')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="intervalDays" maxlength="5" class="form-control required digits"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('备注')}:</label>
+							<div class="col-sm-10">
+								<#form:textarea path="remark" rows="3" 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:mesDeviceMaintenancePlan: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>

+ 83 - 0
src/main/resources/views/modules/mes/mesDeviceMaintenancePlanList.html

@@ -0,0 +1,83 @@
+<% 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:mesDeviceMaintenancePlan:edit')){ %>
+					<a href="${ctx}/mes/mesDeviceMaintenancePlan/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="${mesDeviceMaintenancePlan}" action="${ctx}/mes/mesDeviceMaintenancePlan/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="title" maxlength="100" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('产线')}:</label>
+					<div class="control-inline">
+						<#form:input path="lineSn" maxlength="100" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('工位号')}:</label>
+					<div class="control-inline">
+						<#form:input path="oprno" maxlength="20" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('状态')}:</label>
+					<div class="control-inline width-120">
+						<#form:select path="status" dictType="sys_search_status" blankOption="true" class="form-control isQuick"/>
+					</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({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("计划名称")}', name:'title', index:'a.title', width:150, align:"center", frozen:true, formatter: function(val, obj, row, act){
+			return '<a href="${ctx}/mes/mesDeviceMaintenancePlan/form?id='+row.id+'" class="btnList" data-title="${text("编辑保养计划")}">'+(val||row.id)+'</a>';
+		}},
+		{header:'${text("产线")}', name:'lineSn', index:'a.line_sn', width:80, align:"center"},
+		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:100, align:"center"},
+		{header:'${text("保养周期(天)")}', name:'intervalDays', index:'a.interval_days', width:120, align:"center"},
+		{header:'${text("备注")}', name:'remark', index:'a.remark', width:150, align:"center"},
+		{header:'${text("状态")}', name:'status', index:'a.status', width:80, align:"center", formatter: function(val, obj, row, act){
+			return js.getDictLabel(${@DictUtils.getDictListJson('sys_search_status')}, val, '${text("未知")}', true);
+		}},
+		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
+			var actions = [];
+			//<% if(hasPermi('mes:mesDeviceMaintenancePlan:edit')){ %>
+				actions.push('<a href="${ctx}/mes/mesDeviceMaintenancePlan/form?id='+row.id+'" class="btnList" title="${text("编辑保养计划")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				if (row.status == Global.STATUS_NORMAL){
+					actions.push('<a href="${ctx}/mes/mesDeviceMaintenancePlan/disable?id='+row.id+'" class="btnList" title="${text("停用")}" data-confirm="${text("确认要停用该保养计划吗?")}"><i class="glyphicon glyphicon-ban-circle"></i></a>&nbsp;');
+				} else if (row.status == Global.STATUS_DISABLE){
+					actions.push('<a href="${ctx}/mes/mesDeviceMaintenancePlan/enable?id='+row.id+'" class="btnList" title="${text("启用")}" data-confirm="${text("确认要启用该保养计划吗?")}"><i class="glyphicon glyphicon-ok-circle"></i></a>&nbsp;');
+				}
+				actions.push('<a href="${ctx}/mes/mesDeviceMaintenancePlan/delete?id='+row.id+'" class="btnList" title="${text("删除")}" data-confirm="${text("确认要删除该保养计划吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+			//<% } %>
+			return actions.join('');
+		}}
+	]
+});
+</script>

+ 74 - 0
src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordForm.html

@@ -0,0 +1,74 @@
+<% 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(mesDeviceMaintenanceRecord.isNewRecord ? '新增保养记录' : '编辑保养记录')}
+			</div>
+		</div>
+		<#form:form id="inputForm" model="${mesDeviceMaintenanceRecord}" action="${ctx}/mes/mesDeviceMaintenanceRecord/save" method="post" class="form-horizontal">
+			<div class="box-body">
+				<#form:hidden path="id"/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4"><span class="required">*</span> ${text('产线编号')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="lineSn" maxlength="100" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4"><span class="required">*</span> ${text('工位号')}:</label>
+							<div class="col-sm-8">
+								<#form:input path="oprno" maxlength="20" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('保养内容')}:</label>
+							<div class="col-sm-10">
+								<#form:textarea path="content" rows="4" maxlength="500" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('备注')}:</label>
+							<div class="col-sm-10">
+								<#form:textarea path="remark" rows="2" 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:mesDeviceMaintenanceRecord:edit')){ %>
+							<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-check"></i> ${text('保 存')}</button>&nbsp;
+						<% } %>
+						<button type="button" class="btn btn-sm btn-default" 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>

+ 62 - 0
src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordList.html

@@ -0,0 +1,62 @@
+<% 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:mesDeviceMaintenanceRecord:edit')){ %>
+					<a href="${ctx}/mes/mesDeviceMaintenanceRecord/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="${mesDeviceMaintenanceRecord}" action="${ctx}/mes/mesDeviceMaintenanceRecord/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="lineSn" maxlength="100" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('工位号')}:</label>
+					<div class="control-inline">
+						<#form:input path="oprno" maxlength="20" 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({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("产线")}', name:'lineSn', index:'a.line_sn', width:80, align:"center"},
+		{header:'${text("工位号")}', name:'oprno', index:'a.oprno', width:100, align:"center", frozen:true},
+		{header:'${text("计划名称")}', name:'planTitle', index:'b.title', width:150, align:"center"},
+		{header:'${text("保养内容")}', name:'content', index:'a.content', width:200, align:"center"},
+		{header:'${text("备注")}', name:'remark', index:'a.remark', width:150, align:"center"},
+		{header:'${text("保养人员")}', name:'createBy', index:'a.create_by', width:100, align:"center"},
+		{header:'${text("保养时间")}', name:'createDate', index:'a.create_date', width:150, align:"center"},
+		{header:'${text("操作")}', name:'actions', width:80, formatter: function(val, obj, row, act){
+			var actions = [];
+			//<% if(hasPermi('mes:mesDeviceMaintenanceRecord:edit')){ %>
+				actions.push('<a href="${ctx}/mes/mesDeviceMaintenanceRecord/delete?id='+row.id+'" class="btnList" title="${text("删除")}" data-confirm="${text("确认要删除该保养记录吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+			//<% } %>
+			return actions.join('');
+		}}
+	]
+});
+</script>

+ 59 - 0
src/main/resources/views/modules/mes/mesDeviceMaintenanceRecordStation.html

@@ -0,0 +1,59 @@
+<% 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 fa-wrench"></i> ${text('设备保养录入')}
+			</div>
+		</div>
+		<#form:form id="inputForm" model="${mesDeviceMaintenanceRecord}" action="${ctx}/mes/mesDeviceMaintenanceRecord/addRecord" method="post" class="form-horizontal">
+			<div class="box-body">
+				<#form:hidden path="lineSn"/>
+				<#form:hidden path="oprno"/>
+				<div class="row">
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('工位')}:</label>
+							<div class="col-sm-10">
+								<p class="form-control-static">${mesDeviceMaintenanceRecord.lineSn} / ${mesDeviceMaintenanceRecord.oprno}</p>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('保养内容')}:</label>
+							<div class="col-sm-10">
+								<#form:textarea path="content" rows="5" maxlength="500" class="form-control" placeholder="请填写本次保养内容"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2">${text('备注')}:</label>
+							<div class="col-sm-10">
+								<#form:textarea path="remark" rows="2" 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">
+						<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-check"></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);
+		}, "json");
+	}
+});
+</script>

+ 9 - 0
src/main/resources/views/modules/mes/mesLineProcessMaterialForm.html

@@ -40,6 +40,15 @@
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
+								<span class="required">*</span> ${text('单次消耗数量')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="consumeNums" maxlength="8" class="form-control digits required"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
 								<span class="required">*</span> ${text('工艺号')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
 								<#form:input path="craft" maxlength="8" class="form-control required"/>

+ 1 - 0
src/main/resources/views/modules/mes/mesLineProcessMaterialList.html

@@ -58,6 +58,7 @@ $('#dataGrid').dataGrid({
 		}},
 		{header:'${text("物料")}', name:'materialTitle', index:'a.materialTitle', width:150, align:"center"},
 		{header:'${text("数量")}', name:'nums', index:'a.nums', width:150, align:"center"},
+		{header:'${text("单次消耗数量")}', name:'consumeNums', index:'a.consume_nums', width:150, align:"center"},
 		{header:'${text("工艺号")}', name:'craft', index:'a.craft', width:150, align:"center"},
 		// {header:'${text("创建时间")}', name:'createDate', index:'a.create_date', width:150, align:"center"},
 		// {header:'${text("更新时间")}', name:'updateDate', index:'a.update_date', width:150, align:"center"},

+ 44 - 2
src/main/resources/views/modules/mes/mesMaterialCheckForm.html

@@ -47,7 +47,7 @@
 						</div>
 					</div>
 				</div>
-				<div class="row">
+				<div class="row" id="imageRow">
 					<div class="col-xs-12">
 						<div class="form-group">
 							<label class="control-label col-sm-2">
@@ -59,7 +59,7 @@
 						</div>
 					</div>
 				</div>
-				<div class="row">
+				<div class="row" id="typeRow">
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
@@ -110,6 +110,48 @@
 </div>
 <% } %>
 <script>
+var mesMaterialOrgDict = ${@DictUtils.getDictListJson('mes_material_org')};
+function getOrgDictValue(label) {
+	for (var i = 0; i < mesMaterialOrgDict.length; i++) {
+		if (mesMaterialOrgDict[i].dictLabel === label) {
+			return mesMaterialOrgDict[i].dictValue;
+		}
+	}
+	return '';
+}
+var ORG_SIZE = getOrgDictValue('尺寸');
+var ORG_PERF = getOrgDictValue('性能');
+
+function toggleFieldsByOrg() {
+	var org = $('#org').val();
+	if (org === ORG_PERF) {
+		$("#imageRow").hide();
+		$("#typeRow").hide();
+		$("#min").hide();
+		$("#max").hide();
+		$('#type').val('');
+		$('#minValue').val('');
+		$('#maxValue').val('');
+	} else if (org === ORG_SIZE) {
+		$("#imageRow").show();
+		$("#typeRow").show();
+		$("#min").show();
+		$("#max").show();
+	} else {
+		$("#imageRow").show();
+		$("#typeRow").show();
+		$("#min").hide();
+		$("#max").hide();
+		$('#minValue').val('');
+		$('#maxValue').val('');
+	}
+}
+
+$(document).ready(function() {
+	toggleFieldsByOrg();
+	$('#org').on('change', toggleFieldsByOrg);
+});
+
 $("#inputForm").validate({
 	submitHandler: function(form){
 		js.ajaxSubmitForm($(form), function(data){

+ 89 - 9
src/main/resources/views/modules/mes/mesMaterialCheckRecordForm.html

@@ -94,17 +94,23 @@
 												<img style="width: 60px" onclick="open_img(this)" :src="item1.url" alt="">
 											</span>
 										</td>
-										<td><input type="text" v-model="item.a1" class="form-control"></td>
-										<td><input type="text" v-model="item.a2" class="form-control"></td>
-										<td><input type="text" v-model="item.a3" class="form-control"></td>
-										<td><input type="text" v-model="item.a4" class="form-control"></td>
-										<td><input type="text" v-model="item.a5" class="form-control"></td>
+										<template v-if="isSizeItem(item)">
+											<td><input type="text" v-model="item.a1" class="form-control"></td>
+											<td><input type="text" v-model="item.a2" class="form-control"></td>
+											<td><input type="text" v-model="item.a3" class="form-control"></td>
+											<td><input type="text" v-model="item.a4" class="form-control"></td>
+											<td><input type="text" v-model="item.a5" class="form-control"></td>
+										</template>
+										<td v-else-if="isPerfItem(item)" colspan="5">
+											<div :id="'perfUpload_'+item.id"></div>
+										</td>
+										<td v-else colspan="5" class="text-center text-muted" style="vertical-align: middle;">人工判定</td>
 										<td>
-											<div v-if="item.type == 1">
+											<div v-if="isSizeItem(item) && item.type == 1">
 												<label v-if="item.result == 1"><input type="radio" v-model="item.result" value="1">合格</label>
 												<label v-if="item.result == 0"><input type="radio" v-model="item.result" value="0">不合格</label>
 											</div>
-											<div v-if="item.type == 2">
+											<div v-else>
 												<label>
 													<input type="radio" :name="item.id" v-model="item.result" value="1" @click="formatData2(item,1)">
 													合格
@@ -151,8 +157,43 @@
 <script src="${ctxStatic}/common/elementui2.15.5/vue-2.6.14.js"></script>
 <script src="${ctxStatic}/common/elementui2.15.5/index.js"></script>
 <script>
+var mesMaterialOrgDict = ${@DictUtils.getDictListJson('mes_material_org')};
+function getOrgDictValue(label) {
+	for (var i = 0; i < mesMaterialOrgDict.length; i++) {
+		if (mesMaterialOrgDict[i].dictLabel === label) {
+			return mesMaterialOrgDict[i].dictValue;
+		}
+	}
+	return '';
+}
+var ORG_SIZE = getOrgDictValue('尺寸');
+var ORG_PERF = getOrgDictValue('性能');
+var PERF_FILE_BIZ_TYPE = 'mesMaterialCheckRecord_file';
+
+function getPerfFileFieldName(checkId) {
+	return 'perfFileList[' + checkId + '].' + PERF_FILE_BIZ_TYPE;
+}
+
 $("#inputForm").validate({
 	submitHandler: function(form){
+		if (vm && vm.options) {
+			for (let i = 0; i < vm.options.length; i++) {
+				var item = vm.options[i];
+				if (vm.isPerfItem(item)) {
+					var fieldName = getPerfFileFieldName(item.id);
+					var hasFile = false;
+					$('input[name="' + fieldName + '"]').each(function () {
+						if ($(this).val()) {
+							hasFile = true;
+						}
+					});
+					if (!hasFile && $('#perfUpload_' + item.id).find('.file-item, .files .template-download').length === 0) {
+						js.showMessage('请上传性能检查文件:' + item.content);
+						return false;
+					}
+				}
+			}
+		}
 		js.ajaxSubmitForm($(form), function(data){
 			js.showMessage(data.message);
 			if(data.result == Global.TRUE){
@@ -200,9 +241,43 @@ var vm = new Vue({
 
 	},
 	methods: {
+		isSizeItem(item) {
+			return item.org === ORG_SIZE;
+		},
+		isPerfItem(item) {
+			return item.org === ORG_PERF;
+		},
+		initPerfFileUploads() {
+			var that = this;
+			this.$nextTick(function () {
+				for (let o in that.options) {
+					var item = that.options[o];
+					if (!that.isPerfItem(item)) {
+						continue;
+					}
+					var container = $('#perfUpload_' + item.id);
+					if (!container.length) {
+						continue;
+					}
+					container.html(js.template('perfFileuploadTpl', {
+						id: 'perfFile_' + item.id,
+						bizKey: item.recordItemId || '',
+						bizType: getPerfFileFieldName(item.id),
+						readonly: false
+					}));
+				}
+			});
+		},
 		formatData(){
 			for (let o in this.options){
-				// this.options[o]['result'] = "";
+				if (!this.isSizeItem(this.options[o])) {
+					this.options[o].a1 = '';
+					this.options[o].a2 = '';
+					this.options[o].a3 = '';
+					this.options[o].a4 = '';
+					this.options[o].a5 = '';
+					continue;
+				}
 				if(this.options[o]['type'] == "1"){ // 系统判定
 					let fminval = parseFloat(this.options[o].minValue?this.options[o].minValue:'');
 					this.options[o].minValue = fminval;
@@ -333,6 +408,7 @@ var vm = new Vue({
 					for (let o in that.options){
 						that.options[o]['result'] = "";
 					}
+					that.initPerfFileUploads();
 					console.log(res);
 					console.log("--");
 					that.formatData();
@@ -389,4 +465,8 @@ var vm = new Vue({
 		}
 	}
 })
-</script>
+</script>
+<script id="perfFileuploadTpl" type="text/template">//<!--<div>
+<#form:fileupload id="{{d.id}}" bizKey="{{d.bizKey}}" bizType="{{d.bizType}}"
+	uploadType="all" class="" isMini="true" preview="true" readonly="{{d.readonly}}" maxUploadNum="1"/>
+</div>//--></script>

+ 71 - 9
src/main/resources/views/modules/mes/mesMaterialCheckRecordForm2.html

@@ -87,17 +87,23 @@
 												<img style="width: 60px" onclick="open_img(this)" :src="item1.url" alt="">
 											</span>
 										</td>
-										<td><input type="text" v-model="item.a1" class="form-control"></td>
-										<td><input type="text" v-model="item.a2" class="form-control"></td>
-										<td><input type="text" v-model="item.a3" class="form-control"></td>
-										<td><input type="text" v-model="item.a4" class="form-control"></td>
-										<td><input type="text" v-model="item.a5" class="form-control"></td>
+										<template v-if="isSizeItem(item)">
+											<td><input type="text" v-model="item.a1" class="form-control"></td>
+											<td><input type="text" v-model="item.a2" class="form-control"></td>
+											<td><input type="text" v-model="item.a3" class="form-control"></td>
+											<td><input type="text" v-model="item.a4" class="form-control"></td>
+											<td><input type="text" v-model="item.a5" class="form-control"></td>
+										</template>
+										<td v-else-if="isPerfItem(item)" colspan="5">
+											<div :id="'perfUpload_'+item.id"></div>
+										</td>
+										<td v-else colspan="5" class="text-center text-muted" style="vertical-align: middle;">人工判定</td>
 										<td>
-											<div v-if="item.type == 1">
+											<div v-if="isSizeItem(item) && item.type == 1">
 												<label v-if="item.result == 1"><input type="radio" v-model="item.result" value="1">合格</label>
 												<label v-if="item.result == 0"><input type="radio" v-model="item.result" value="0">不合格</label>
 											</div>
-											<div v-if="item.type == 2">
+											<div v-else>
 												<label>
 													<input type="radio" :name="item.id" v-model="item.result" value="1" @click="formatData2(item,1)">
 													合格
@@ -133,6 +139,23 @@
 <script src="${ctxStatic}/common/elementui2.15.5/vue-2.6.14.js"></script>
 <script src="${ctxStatic}/common/elementui2.15.5/index.js"></script>
 <script>
+var mesMaterialOrgDict = ${@DictUtils.getDictListJson('mes_material_org')};
+function getOrgDictValue(label) {
+	for (var i = 0; i < mesMaterialOrgDict.length; i++) {
+		if (mesMaterialOrgDict[i].dictLabel === label) {
+			return mesMaterialOrgDict[i].dictValue;
+		}
+	}
+	return '';
+}
+var ORG_SIZE = getOrgDictValue('尺寸');
+var ORG_PERF = getOrgDictValue('性能');
+var PERF_FILE_BIZ_TYPE = 'mesMaterialCheckRecord_file';
+
+function getPerfFileFieldName(checkId) {
+	return 'perfFileList[' + checkId + '].' + PERF_FILE_BIZ_TYPE;
+}
+
 $("#inputForm").validate({
 	submitHandler: function(form){
 		js.ajaxSubmitForm($(form), function(data){
@@ -182,9 +205,43 @@ var vm = new Vue({
 
 	},
 	methods: {
+		isSizeItem(item) {
+			return item.org === ORG_SIZE;
+		},
+		isPerfItem(item) {
+			return item.org === ORG_PERF;
+		},
+		initPerfFileUploads() {
+			var that = this;
+			this.$nextTick(function () {
+				for (let o in that.options) {
+					var item = that.options[o];
+					if (!that.isPerfItem(item)) {
+						continue;
+					}
+					var container = $('#perfUpload_' + item.id);
+					if (!container.length) {
+						continue;
+					}
+					container.html(js.template('perfFileuploadTpl', {
+						id: 'perfFile_' + item.id,
+						bizKey: item.recordItemId || '',
+						bizType: getPerfFileFieldName(item.id),
+						readonly: false
+					}));
+				}
+			});
+		},
 		formatData(){
 			for (let o in this.options){
-				// this.options[o]['result'] = "";
+				if (!this.isSizeItem(this.options[o])) {
+					this.options[o].a1 = '';
+					this.options[o].a2 = '';
+					this.options[o].a3 = '';
+					this.options[o].a4 = '';
+					this.options[o].a5 = '';
+					continue;
+				}
 				if(this.options[o]['type'] == "1"){ // 系统判定
 					let fminval = parseFloat(this.options[o].minValue?this.options[o].minValue:'');
 					this.options[o].minValue = fminval;
@@ -279,6 +336,7 @@ var vm = new Vue({
 					for (let o in that.options){
 						that.options[o]['result'] = "";
 					}
+					that.initPerfFileUploads();
 					console.log(res);
 					console.log("--");
 					that.formatData();
@@ -334,4 +392,8 @@ var vm = new Vue({
 		}
 	}
 })
-</script>
+</script>
+<script id="perfFileuploadTpl" type="text/template">//<!--<div>
+<#form:fileupload id="{{d.id}}" bizKey="{{d.bizKey}}" bizType="{{d.bizType}}"
+	uploadType="all" class="" isMini="true" preview="true" readonly="{{d.readonly}}" maxUploadNum="1"/>
+</div>//--></script>

+ 67 - 17
src/main/resources/views/modules/mes/mesMaterialCheckRecordFormEdit.html

@@ -9,7 +9,7 @@
                 <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="${mesMaterialCheckRecord}" action="${ctx}/mes/mesMaterialCheckRecord/save" method="post" class="form-horizontal">
+        <#form:form id="inputForm" model="${mesMaterialCheckRecord}" action="${ctx}/mes/mesMaterialCheckRecord/editSave" method="post" class="form-horizontal">
         <div class="box-body" id="app">
             <#form:hidden path="id" id="recordId"/>
             <#form:hidden path="materialId"/>
@@ -115,11 +115,20 @@
 												<img style="width: 60px" onclick="open_img(this)" :src="item1.url" alt="">
 											</span>
                                     </td>
-                                    <td><input type="text" v-model="item.a1" class="form-control"></td>
-                                    <td><input type="text" v-model="item.a2" class="form-control"></td>
-                                    <td><input type="text" v-model="item.a3" class="form-control"></td>
-                                    <td><input type="text" v-model="item.a4" class="form-control"></td>
-                                    <td><input type="text" v-model="item.a5" class="form-control"></td>
+                                    <template v-if="isSizeItem(item)">
+                                        <td><input type="text" v-model="item.a1" class="form-control"></td>
+                                        <td><input type="text" v-model="item.a2" class="form-control"></td>
+                                        <td><input type="text" v-model="item.a3" class="form-control"></td>
+                                        <td><input type="text" v-model="item.a4" class="form-control"></td>
+                                        <td><input type="text" v-model="item.a5" class="form-control"></td>
+                                    </template>
+                                    <td v-else-if="isPerfItem(item)" colspan="5">
+                                        <div v-if="item.perfFiles && item.perfFiles.length" style="margin-bottom: 8px;">
+                                            <a v-for="(f, idx) in item.perfFiles" :key="idx" :href="f.url" target="_blank" style="margin-right: 10px;">{{f.name}}</a>
+                                        </div>
+                                        <div :id="'perfUpload_'+item.checkId"></div>
+                                    </td>
+                                    <td v-else colspan="5" class="text-center text-muted" style="vertical-align: middle;">人工判定</td>
                                     <td>
                                             <label>
                                                 <input type="radio"  v-model="item.result" value="1">
@@ -156,14 +165,31 @@
 <script src="${ctxStatic}/common/elementui2.15.5/index.js"></script>
 <script src="${ctxStatic}/common/elementui2.15.5/axios.min.js"></script>
 <script>
+    var mesMaterialOrgDict = ${@DictUtils.getDictListJson('mes_material_org')};
+    function getOrgDictValue(label) {
+        for (var i = 0; i < mesMaterialOrgDict.length; i++) {
+            if (mesMaterialOrgDict[i].dictLabel === label) {
+                return mesMaterialOrgDict[i].dictValue;
+            }
+        }
+        return '';
+    }
+    var ORG_SIZE = getOrgDictValue('尺寸');
+    var ORG_PERF = getOrgDictValue('性能');
+    var PERF_FILE_BIZ_TYPE = 'mesMaterialCheckRecord_file';
+
+    function getPerfFileFieldName(checkId) {
+        return 'perfFileList[' + checkId + '].' + PERF_FILE_BIZ_TYPE;
+    }
+
     $("#inputForm").validate({
         submitHandler: function(form){
+            $('#checkList').val(JSON.stringify(vm.options));
             js.ajaxSubmitForm($(form), function(data){
                 js.showMessage(data.message);
                 if(data.result == Global.TRUE){
                     js.closeCurrentTabPage(function(contentWindow){
                         contentWindow.page();
-
                     });
                 }
             }, "json");
@@ -195,22 +221,46 @@
             ).then(response => {
                 const data = response.data.commonResp
                 this.options = data.data
+                this.initPerfFileUploads()
             })
 
         },
 
         methods: {
-            save(){
-                console.log("点击保存")
-                axios(
-                    {
-                        method: 'post',
-                        url: "${ctx}/mes/mesMaterialCheckRecord/editSave",
-                        data:  this.options
+            isSizeItem(item) {
+                return item.org === ORG_SIZE;
+            },
+            isPerfItem(item) {
+                return item.org === ORG_PERF;
+            },
+            initPerfFileUploads() {
+                var that = this;
+                this.$nextTick(function () {
+                    for (let o in that.options) {
+                        var item = that.options[o];
+                        if (!that.isPerfItem(item)) {
+                            continue;
+                        }
+                        var container = $('#perfUpload_' + item.checkId);
+                        if (!container.length) {
+                            continue;
+                        }
+                        container.html(js.template('perfFileuploadTpl', {
+                            id: 'perfFile_' + item.checkId,
+                            bizKey: '',
+                            bizType: getPerfFileFieldName(item.checkId),
+                            readonly: false
+                        }));
                     }
-                )
-                js.closeCurrentTabPage()
+                });
+            },
+            save(){
+                $("#inputForm").submit();
             }
         }
     })
-</script>
+</script>
+<script id="perfFileuploadTpl" type="text/template">//<!--<div>
+<#form:fileupload id="{{d.id}}" bizKey="{{d.bizKey}}" bizType="{{d.bizType}}"
+	uploadType="all" class="" isMini="true" preview="true" readonly="{{d.readonly}}" maxUploadNum="1"/>
+</div>//--></script>

+ 15 - 5
src/main/resources/views/modules/mes/mesMaterialCheckRecordInfo.html

@@ -69,11 +69,21 @@
 									</span>
 									<% } %>
 								</td>
-								<td>${item.a1}</td>
-								<td>${item.a2}</td>
-								<td>${item.a3}</td>
-								<td>${item.a4}</td>
-								<td>${item.a5}</td>
+								<% if(item.orgName == '尺寸'){ %>
+								<td>${item.a1!}</td>
+								<td>${item.a2!}</td>
+								<td>${item.a3!}</td>
+								<td>${item.a4!}</td>
+								<td>${item.a5!}</td>
+								<% } else if(item.orgName == '性能'){ %>
+								<td colspan="5">
+									<% for(var perfFile in item.perfFiles){ %>
+									<a href="${perfFile.url}" target="_blank">${perfFile.name}</a>&nbsp;
+									<% } %>
+								</td>
+								<% } else { %>
+								<td colspan="5" class="text-center text-muted">人工判定</td>
+								<% } %>
 								<td>
 									<% if (item.result == '1'){ %>
 									合格

+ 3 - 1
src/main/resources/views/modules/mes/mesProductDbjRecordInfo.html

@@ -64,6 +64,7 @@
 				<tr>
 					<th class="text-center" style="width:120px;background-color:#d2d6de;">工艺号</th>
 					<th class="text-center" style="width:180px;background-color:#d2d6de;">物料名称</th>
+					<th class="text-center" style="width:100px;background-color:#d2d6de;">消耗数量</th>
 					<th class="text-center" style="width:80px;background-color:#d2d6de;">结果</th>
 					<th class="text-center" style="background-color:#d2d6de;">参数值</th>
 				</tr>
@@ -74,12 +75,13 @@
 					<tr>
 						<td class="text-center">${item.craft!''}</td>
 						<td class="text-center">${item.craftName!''}</td>
+						<td class="text-center">${item.consumeNums!''}</td>
 						<td class="text-center">${item.result!''}</td>
 						<td class="text-center">${item.val!''}</td>
 					</tr>
 					<% } %>
 				<% } else { %>
-					<tr><td colspan="4" class="text-center text-muted">暂无过程参数</td></tr>
+					<tr><td colspan="5" class="text-center text-muted">暂无过程参数</td></tr>
 				<% } %>
 				</tbody>
 			</table>

+ 26 - 20
src/main/resources/views/modules/mes/mesProductList.html

@@ -47,18 +47,18 @@
 						<#form:input path="cate" 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="batchSn" maxlength="100" class="form-control width-120"/>-->
-<!--					</div>-->
-<!--				</div>-->
-<!--				<div class="form-group">-->
-<!--					<label class="control-label">${text('重量')}:</label>-->
-<!--					<div class="control-inline">-->
-<!--						<#form:input path="weight" maxlength="10" class="form-control width-120"/>-->
-<!--					</div>-->
-<!--				</div>-->
+				<div class="form-group">
+					<label class="control-label">${text('打包批号')}:</label>
+					<div class="control-inline">
+						<#form:input path="batchSn" maxlength="100" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('重量')}:</label>
+					<div class="control-inline">
+						<#form:input path="weight" maxlength="10" class="form-control width-120"/>
+					</div>
+				</div>
 			<div class="form-group">
 				<label class="control-label">${text('创建日期')}:</label>
 				<div class="control-inline">
@@ -108,14 +108,20 @@ $('#dataGrid').dataGrid({
 				return js.getDictLabel(${@DictUtils.getDictListJson('mes_product_status')}, val, '${text("未知")}', true);
 			}},
 		// {header:'${text("备注")}', name:'remark', index:'a.remark', width:150, align:"center"},
-		//  {header:'${text("打包批号")}', name:'batchSn', index:'a.batch_sn', width:150, align:"center"},
-		// {header:'${text("重量(kg)")}', name:'weight', index:'a.weight', width:150, align:"center", formatter: function(val, obj, row, act){
-		// 		if(val){
-		// 			return parseFloat(val);
-		// 		}else{
-		// 			return "";
-		// 		}
-		// 	}},
+		{header:'${text("打包批号")}', name:'batchSn', index:'a.batch_sn', width:150, align:"center", formatter: function(val, obj, row, act){
+				if(val == null || val == ""){
+					return "-";
+				}else {
+					return val;
+				}
+			}},
+		{header:'${text("重量(kg)")}', name:'weight', index:'a.weight', width:150, align:"center", formatter: function(val, obj, row, act){
+				if(val){
+					return parseFloat(val).toFixed(1);
+				}else{
+					return "-";
+				}
+			}},
 		// {header:'${text("重量(kg)")}', name:'weight', index:'a.weight', width:150, align:"center"},
 		// {header:'${text("包装时间")}', name:'bindDate', index:'a.bind_date', width:150, align:"center"},
 		// {header:'${text("包装人")}', name:'bindBy', index:'a.bind_by', width:150, align:"center"},

+ 1 - 1
src/main/resources/views/modules/mes/mesScreen5.html

@@ -182,7 +182,7 @@
 <script src="${ctxStatic}/echarts/4.2/echarts.min.js"></script>
 <script>
 	window.screenOprnoConfig = {
-		title: "一号工位加工记录统计大屏",
+		title: "华为项目加工记录统计大屏",
 		defaultOprnos: ["OP010A", "OP050A", "OP060A", "OP070A", "OP070B", "OP080A", "OP090A", "OP090B", "OP090C", "OP100A", "OP100B", "OP100C"]
 	};
 </script>

+ 2 - 2
src/main/resources/views/modules/mes/mesScreen6.html

@@ -182,8 +182,8 @@
 <script src="${ctxStatic}/echarts/4.2/echarts.min.js"></script>
 <script>
 	window.screenOprnoConfig = {
-		title: "二号工位加工记录统计大屏",
-		defaultOprnos: ["OP150", "OP160", "OP170", "OP180", "OP190", "OP200", "OP210", "OP220", "OP230", "OP240"]
+		title: "华为项目加工记录统计大屏",
+		defaultOprnos: ["OP110A", "OP110B", "OP120A", "OP120B", "OP130A", "OP140A", "OP150A", "OP160A", "OP160B", "OP170A", "OP180A", "OP180B", "OP190A", "OP190B"]
 	};
 </script>
 <script src="${ctxStatic}/screen/oprno-record-screen.js?v=202506244"></script>

+ 2 - 2
src/main/resources/views/modules/mes/mesScreen7.html

@@ -182,8 +182,8 @@
 <script src="${ctxStatic}/echarts/4.2/echarts.min.js"></script>
 <script>
 	window.screenOprnoConfig = {
-		title: "三号工位加工记录统计大屏",
-		defaultOprnos: ["OP250", "OP260", "OP270", "OP281", "OP282", "OP283", "OP284", "OP290", "OP300", "OP310"]
+		title: "华为项目加工记录统计大屏",
+		defaultOprnos: ["OP200A", "OP210A", "OP220A", "OP230A", "OP240A", "OP240B", "OP250A", "OP260A", "OP270A", "OP270B", "OP280A", "OP290A", "OP300A", "OP310A", "OP320A", "OP330A", "OP340A", "OP350A", "OP360A"]
 	};
 </script>
 <script src="${ctxStatic}/screen/oprno-record-screen.js?v=202506244"></script>

+ 1 - 1
src/main/resources/views/modules/mes/mesScreen8.html

@@ -182,7 +182,7 @@
 <script src="${ctxStatic}/echarts/4.2/echarts.min.js"></script>
 <script>
 	window.screenOprnoConfig = {
-		title: "四号工位加工记录统计大屏",
+		title: "华为项目加工记录统计大屏",
 		defaultOprnos: ["OP320", "OP330", "OP340", "OP350", "OP360", "OP370", "OP380", "OP390", "OP400", "OP410"]
 	};
 </script>

+ 1 - 1
src/main/resources/views/modules/mes/mesScreen9.html

@@ -182,7 +182,7 @@
 <script src="${ctxStatic}/echarts/4.2/echarts.min.js"></script>
 <script>
 	window.screenOprnoConfig = {
-		title: "五号工位加工记录统计大屏",
+		title: "华为项目加工记录统计大屏",
 		defaultOprnos: ["OP420", "OP430", "OP440", "OP450", "OP460", "OP470", "OP480", "OP490", "OP320A"]
 	};
 </script>