hou 1 ヶ月 前
親
コミット
4e8c9feec7
24 ファイル変更、520 行追加、52 行削除
  1. 2 0
      db/mysql/add_mes_screen_honor_publish_date.sql
  2. 3 0
      src/main/java/com/jeesite/modules/mes/dao/MesScreenHonorDao.java
  3. 3 0
      src/main/java/com/jeesite/modules/mes/dao/MesScreenNoticeDao.java
  4. 15 2
      src/main/java/com/jeesite/modules/mes/entity/MesScreenHonor.java
  5. 2 2
      src/main/java/com/jeesite/modules/mes/entity/MesScreenNotice.java
  6. 30 0
      src/main/java/com/jeesite/modules/mes/erp/ErpProductionOrder.java
  7. 222 17
      src/main/java/com/jeesite/modules/mes/erp/ErpProductionOrderService.java
  8. 32 4
      src/main/java/com/jeesite/modules/mes/service/MesScreenHonorService.java
  9. 22 3
      src/main/java/com/jeesite/modules/mes/service/MesScreenNoticeService.java
  10. 73 2
      src/main/java/com/jeesite/modules/mes/web/MesProductRecordController.java
  11. 5 1
      src/main/java/com/jeesite/modules/mes/web/MesRepairController.java
  12. 9 1
      src/main/java/com/jeesite/modules/mes/web/MesScreenHonorController.java
  13. 9 1
      src/main/java/com/jeesite/modules/mes/web/MesScreenNoticeController.java
  14. 27 0
      src/main/java/com/jeesite/modules/scheduling/MesScreenPublishScheduling.java
  15. 2 0
      src/main/java/com/jeesite/modules/utils/ErrorMsg.java
  16. 11 6
      src/main/resources/config/application.yml
  17. 14 1
      src/main/resources/mappings/modules/mes/MesScreenHonorDao.xml
  18. 12 0
      src/main/resources/mappings/modules/mes/MesScreenNoticeDao.xml
  19. 1 1
      src/main/resources/views/modules/mes/erpProductionOrderDetail.html
  20. 2 0
      src/main/resources/views/modules/mes/erpProductionOrderList.html
  21. 13 2
      src/main/resources/views/modules/mes/mesScreenHonorForm.html
  22. 4 3
      src/main/resources/views/modules/mes/mesScreenHonorList.html
  23. 3 2
      src/main/resources/views/modules/mes/mesScreenNoticeForm.html
  24. 4 4
      src/main/resources/views/modules/mes/mesScreenNoticeList.html

+ 2 - 0
db/mysql/add_mes_screen_honor_publish_date.sql

@@ -0,0 +1,2 @@
+-- 荣誉榜单增加发布时间字段,用于定时自动上屏
+ALTER TABLE mes_screen_honor ADD COLUMN publish_date datetime DEFAULT NULL COMMENT '发布时间' AFTER dept_name;

+ 3 - 0
src/main/java/com/jeesite/modules/mes/dao/MesScreenHonorDao.java

@@ -5,6 +5,7 @@ import com.jeesite.common.mybatis.annotation.MyBatisDao;
 import com.jeesite.modules.mes.entity.MesScreenHonor;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -16,4 +17,6 @@ import java.util.List;
 public interface MesScreenHonorDao extends CrudDao<MesScreenHonor> {
 
 	List<MesScreenHonor> findEnabledList(@Param("isEnabled") String isEnabled);
+
+	int enableDuePublish(@Param("now") Date now);
 }

+ 3 - 0
src/main/java/com/jeesite/modules/mes/dao/MesScreenNoticeDao.java

@@ -5,6 +5,7 @@ import com.jeesite.common.mybatis.annotation.MyBatisDao;
 import com.jeesite.modules.mes.entity.MesScreenNotice;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -16,4 +17,6 @@ import java.util.List;
 public interface MesScreenNoticeDao extends CrudDao<MesScreenNotice> {
 
 	List<MesScreenNotice> findEnabledList(@Param("isEnabled") String isEnabled);
+
+	int enableDuePublish(@Param("now") Date now);
 }

+ 15 - 2
src/main/java/com/jeesite/modules/mes/entity/MesScreenHonor.java

@@ -1,11 +1,13 @@
 package com.jeesite.modules.mes.entity;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 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;
 
 import javax.validation.constraints.Size;
+import java.util.Date;
 
 /**
  * 大屏荣誉墙 Entity
@@ -17,15 +19,16 @@ import javax.validation.constraints.Size;
 		@Column(name="honor_title", attrName="honorTitle", label="奖项标题", queryType=QueryType.LIKE),
 		@Column(name="emp_name", attrName="empName", label="姓名", queryType=QueryType.LIKE),
 		@Column(name="dept_name", attrName="deptName", label="部门", queryType=QueryType.LIKE),
+		@Column(name="publish_date", attrName="publishDate", label="发布时间"),
 		@Column(name="sort_order", attrName="sortOrder", label="排序", isQuery=false),
 		@Column(name="is_enabled", attrName="isEnabled", label="是否上屏"),
-		@Column(name="status", attrName="status", label="状态", isUpdate=false, isQuery=false),
+		@Column(name="status", attrName="status", label="状态", isUpdate=false),
 		@Column(name="create_by", attrName="createBy", label="创建者", isUpdate=false, isQuery=false),
 		@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false, isUpdateForce=true),
 		@Column(name="update_by", attrName="updateBy", label="更新者", isQuery=false),
 		@Column(name="update_date", attrName="updateDate", label="更新时间", isQuery=false, isUpdateForce=true),
 		@Column(name="remarks", attrName="remarks", label="备注", isQuery=false),
-	}, orderBy="a.sort_order ASC, a.update_date DESC"
+	}, orderBy="a.sort_order ASC, a.publish_date DESC, a.update_date DESC"
 )
 public class MesScreenHonor extends DataEntity<MesScreenHonor> {
 
@@ -33,6 +36,7 @@ public class MesScreenHonor extends DataEntity<MesScreenHonor> {
 	private String honorTitle;
 	private String empName;
 	private String deptName;
+	private Date publishDate;
 	private Integer sortOrder;
 	private String isEnabled;
 
@@ -71,6 +75,15 @@ public class MesScreenHonor extends DataEntity<MesScreenHonor> {
 		this.deptName = deptName;
 	}
 
+	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	public Date getPublishDate() {
+		return publishDate;
+	}
+
+	public void setPublishDate(Date publishDate) {
+		this.publishDate = publishDate;
+	}
+
 	public Integer getSortOrder() {
 		return sortOrder;
 	}

+ 2 - 2
src/main/java/com/jeesite/modules/mes/entity/MesScreenNotice.java

@@ -18,10 +18,10 @@ import java.util.Date;
 		@Column(name="id", attrName="id", label="主键", isPK=true),
 		@Column(name="title", attrName="title", label="标题", queryType=QueryType.LIKE),
 		@Column(name="content", attrName="content", label="通知正文", queryType=QueryType.LIKE),
-		@Column(name="publish_date", attrName="publishDate", label="发布日期"),
+		@Column(name="publish_date", attrName="publishDate", label="发布时间"),
 		@Column(name="sort_order", attrName="sortOrder", label="排序", isQuery=false),
 		@Column(name="is_enabled", attrName="isEnabled", label="是否上屏"),
-		@Column(name="status", attrName="status", label="状态", isUpdate=false, isQuery=false),
+		@Column(name="status", attrName="status", label="状态", isUpdate=false),
 		@Column(name="create_by", attrName="createBy", label="创建者", isUpdate=false, isQuery=false),
 		@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false, isUpdateForce=true),
 		@Column(name="update_by", attrName="updateBy", label="更新者", isQuery=false),

+ 30 - 0
src/main/java/com/jeesite/modules/mes/erp/ErpProductionOrder.java

@@ -37,6 +37,12 @@ public class ErpProductionOrder implements Serializable {
 	private String planFinishDate;
 	private String businessStatus;
 	private String businessStatusName;
+	/** 金蝶领料套数 */
+	private BigDecimal pickMtrlQty;
+	/** 金蝶领料状态码 */
+	private String pickStatus;
+	/** 领料状态:未领料 / 部分领料 / 全部领料 / 超额领料 */
+	private String pickStatusName;
 	private String stockName;
 	private String bomNumber;
 	private String routingNumber;
@@ -263,6 +269,30 @@ public class ErpProductionOrder implements Serializable {
 		this.businessStatusName = businessStatusName;
 	}
 
+	public BigDecimal getPickMtrlQty() {
+		return pickMtrlQty;
+	}
+
+	public void setPickMtrlQty(BigDecimal pickMtrlQty) {
+		this.pickMtrlQty = pickMtrlQty;
+	}
+
+	public String getPickStatus() {
+		return pickStatus;
+	}
+
+	public void setPickStatus(String pickStatus) {
+		this.pickStatus = pickStatus;
+	}
+
+	public String getPickStatusName() {
+		return pickStatusName;
+	}
+
+	public void setPickStatusName(String pickStatusName) {
+		this.pickStatusName = pickStatusName;
+	}
+
 	public String getStockName() {
 		return stockName;
 	}

+ 222 - 17
src/main/java/com/jeesite/modules/mes/erp/ErpProductionOrderService.java

@@ -13,6 +13,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -34,6 +35,13 @@ public class ErpProductionOrderService {
 	private final ConcurrentHashMap<String, ViewDetailCacheEntry> viewCategoryCache = new ConcurrentHashMap<>();
 	/** BillQuery 存货类别字段不可用时会自动降级为 View 兜底 */
 	private volatile boolean billQueryCategoryFieldDisabled = false;
+	/**
+	 * 生产订单「领料套数」BillQuery 字段(金蝶列表领料状态据此计算)。
+	 * 勿加入已确认不存在的标识(如 FPickMtrlQty),否则会反复触发元数据报错。
+	 */
+	private static final List<String> PICK_EXTRA_FIELD_CANDIDATES = Arrays.asList(
+			"FIssueQty", "FPickMtrlStatus");
+	private final Set<String> disabledPickExtraFields = ConcurrentHashMap.newKeySet();
 	private static final String HEADER_FIELD_KEYS = String.join(",",
 			"FID",
 			"FBILLNO",
@@ -243,14 +251,14 @@ public class ErpProductionOrderService {
 			int startRow, int limit) {
 		JSONObject data = new JSONObject();
 		data.put("FormId", FORM_ID);
-		data.put("FieldKeys", DETAIL_FIELD_KEYS);
+		data.put("FieldKeys", buildDetailFieldKeys());
 		data.put("FilterString", buildMaterialNumberFilter(billNo, materialNumbers));
 		data.put("OrderString", "FDate DESC,FBILLNO DESC,FTreeEntity_FSeq");
 		data.put("StartRow", Math.max(startRow, 0));
 		data.put("Limit", Math.max(limit, 1));
 		logger.info("ERP production order material-filter query: {}", data.toJSONString());
 
-		JSONArray rows = erpClient.billQuery(data);
+		JSONArray rows = executeDetailBillQuery(data, false);
 		List<ErpProductionOrder> list = new ArrayList<>();
 		for (int i = 0; i < rows.size(); i++) {
 			list.add(toDetail(rows.getJSONObject(i), i));
@@ -404,6 +412,9 @@ public class ErpProductionOrderService {
 		if (!isBillQueryCategoryFieldError(ex)) {
 			return false;
 		}
+		if (billQueryCategoryFieldDisabled) {
+			return true;
+		}
 		billQueryCategoryFieldDisabled = true;
 		logger.warn("ERP BillQuery 存货类别字段 {} 不可用,已切换为 View 兜底:{}",
 				erpProperties.getInventoryCategoryField(), ex.getMessage());
@@ -412,24 +423,37 @@ public class ErpProductionOrderService {
 
 	private boolean isBillQueryCategoryFieldError(IllegalStateException ex) {
 		String message = ex.getMessage();
-		return message != null && message.contains("不存在");
+		String categoryField = erpProperties.getInventoryCategoryField();
+		return message != null
+				&& message.contains("不存在")
+				&& StringUtils.isNotBlank(categoryField)
+				&& message.contains(categoryField.trim());
 	}
 
 	private JSONArray executeDetailBillQuery(JSONObject data, boolean strictCategoryField) {
-		try {
-			return erpClient.billQuery(data);
-		} catch (IllegalStateException ex) {
-			String categoryField = erpProperties.getInventoryCategoryField();
-			if (disableBillQueryCategoryFieldIfInvalid(ex)) {
-				if (strictCategoryField) {
-					throw ex;
-				}
-				data.put("FieldKeys", DETAIL_FIELD_KEYS);
-				data.put("FilterString", stripCategoryFilter(data.getString("FilterString"), categoryField));
+		int attempts = 0;
+		while (attempts < 12) {
+			data.put("FieldKeys", buildDetailFieldKeys());
+			try {
 				return erpClient.billQuery(data);
+			} catch (IllegalStateException ex) {
+				attempts++;
+				// 先处理领料扩展字段缺失,避免误判成存货类别字段不可用
+				if (disableMissingPickExtraField(ex)) {
+					continue;
+				}
+				if (disableBillQueryCategoryFieldIfInvalid(ex)) {
+					if (strictCategoryField) {
+						throw ex;
+					}
+					String categoryField = erpProperties.getInventoryCategoryField();
+					data.put("FilterString", stripCategoryFilter(data.getString("FilterString"), categoryField));
+					continue;
+				}
+				throw ex;
 			}
-			throw ex;
 		}
+		throw new IllegalStateException("ERP BillQuery 多次重试后仍失败");
 	}
 
 	private String stripCategoryFilter(String filterString, String categoryField) {
@@ -754,6 +778,11 @@ public class ErpProductionOrderService {
 		order.setWorkshopName(detail.getWorkshopName());
 		order.setPlannerName(detail.getPlannerName());
 		order.setInventoryCategory(detail.getInventoryCategory());
+		order.setBusinessStatus(detail.getBusinessStatus());
+		order.setBusinessStatusName(detail.getBusinessStatusName());
+		order.setPickMtrlQty(detail.getPickMtrlQty());
+		order.setPickStatus(detail.getPickStatus());
+		order.setPickStatusName(detail.getPickStatusName());
 		return order;
 	}
 
@@ -786,6 +815,9 @@ public class ErpProductionOrderService {
 		order.setPlanFinishDate(formatErpDate(row.getString("FPlanFinishDate")));
 		order.setBusinessStatus(row.getString("FStatus"));
 		order.setBusinessStatusName(businessStatusName(order.getBusinessStatus()));
+		order.setPickMtrlQty(firstDecimal(row, "FIssueQty"));
+		order.setPickStatus(firstNonBlank(row.getString("FPickMtrlStatus")));
+		order.setPickStatusName(resolvePickStatusName(order.getPickStatus(), order.getPickMtrlQty(), order.getQty()));
 		order.setStockName(row.getString("FStockId.FNAME"));
 		order.setBomNumber(row.getString("FBomId.FNUMBER"));
 		order.setRoutingNumber(row.getString("FRoutingId.FNUMBER"));
@@ -906,6 +938,19 @@ public class ErpProductionOrderService {
 			if (qty != null) {
 				summary.totalQty = summary.totalQty.add(qty);
 			}
+			String entryStatus = firstNonBlank(entry.getString("Status"), entry.getString("FStatus"));
+			String statusName = businessStatusName(entryStatus);
+			if (StringUtils.isNotBlank(statusName) && !summary.businessStatusNames.contains(statusName)) {
+				summary.businessStatusNames.add(statusName);
+			}
+			BigDecimal pickQty = firstDecimal(entry, "IssueQty", "FIssueQty");
+			String pickStatus = firstNonBlank(
+					entry.getString("PickMtrlStatus"),
+					entry.getString("FPickMtrlStatus"));
+			String pickStatusName = resolvePickStatusName(pickStatus, pickQty, qty);
+			if (StringUtils.isNotBlank(pickStatusName) && !summary.pickStatusNames.contains(pickStatusName)) {
+				summary.pickStatusNames.add(pickStatusName);
+			}
 		}
 		return summary;
 	}
@@ -983,6 +1028,22 @@ public class ErpProductionOrderService {
 		return "";
 	}
 
+	private BigDecimal firstDecimal(JSONObject row, String... keys) {
+		if (row == null || keys == null) {
+			return null;
+		}
+		for (String key : keys) {
+			if (StringUtils.isBlank(key)) {
+				continue;
+			}
+			BigDecimal value = row.getBigDecimal(key);
+			if (value != null) {
+				return ErpKingdeeParseUtils.normalizeQtyNullable(value);
+			}
+		}
+		return null;
+	}
+
 	/** BillQuery 明细行优先取 FWorkShopID,表头 FWorkShopID0 兜底 */
 	private String readWorkshopName(JSONObject row) {
 		return firstNonBlank(
@@ -1007,6 +1068,8 @@ public class ErpProductionOrderService {
 		if (StringUtils.isBlank(header.getPlannerName())) {
 			header.setPlannerName(detail.getPlannerName());
 		}
+		mergeBusinessStatusName(header, detail.getBusinessStatus(), detail.getBusinessStatusName());
+		mergePickStatusName(header, detail.getPickStatusName());
 	}
 
 	private void mergeHeaderFieldsFromSummary(ErpProductionOrder header, ViewDetailSummary summary) {
@@ -1019,6 +1082,53 @@ public class ErpProductionOrderService {
 		if (StringUtils.isBlank(header.getPlannerName())) {
 			header.setPlannerName(summary.plannerName);
 		}
+		if (StringUtils.isBlank(header.getBusinessStatusName()) && !summary.businessStatusNames.isEmpty()) {
+			header.setBusinessStatusName(String.join(" / ", summary.businessStatusNames));
+		}
+		if (StringUtils.isBlank(header.getPickStatusName()) && !summary.pickStatusNames.isEmpty()) {
+			header.setPickStatusName(String.join(" / ", summary.pickStatusNames));
+		}
+	}
+
+	private void mergeBusinessStatusName(ErpProductionOrder header, String status, String statusName) {
+		String name = StringUtils.isNotBlank(statusName) ? statusName.trim() : businessStatusName(status);
+		if (StringUtils.isBlank(name)) {
+			return;
+		}
+		if (StringUtils.isBlank(header.getBusinessStatusName())) {
+			header.setBusinessStatus(status);
+			header.setBusinessStatusName(name);
+			return;
+		}
+		Set<String> names = new LinkedHashSet<>();
+		for (String part : header.getBusinessStatusName().split(" / ")) {
+			if (StringUtils.isNotBlank(part)) {
+				names.add(part.trim());
+			}
+		}
+		if (names.add(name)) {
+			header.setBusinessStatusName(String.join(" / ", names));
+		}
+	}
+
+	private void mergePickStatusName(ErpProductionOrder header, String pickStatusName) {
+		if (header == null || StringUtils.isBlank(pickStatusName)) {
+			return;
+		}
+		String name = pickStatusName.trim();
+		if (StringUtils.isBlank(header.getPickStatusName())) {
+			header.setPickStatusName(name);
+			return;
+		}
+		Set<String> names = new LinkedHashSet<>();
+		for (String part : header.getPickStatusName().split(" / ")) {
+			if (StringUtils.isNotBlank(part)) {
+				names.add(part.trim());
+			}
+		}
+		if (names.add(name)) {
+			header.setPickStatusName(String.join(" / ", names));
+		}
 	}
 
 	private boolean isAllowedCategory(String value) {
@@ -1120,14 +1230,56 @@ public class ErpProductionOrderService {
 	}
 
 	private String buildDetailFieldKeys() {
-		if (!useBillQueryCategoryField()) {
-			return DETAIL_FIELD_KEYS;
+		String keys = DETAIL_FIELD_KEYS;
+		if (useBillQueryCategoryField()) {
+			keys = keys + "," + erpProperties.getInventoryCategoryField().trim();
+		}
+		String pickFields = getEnabledPickExtraFields();
+		if (StringUtils.isNotBlank(pickFields)) {
+			keys = keys + "," + pickFields;
+		}
+		return keys;
+	}
+
+	private String getEnabledPickExtraFields() {
+		List<String> enabled = new ArrayList<>();
+		for (String field : PICK_EXTRA_FIELD_CANDIDATES) {
+			if (!disabledPickExtraFields.contains(field)) {
+				enabled.add(field);
+			}
 		}
-		return DETAIL_FIELD_KEYS + "," + erpProperties.getInventoryCategoryField().trim();
+		return String.join(",", enabled);
+	}
+
+	private boolean disableMissingPickExtraField(IllegalStateException ex) {
+		String message = ex.getMessage();
+		if (message == null || !message.contains("不存在")) {
+			return false;
+		}
+		for (String field : PICK_EXTRA_FIELD_CANDIDATES) {
+			if (!disabledPickExtraFields.contains(field) && messageContainsField(message, field)) {
+				disabledPickExtraFields.add(field);
+				logger.warn("ERP BillQuery 生产订单字段 {} 不可用,已跳过", field);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean messageContainsField(String message, String field) {
+		if (StringUtils.isBlank(message) || StringUtils.isBlank(field)) {
+			return false;
+		}
+		return message.contains("标识为" + field)
+				|| message.contains("\"" + field + "\"")
+				|| message.contains("'" + field + "'")
+				|| message.contains(field);
 	}
 
 	private static class ViewDetailSummary {
 		private final Map<String, String> categories = new LinkedHashMap<>();
+		private final List<String> businessStatusNames = new ArrayList<>();
+		private final List<String> pickStatusNames = new ArrayList<>();
 		private int entryCount;
 		private BigDecimal totalQty = BigDecimal.ZERO;
 		private String workshopName = "";
@@ -1191,6 +1343,59 @@ public class ErpProductionOrderService {
 		if ("6".equals(status)) {
 			return "结案";
 		}
+		if ("7".equals(status)) {
+			return "结算";
+		}
 		return status;
 	}
+
+	private String resolvePickStatusName(String status, BigDecimal pickQty, BigDecimal orderQty) {
+		String mapped = pickStatusName(status);
+		if (StringUtils.isNotBlank(mapped)) {
+			return mapped;
+		}
+		return computePickStatusName(pickQty, orderQty);
+	}
+
+	private String pickStatusName(String status) {
+		if (StringUtils.isBlank(status)) {
+			return "";
+		}
+		String trimmed = status.trim();
+		if ("未领料".equals(trimmed) || "部分领料".equals(trimmed)
+				|| "全部领料".equals(trimmed) || "超额领料".equals(trimmed)) {
+			return trimmed;
+		}
+		if ("0".equals(trimmed) || "1".equals(trimmed)) {
+			return "未领料";
+		}
+		if ("2".equals(trimmed)) {
+			return "部分领料";
+		}
+		if ("3".equals(trimmed)) {
+			return "全部领料";
+		}
+		if ("4".equals(trimmed)) {
+			return "超额领料";
+		}
+		return "";
+	}
+
+	private String computePickStatusName(BigDecimal pickQty, BigDecimal orderQty) {
+		if (pickQty == null) {
+			return "";
+		}
+		BigDecimal qty = orderQty == null ? BigDecimal.ZERO : orderQty;
+		if (pickQty.compareTo(BigDecimal.ZERO) <= 0) {
+			return "未领料";
+		}
+		int cmp = pickQty.compareTo(qty);
+		if (cmp < 0) {
+			return "部分领料";
+		}
+		if (cmp == 0) {
+			return "全部领料";
+		}
+		return "超额领料";
+	}
 }

+ 32 - 4
src/main/java/com/jeesite/modules/mes/service/MesScreenHonorService.java

@@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -54,17 +55,44 @@ public class MesScreenHonorService extends CrudService<MesScreenHonorDao, MesScr
 		if (mesScreenHonor.getSortOrder() == null) {
 			mesScreenHonor.setSortOrder(0);
 		}
-		if (StringUtils.isBlank(mesScreenHonor.getIsEnabled())) {
-			mesScreenHonor.setIsEnabled("1");
-		}
+		applyPublishOnSave(mesScreenHonor);
 		super.save(mesScreenHonor);
 		FileUploadUtils.saveFileUpload(mesScreenHonor, mesScreenHonor.getId(), BIZ_TYPE_IMAGE);
 	}
 
+	/**
+	 * 发布时间未到前暂不上屏,到达发布时间后由定时任务自动启用。
+	 */
+	private void applyPublishOnSave(MesScreenHonor mesScreenHonor) {
+		Date publishDate = mesScreenHonor.getPublishDate();
+		if (publishDate != null && publishDate.after(new Date())) {
+			mesScreenHonor.setIsEnabled("0");
+		} else if (StringUtils.isBlank(mesScreenHonor.getIsEnabled())) {
+			mesScreenHonor.setIsEnabled("1");
+		}
+	}
+
+	@Transactional
+	public void autoPublishDue() {
+		dao.enableDuePublish(new Date());
+	}
+
 	@Override
 	@Transactional
 	public void delete(MesScreenHonor mesScreenHonor) {
-		super.delete(mesScreenHonor);
+		if (mesScreenHonor == null || StringUtils.isBlank(mesScreenHonor.getId())) {
+			return;
+		}
+		FileUpload fu = new FileUpload();
+		fu.setBizKey(mesScreenHonor.getId());
+		fu.setBizType(BIZ_TYPE_IMAGE);
+		List<FileUpload> files = fileUploadService.findList(fu);
+		if (ListUtils.isNotEmpty(files)) {
+			for (FileUpload file : files) {
+				fileUploadService.delete(file);
+			}
+		}
+		dao.phyDelete(mesScreenHonor);
 	}
 
 	/**

+ 22 - 3
src/main/java/com/jeesite/modules/mes/service/MesScreenNoticeService.java

@@ -11,6 +11,7 @@ import com.jeesite.modules.mes.entity.MesScreenNotice;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -43,16 +44,34 @@ public class MesScreenNoticeService extends CrudService<MesScreenNoticeDao, MesS
 		if (mesScreenNotice.getSortOrder() == null) {
 			mesScreenNotice.setSortOrder(0);
 		}
-		if (StringUtils.isBlank(mesScreenNotice.getIsEnabled())) {
+		applyPublishOnSave(mesScreenNotice);
+		super.save(mesScreenNotice);
+	}
+
+	/**
+	 * 发布时间未到前暂不上屏,到达发布时间后由定时任务自动启用。
+	 */
+	private void applyPublishOnSave(MesScreenNotice mesScreenNotice) {
+		Date publishDate = mesScreenNotice.getPublishDate();
+		if (publishDate != null && publishDate.after(new Date())) {
+			mesScreenNotice.setIsEnabled("0");
+		} else if (StringUtils.isBlank(mesScreenNotice.getIsEnabled())) {
 			mesScreenNotice.setIsEnabled("1");
 		}
-		super.save(mesScreenNotice);
+	}
+
+	@Transactional
+	public void autoPublishDue() {
+		dao.enableDuePublish(new Date());
 	}
 
 	@Override
 	@Transactional
 	public void delete(MesScreenNotice mesScreenNotice) {
-		super.delete(mesScreenNotice);
+		if (mesScreenNotice == null || StringUtils.isBlank(mesScreenNotice.getId())) {
+			return;
+		}
+		dao.phyDelete(mesScreenNotice);
 	}
 
 	/**

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

@@ -2017,7 +2017,7 @@ public class MesProductRecordController extends BaseController {
 
 		if(mesLineProcess1.getQuality().equals("0") && !ret.equals(bs+"OK") && !ret.equals(bs+"NG")){ // 不防呆
 			ret = bs+"UD";
-			return ret;
+			return apply115Op180TjTimeGate(ret, sn, lineSn, oprno, lists);
 		}
 
 		if(mesLineProcess1.getRepeat().equals("1") && (ret.equals(bs+"OK") || ret.equals(bs+"NG"))){ // 可重复工作
@@ -2074,16 +2074,71 @@ public class MesProductRecordController extends BaseController {
 		if (!ObjectUtils.isEmpty(mesProductProgressc1)){
 			if ("1".equals(mesProductProgressc1.getState())){
 				ret = bs+"UD";
-				return ret;
+				return apply115Op180TjTimeGate(ret, sn, lineSn, oprno, lists);
 			}else if("0".equals(mesProductProgressc1.getState())){
 				ret = bs+"RK";
 				return ret;
 			}
 		}
 
+		return apply115Op180TjTimeGate(ret, sn, lineSn, oprno, lists);
+	}
+
+	/**
+	 * 115产线:OP150加工完成后,须等待系统参数 mes.tjTime(分钟)后,OP180才可加工。
+	 */
+	private String apply115Op180TjTimeGate(String ret, String sn, String lineSn, String oprno, List<MesProductRecord> lists) {
+		if (StringUtils.isEmpty(ret) || ret.length() < 5 || !"UD".equals(ret.substring(3, 5))) {
+			return ret;
+		}
+		if (!is115LineSn(lineSn) || !"OP180".equals(CommonUitl.formatOprno(oprno))) {
+			return ret;
+		}
+		String tjTime = Global.getConfig("mes.tjTime");
+		if (StringUtils.isEmpty(tjTime) || "0".equals(tjTime.trim())) {
+			return ret;
+		}
+		try {
+			int needMinutes = Integer.parseInt(tjTime.trim());
+			if (needMinutes <= 0) {
+				return ret;
+			}
+			Date op150OkTime = null;
+			if (!ListUtils.isEmpty(lists)) {
+				for (MesProductRecord mpr : lists) {
+					if (mpr.getOprno() != null
+							&& "OP150".equals(CommonUitl.formatOprno(mpr.getOprno()))
+							&& "OK".equals(mpr.getContent())
+							&& mpr.getUpdateDate() != null) {
+						op150OkTime = mpr.getUpdateDate();
+						break;
+					}
+				}
+			}
+			if (op150OkTime == null) {
+				// 无OP150合格时间时按前工位未加工处理
+				return "150QD";
+			}
+			long minutesBetween = ChronoUnit.MINUTES.between(op150OkTime.toInstant(), new Date().toInstant());
+			if (minutesBetween < needMinutes) {
+				logger.info("115 OP180涂胶固化未到: sn={}, op150Time={}, elapsed={}min, need={}min",
+						sn, op150OkTime, minutesBetween, needMinutes);
+				return ret.substring(0, 3) + "TJ";
+			}
+		} catch (Exception e) {
+			logger.warn("115 OP180涂胶固化时间校验异常 sn=" + sn, e);
+		}
 		return ret;
 	}
 
+	private boolean is115LineSn(String lineSn) {
+		if (StringUtils.isEmpty(lineSn)) {
+			return false;
+		}
+		String normalized = mesProductRecordService.normalizeLineSn(lineSn);
+		return "115XT".equalsIgnoreCase(normalized) || normalized.toUpperCase().contains("115");
+	}
+
 	//上传质量结果
 	//msg=aaaabbbbbABWMQDWGWOP040 GY100000ID151245P00000106200123062900001      RSOKDA2023-08-18ZT14:32:33YHjinjushijinjushi1111
 	//msg=aaaabbbbbABWMQDWGWOP080 GY100000LX  ID151245P00000106200123062900001      RSOKDA2023-08-18ZT14:32:33YHjinjushijinjushi111105Y11111111N22222222Y33333333Y44444444Y55555555
@@ -2139,6 +2194,22 @@ public class MesProductRecordController extends BaseController {
 	}
 
 	private String updateQualityCommon(MesLineProcess mesLineProcess1,String oprno,String lineSn,String sn,String craft,String content,String userCode,List<ParamsResp> params){
+		if(!mesLineProcess1.getType().equals("3") && "100000".equals(craft)
+				&& is115LineSn(lineSn) && "OP180".equals(CommonUitl.formatOprno(oprno))){
+			MesProductRecord mpr1 = new MesProductRecord();
+			mpr1.setCraft("100000");
+			mpr1.setLineSn(lineSn);
+			mpr1.setSn(sn);
+			List<MesProductRecord> lists = mesProductRecordService.findList(mpr1);
+			String gate = apply115Op180TjTimeGate("RS UD", sn, lineSn, oprno, lists);
+			if (!"UD".equals(gate.substring(3, 5))) {
+				String code = gate.substring(3, 5);
+				if ("QD".equals(code)) {
+					return "RSQD";
+				}
+				return "RS" + code;
+			}
+		}
 		if(mesLineProcess1.getType().equals("3")){ // 单部件
 			List<BindMaterialResp> bmlists = mesLineProcessMaterialService.getBindMaterial(oprno, lineSn);
 			mesProductRecordService.updateRecordResult(sn,oprno,craft,"",content,userCode,params,lineSn,true,bmlists);

+ 5 - 1
src/main/java/com/jeesite/modules/mes/web/MesRepairController.java

@@ -16,6 +16,7 @@ import com.jeesite.modules.mes.entity.*;
 import com.jeesite.modules.mes.resp.CommonResp;
 import com.jeesite.modules.mes.service.*;
 import com.jeesite.modules.mes.util.CommonUitl;
+import com.jeesite.modules.mes.util.Utf8DisplayUtils;
 import com.jeesite.modules.sys.entity.User;
 import com.jeesite.modules.sys.utils.UserUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -160,6 +161,9 @@ public class MesRepairController extends BaseController {
 		MesRepairQuality mesRepairQuality = new MesRepairQuality();
 		mesRepairQuality.setRepairId(mesRepair.getId());
 		MesRepairQuality quality = mesRepairQualityService.findInfo(mesRepairQuality);
+		// 详情页走模板渲染,不经 JSON Advice;对 remark 等历史乱码做展示还原
+		Utf8DisplayUtils.repairGraph(mesRepair);
+		Utf8DisplayUtils.repairGraph(quality);
 		model.addAttribute("mesRepair", mesRepair);
 		model.addAttribute("quality", quality);
 		return "modules/mes/mesRepairInfo";
@@ -687,7 +691,7 @@ public class MesRepairController extends BaseController {
 		}
 		mesRepair2.setLineSn(mesProductRecordService.normalizeLineSn(lineSn));
 		mesRepair2.setItemId(itemId);
-		mesRepair2.setRemark(remark);
+		mesRepair2.setRemark(Utf8DisplayUtils.repair(remark));
 		mesRepair2.setOprno(oprno);
 		mesRepair2.setType(type);
 		if(type.equals("1")){ // 在线返修

+ 9 - 1
src/main/java/com/jeesite/modules/mes/web/MesScreenHonorController.java

@@ -13,10 +13,12 @@ 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.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
 
 /**
  * 大屏荣誉墙 Controller
@@ -48,6 +50,7 @@ public class MesScreenHonorController extends BaseController {
 	public Page<MesScreenHonor> listData(MesScreenHonor mesScreenHonor, HttpServletRequest request,
 			HttpServletResponse response) {
 		mesScreenHonor.setPage(new Page<>(request, response));
+		mesScreenHonor.setStatus(MesScreenHonor.STATUS_NORMAL);
 		return mesScreenHonorService.findPage(mesScreenHonor);
 	}
 
@@ -56,6 +59,7 @@ public class MesScreenHonorController extends BaseController {
 	public String form(MesScreenHonor mesScreenHonor, Model model) {
 		if (mesScreenHonor.getIsNewRecord()) {
 			mesScreenHonor.setHonorTitle("闪耀之星");
+			mesScreenHonor.setPublishDate(new Date());
 			mesScreenHonor.setIsEnabled("1");
 			mesScreenHonor.setSortOrder(0);
 		}
@@ -74,7 +78,11 @@ public class MesScreenHonorController extends BaseController {
 	@RequiresPermissions("mes:mesScreenHonor:edit")
 	@RequestMapping(value = "delete")
 	@ResponseBody
-	public String delete(MesScreenHonor mesScreenHonor) {
+	public String delete(@RequestParam String id) {
+		MesScreenHonor mesScreenHonor = mesScreenHonorService.get(id);
+		if (mesScreenHonor == null || mesScreenHonor.getIsNewRecord()) {
+			return renderResult(Global.FALSE, text("删除失败,记录不存在!"));
+		}
 		mesScreenHonorService.delete(mesScreenHonor);
 		return renderResult(Global.TRUE, text("删除荣誉榜单成功!"));
 	}

+ 9 - 1
src/main/java/com/jeesite/modules/mes/web/MesScreenNoticeController.java

@@ -13,10 +13,12 @@ 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.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
 
 /**
  * 大屏通知栏 Controller
@@ -48,6 +50,7 @@ public class MesScreenNoticeController extends BaseController {
 	public Page<MesScreenNotice> listData(MesScreenNotice mesScreenNotice, HttpServletRequest request,
 			HttpServletResponse response) {
 		mesScreenNotice.setPage(new Page<>(request, response));
+		mesScreenNotice.setStatus(MesScreenNotice.STATUS_NORMAL);
 		return mesScreenNoticeService.findPage(mesScreenNotice);
 	}
 
@@ -55,6 +58,7 @@ public class MesScreenNoticeController extends BaseController {
 	@RequestMapping(value = "form")
 	public String form(MesScreenNotice mesScreenNotice, Model model) {
 		if (mesScreenNotice.getIsNewRecord()) {
+			mesScreenNotice.setPublishDate(new Date());
 			mesScreenNotice.setIsEnabled("1");
 			mesScreenNotice.setSortOrder(0);
 		}
@@ -73,7 +77,11 @@ public class MesScreenNoticeController extends BaseController {
 	@RequiresPermissions("mes:mesScreenNotice:edit")
 	@RequestMapping(value = "delete")
 	@ResponseBody
-	public String delete(MesScreenNotice mesScreenNotice) {
+	public String delete(@RequestParam String id) {
+		MesScreenNotice mesScreenNotice = mesScreenNoticeService.get(id);
+		if (mesScreenNotice == null || mesScreenNotice.getIsNewRecord()) {
+			return renderResult(Global.FALSE, text("删除失败,记录不存在!"));
+		}
 		mesScreenNoticeService.delete(mesScreenNotice);
 		return renderResult(Global.TRUE, text("删除大屏通知成功!"));
 	}

+ 27 - 0
src/main/java/com/jeesite/modules/scheduling/MesScreenPublishScheduling.java

@@ -0,0 +1,27 @@
+package com.jeesite.modules.scheduling;
+
+import com.jeesite.modules.mes.service.MesScreenHonorService;
+import com.jeesite.modules.mes.service.MesScreenNoticeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * 大屏通知、荣誉榜单定时自动上屏
+ */
+@Configuration
+@EnableScheduling
+public class MesScreenPublishScheduling {
+
+	@Autowired
+	private MesScreenNoticeService mesScreenNoticeService;
+	@Autowired
+	private MesScreenHonorService mesScreenHonorService;
+
+	@Scheduled(cron = "0 * * * * ?")
+	public void autoPublishDue() {
+		mesScreenNoticeService.autoPublishDue();
+		mesScreenHonorService.autoPublishDue();
+	}
+}

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

@@ -52,6 +52,8 @@ public class ErrorMsg {
                 lmsg = "恒温4h时间未到";
             }else if(processMsgRet.equalsIgnoreCase("NL")) {
                 lmsg = "恒温4h未扫码";
+            }else if(processMsgRet.equalsIgnoreCase("TJ")) {
+                lmsg = "涂胶固化时间未到";
             } else if (processMsgRet.equalsIgnoreCase("PZ")) {
                 lmsg = "请先上传照片";
             } else if (processMsgRet.equalsIgnoreCase("SJ")) {

+ 11 - 6
src/main/resources/config/application.yml

@@ -52,12 +52,12 @@ erp:
   k3cloud:
     base-url: https://erp.anhuidayang.com:8800/k3cloud
 #    生产环境
-#    acct-id: 672630265043d5
+    acct-id: 672630265043d5
 #    测试环境
-    acct-id: 6a239b82159033
+#    acct-id: 6a239b82159033
     username: 经博
-#    password: JingBo@030323
-    password: dy123456.
+    password: JingBo@030323
+#    password: dy123456.
     org-number: 110
     filter-current-org: true
     inventory-category-filter-enabled: true
@@ -124,7 +124,8 @@ erp:
       link-table: T_PRD_MOENTRY
     # ERP 排产计划:下推选分录时按以下成品物料编码过滤
     schedule:
-      material-numbers: 8.10.HEV.05.049025,8.35.115.05.5003146600021
+      material-numbers: 8.10.HEV.10.047696,8.10.HEV.10.049025,8.35.115.10.5003146600021
+#      material-numbers: 8.10.HEV.05.049025,8.35.115.05.5003146600021
 
 #======================================#
 #========== Server settings ===========#
@@ -169,11 +170,12 @@ jdbc:
   driver: com.mysql.cj.jdbc.Driver
  # url: jdbc:mysql://127.0.0.1:3306/ce_liu?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
 #  url: jdbc:mysql://127.0.0.1:3306/mes_cloude_npd?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
+#  url: jdbc:mysql://127.0.0.1:3306/mes_cloud_ahdy?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
   url: jdbc:mysql://192.168.9.181:3306/mes_cloud?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
   username: mes_cloud
   password: s2ENj7KaEySTC7dW
 #  username: root
- # password: 123456
+#  password: 123456
   testSql: SELECT 1
 
   #  # Oracle 数据库配置(若使用 12c,请修改 /modules/core/pom.xml 文件,打开 12c 依赖,去掉 11g 依赖)
@@ -1078,7 +1080,10 @@ file:
   enabled: true
 
   #  # 文件上传根路径,设置路径中不允许包含“userfiles”,在指定目录中系统会自动创建userfiles目录,如果不设置默认为contextPath路径
+  # 服务器
   baseDir: E:/mescloud
+  # 本地
+#  baseDir: D:/mescloud
   #  baseDir: /www/wwwroot/mes_cloud_dy
   #
   #  # 上传文件的相对路径(支持:yyyy, MM, dd, HH, mm, ss, E)

+ 14 - 1
src/main/resources/mappings/modules/mes/MesScreenHonorDao.xml

@@ -8,6 +8,7 @@
 			a.honor_title AS honorTitle,
 			a.emp_name AS empName,
 			a.dept_name AS deptName,
+			a.publish_date AS publishDate,
 			a.sort_order AS sortOrder,
 			a.is_enabled AS isEnabled,
 			a.status,
@@ -19,6 +20,18 @@
 		FROM mes_screen_honor a
 		WHERE a.is_enabled = #{isEnabled}
 		  AND a.status = '0'
-		ORDER BY a.sort_order ASC, a.update_date DESC
+		  AND (a.publish_date IS NULL OR a.publish_date &lt;= NOW())
+		ORDER BY a.sort_order ASC, a.publish_date DESC, a.update_date DESC
 	</select>
+
+	<update id="enableDuePublish">
+		UPDATE mes_screen_honor
+		SET is_enabled = '1',
+			update_date = #{now}
+		WHERE is_enabled = '0'
+		  AND publish_date IS NOT NULL
+		  AND publish_date &lt;= #{now}
+		  AND update_date &lt;= publish_date
+		  AND status = '0'
+	</update>
 </mapper>

+ 12 - 0
src/main/resources/mappings/modules/mes/MesScreenNoticeDao.xml

@@ -19,6 +19,18 @@
 		FROM mes_screen_notice a
 		WHERE a.is_enabled = #{isEnabled}
 		  AND a.status = '0'
+		  AND (a.publish_date IS NULL OR a.publish_date &lt;= NOW())
 		ORDER BY a.sort_order ASC, a.publish_date DESC
 	</select>
+
+	<update id="enableDuePublish">
+		UPDATE mes_screen_notice
+		SET is_enabled = '1',
+			update_date = #{now}
+		WHERE is_enabled = '0'
+		  AND publish_date IS NOT NULL
+		  AND publish_date &lt;= #{now}
+		  AND update_date &lt;= publish_date
+		  AND status = '0'
+	</update>
 </mapper>

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

@@ -32,7 +32,7 @@ $('#dataGrid').dataGrid({
 		{header:'${text("生产车间")}', name:'workshopName', index:'workshopName', width:140, align:"left"},
 		{header:'${text("数量")}', name:'qty', index:'qty', width:110, align:"right", formatter: formatErpQty},
 		{header:'${text("单位")}', name:'unitName', index:'unitName', width:90, align:"center"},
-		{header:'${text("业务状态")}', name:'businessStatusName', index:'businessStatusName', width:100, align:"center"},
+		{header:'${text("领料状态")}', name:'pickStatusName', index:'pickStatusName', width:110, align:"center"},
 		{header:'${text("计划开工")}', name:'planStartDate', index:'planStartDate', width:150, align:"center"},
 		{header:'${text("计划完工")}', name:'planFinishDate', index:'planFinishDate', width:150, align:"center"},
 		{header:'${text("入库仓库")}', name:'stockName', index:'stockName', width:140, align:"left"},

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

@@ -81,6 +81,8 @@ $('#dataGrid').dataGrid({
 		}},
 		{header:'${text("单据日期")}', name:'date', index:'date', width:150, align:"center"},
 		{header:'${text("单据状态")}', name:'documentStatusName', index:'documentStatusName', width:100, align:"center"},
+		{header:'${text("业务状态")}', name:'businessStatusName', index:'businessStatusName', width:120, align:"center"},
+		{header:'${text("领料状态")}', name:'pickStatusName', index:'pickStatusName', width:120, align:"center"},
 		{header:'${text("生产组织")}', name:'prdOrgName', index:'prdOrgName', width:180, align:"left"},
 		{header:'${text("存货类别")}', name:'inventoryCategory', index:'inventoryCategory', width:100, align:"center"},
 		{header:'${text("生产车间")}', name:'workshopName', index:'workshopName', width:140, align:"left"},

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

@@ -46,9 +46,11 @@
 					<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>
+								<span class="required">*</span> ${text('发布时间')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="sortOrder" maxlength="5" class="form-control required digits"/>
+								<#form:input path="publishDate" readonly="true" maxlength="20" class="form-control laydate required"
+									dataFormat="datetime" data-type="datetime" data-format="yyyy-MM-dd HH:mm"/>
+								<span class="help-block">${text('到达该时间后自动上屏;未到时间前不会展示在大屏')}</span>
 							</div>
 						</div>
 					</div>
@@ -57,6 +59,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="sortOrder" maxlength="5" class="form-control required digits"/>
+							</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:radio path="isEnabled" dictType="sys_yes_no" class="form-control required"/>

+ 4 - 3
src/main/resources/views/modules/mes/mesScreenHonorList.html

@@ -56,10 +56,11 @@ $('#dataGrid').dataGrid({
 	searchForm: $("#searchForm"),
 	columnModel: [
 		{header:'${text("奖项标题")}', name:'honorTitle', index:'a.honor_title', width:140, align:"center", formatter: function(val, obj, row, act){
-			return '<a href="${ctx}/mes/mesScreenHonor/form?id='+row.id+'" class="btnList" data-title="${text("编辑荣誉榜单")}">'+(val||row.id)+'</a>';
+			return '<a href="${ctx}/mes/mesScreenHonor/form?id='+obj.rowId+'" class="btnList" data-title="${text("编辑荣誉榜单")}">'+(val||obj.rowId)+'</a>';
 		}},
 		{header:'${text("姓名")}', name:'empName', index:'a.emp_name', width:120, align:"center"},
 		{header:'${text("部门")}', name:'deptName', index:'a.dept_name', width:150, align:"center"},
+		{header:'${text("发布时间")}', name:'publishDate', index:'a.publish_date', width:150, align:"center"},
 		{header:'${text("排序")}', name:'sortOrder', index:'a.sort_order', width:80, align:"center"},
 		{header:'${text("是否上屏")}', name:'isEnabled', index:'a.is_enabled', width:80, align:"center", formatter: function(val, obj, row, act){
 			return val == '1' ? '是' : '否';
@@ -68,8 +69,8 @@ $('#dataGrid').dataGrid({
 		{header:'${text("操作")}', name:'actions', width:100, formatter: function(val, obj, row, act){
 			var actions = [];
 			<% if(hasPermi('mes:mesScreenHonor:edit')){ %>
-				actions.push('<a href="${ctx}/mes/mesScreenHonor/form?id='+row.id+'" class="btnList" title="${text("编辑荣誉榜单")}"><i class="fa fa-pencil"></i></a>&nbsp;');
-				actions.push('<a href="${ctx}/mes/mesScreenHonor/delete?id='+row.id+'" class="btnList" title="${text("删除荣誉榜单")}" data-confirm="${text("确认要删除该荣誉吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesScreenHonor/form?id='+obj.rowId+'" class="btnList" title="${text("编辑荣誉榜单")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesScreenHonor/delete?id='+obj.rowId+'" class="btnList" title="${text("删除荣誉榜单")}" data-confirm="${text("确认要删除该荣誉吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
 			<% } %>
 			return actions.join('');
 		}}

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

@@ -26,10 +26,11 @@
 					<div class="col-xs-6">
 						<div class="form-group">
 							<label class="control-label col-sm-4" title="">
-								${text('发布日期')}:<i class="fa icon-question hide"></i></label>
+								<span class="required">*</span> ${text('发布时间')}:<i class="fa icon-question hide"></i></label>
 							<div class="col-sm-8">
-								<#form:input path="publishDate" readonly="true" maxlength="20" class="form-control laydate"
+								<#form:input path="publishDate" readonly="true" maxlength="20" class="form-control laydate required"
 									dataFormat="datetime" data-type="datetime" data-format="yyyy-MM-dd HH:mm"/>
+								<span class="help-block">${text('到达该时间后自动上屏;未到时间前不会展示在大屏')}</span>
 							</div>
 						</div>
 					</div>

+ 4 - 4
src/main/resources/views/modules/mes/mesScreenNoticeList.html

@@ -50,10 +50,10 @@ $('#dataGrid').dataGrid({
 	searchForm: $("#searchForm"),
 	columnModel: [
 		{header:'${text("标题")}', name:'title', index:'a.title', width:150, align:"center", formatter: function(val, obj, row, act){
-			return '<a href="${ctx}/mes/mesScreenNotice/form?id='+row.id+'" class="btnList" data-title="${text("编辑大屏通知")}">'+(val||row.id)+'</a>';
+			return '<a href="${ctx}/mes/mesScreenNotice/form?id='+obj.rowId+'" class="btnList" data-title="${text("编辑大屏通知")}">'+(val||obj.rowId)+'</a>';
 		}},
 		{header:'${text("通知正文")}', name:'content', index:'a.content', width:280, align:"left"},
-		{header:'${text("发布日期")}', name:'publishDate', index:'a.publish_date', width:150, align:"center"},
+		{header:'${text("发布时间")}', name:'publishDate', index:'a.publish_date', width:150, align:"center"},
 		{header:'${text("排序")}', name:'sortOrder', index:'a.sort_order', width:80, align:"center"},
 		{header:'${text("是否上屏")}', name:'isEnabled', index:'a.is_enabled', width:80, align:"center", formatter: function(val, obj, row, act){
 			return val == '1' ? '是' : '否';
@@ -62,8 +62,8 @@ $('#dataGrid').dataGrid({
 		{header:'${text("操作")}', name:'actions', width:100, formatter: function(val, obj, row, act){
 			var actions = [];
 			<% if(hasPermi('mes:mesScreenNotice:edit')){ %>
-				actions.push('<a href="${ctx}/mes/mesScreenNotice/form?id='+row.id+'" class="btnList" title="${text("编辑大屏通知")}"><i class="fa fa-pencil"></i></a>&nbsp;');
-				actions.push('<a href="${ctx}/mes/mesScreenNotice/delete?id='+row.id+'" class="btnList" title="${text("删除大屏通知")}" data-confirm="${text("确认要删除该通知吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesScreenNotice/form?id='+obj.rowId+'" class="btnList" title="${text("编辑大屏通知")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesScreenNotice/delete?id='+obj.rowId+'" class="btnList" title="${text("删除大屏通知")}" data-confirm="${text("确认要删除该通知吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
 			<% } %>
 			return actions.join('');
 		}}