zhanghe vor 5 Monaten
Ursprung
Commit
78151c41ac

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

@@ -0,0 +1,15 @@
+package com.jeesite.modules.mes.dao;
+
+import com.jeesite.common.dao.CrudDao;
+import com.jeesite.common.mybatis.annotation.MyBatisDao;
+import com.jeesite.modules.mes.entity.MesGpy;
+
+/**
+ * 光谱仪数据 DAO接口
+ * @author system
+ * @version 2026-05-21
+ */
+@MyBatisDao
+public interface MesGpyDao extends CrudDao<MesGpy> {
+
+}

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

@@ -0,0 +1,15 @@
+package com.jeesite.modules.mes.dao;
+
+import com.jeesite.common.dao.CrudDao;
+import com.jeesite.common.mybatis.annotation.MyBatisDao;
+import com.jeesite.modules.mes.entity.MesGpyMeas;
+
+/**
+ * 光谱仪元素数据 DAO接口
+ * @author system
+ * @version 2026-05-21
+ */
+@MyBatisDao
+public interface MesGpyMeasDao extends CrudDao<MesGpyMeas> {
+
+}

+ 222 - 0
src/main/java/com/jeesite/modules/mes/entity/MesGpy.java

@@ -0,0 +1,222 @@
+package com.jeesite.modules.mes.entity;
+
+import java.util.Date;
+
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.Table;
+
+/**
+ * 光谱仪数据 Entity
+ * @author system
+ * @version 2026-05-21
+ */
+@Table(name="mes_gpy", alias="a", label="光谱仪数据", columns={
+		@Column(name="id", attrName="id", label="id", isPK=true),
+		@Column(name="sample_result_name", attrName="sampleResultName", label="样品结果名称"),
+		@Column(name="measure_date_time", attrName="measureDateTime", label="测量日期时间"),
+		@Column(name="recalculation_date_time", attrName="recalculationDateTime", label="重新计算日期时间"),
+		@Column(name="method_name", attrName="methodName", label="方法名称"),
+		@Column(name="origin", attrName="origin", label="组织"),
+		@Column(name="check_type", attrName="checkType", label="检查类型"),
+		@Column(name="check_status", attrName="checkStatus", label="检查结果"),
+		@Column(name="grade_verification_name", attrName="gradeVerificationName", label="验证姓名"),
+		@Column(name="grade_verification_similarity", attrName="gradeVerificationSimilarity", label="成绩验证相似性"),
+		@Column(name="correction_type", attrName="correctionType", label="纠正类型"),
+		@Column(name="outlier_test_type", attrName="outlierTestType", label="异常值检验类型"),
+		@Column(name="Status", attrName="status", label="状态"),
+		@Column(name="submit_inspection", attrName="submitInspection", label="送检部门"),
+		@Column(name="batch_number", attrName="batchNumber", label="批次号"),
+		@Column(name="submission_time", attrName="submissionTime", label="送检时间"),
+		@Column(name="bottle_model_specification", attrName="bottleModelSpecification", label="牌号规范"),
+		@Column(name="bottle_model_id", attrName="bottleModelId", label="牌号ID"),
+		@Column(name="furnace_number", attrName="furnaceNumber", label="炉号/包数"),
+		@Column(name="code", attrName="code", label="编码"),
+	}, orderBy="a.id DESC"
+)
+public class MesGpy extends DataEntity<MesGpy> {
+
+	private static final long serialVersionUID = 1L;
+
+	private String sampleResultName;		// 样品结果名称
+	private Date measureDateTime;			// 测量日期时间
+	private Date recalculationDateTime;		// 重新计算日期时间
+	private String methodName;				// 方法名称
+	private String origin;					// 组织
+	private String checkType;				// 检查类型
+	private String checkStatus;				// 检查结果
+	private String gradeVerificationName;	// 验证姓名
+	private String gradeVerificationSimilarity;	// 成绩验证相似性
+	private String correctionType;			// 纠正类型
+	private String outlierTestType;			// 异常值检验类型
+	private String status;					// 状态
+	private String submitInspection;		// 送检部门
+	private String batchNumber;				// 批次号
+	private String submissionTime;			// 送检时间
+	private String bottleModelSpecification;// 牌号规范
+	private String bottleModelId;			// 牌号ID
+	private String furnaceNumber;			// 炉号/包数
+	private String code;					// 编码
+
+	public MesGpy() {
+		this(null);
+	}
+
+	public MesGpy(String id) {
+		super(id);
+	}
+
+	public String getSampleResultName() {
+		return sampleResultName;
+	}
+
+	public void setSampleResultName(String sampleResultName) {
+		this.sampleResultName = sampleResultName;
+	}
+
+	public Date getMeasureDateTime() {
+		return measureDateTime;
+	}
+
+	public void setMeasureDateTime(Date measureDateTime) {
+		this.measureDateTime = measureDateTime;
+	}
+
+	public Date getRecalculationDateTime() {
+		return recalculationDateTime;
+	}
+
+	public void setRecalculationDateTime(Date recalculationDateTime) {
+		this.recalculationDateTime = recalculationDateTime;
+	}
+
+	public String getMethodName() {
+		return methodName;
+	}
+
+	public void setMethodName(String methodName) {
+		this.methodName = methodName;
+	}
+
+	public String getOrigin() {
+		return origin;
+	}
+
+	public void setOrigin(String origin) {
+		this.origin = origin;
+	}
+
+	public String getCheckType() {
+		return checkType;
+	}
+
+	public void setCheckType(String checkType) {
+		this.checkType = checkType;
+	}
+
+	public String getCheckStatus() {
+		return checkStatus;
+	}
+
+	public void setCheckStatus(String checkStatus) {
+		this.checkStatus = checkStatus;
+	}
+
+	public String getGradeVerificationName() {
+		return gradeVerificationName;
+	}
+
+	public void setGradeVerificationName(String gradeVerificationName) {
+		this.gradeVerificationName = gradeVerificationName;
+	}
+
+	public String getGradeVerificationSimilarity() {
+		return gradeVerificationSimilarity;
+	}
+
+	public void setGradeVerificationSimilarity(String gradeVerificationSimilarity) {
+		this.gradeVerificationSimilarity = gradeVerificationSimilarity;
+	}
+
+	public String getCorrectionType() {
+		return correctionType;
+	}
+
+	public void setCorrectionType(String correctionType) {
+		this.correctionType = correctionType;
+	}
+
+	public String getOutlierTestType() {
+		return outlierTestType;
+	}
+
+	public void setOutlierTestType(String outlierTestType) {
+		this.outlierTestType = outlierTestType;
+	}
+
+	@Override
+	public String getStatus() {
+		return status;
+	}
+
+	@Override
+	public void setStatus(String status) {
+		this.status = status;
+	}
+
+	public String getSubmitInspection() {
+		return submitInspection;
+	}
+
+	public void setSubmitInspection(String submitInspection) {
+		this.submitInspection = submitInspection;
+	}
+
+	public String getBatchNumber() {
+		return batchNumber;
+	}
+
+	public void setBatchNumber(String batchNumber) {
+		this.batchNumber = batchNumber;
+	}
+
+	public String getSubmissionTime() {
+		return submissionTime;
+	}
+
+	public void setSubmissionTime(String submissionTime) {
+		this.submissionTime = submissionTime;
+	}
+
+	public String getBottleModelSpecification() {
+		return bottleModelSpecification;
+	}
+
+	public void setBottleModelSpecification(String bottleModelSpecification) {
+		this.bottleModelSpecification = bottleModelSpecification;
+	}
+
+	public String getBottleModelId() {
+		return bottleModelId;
+	}
+
+	public void setBottleModelId(String bottleModelId) {
+		this.bottleModelId = bottleModelId;
+	}
+
+	public String getFurnaceNumber() {
+		return furnaceNumber;
+	}
+
+	public void setFurnaceNumber(String furnaceNumber) {
+		this.furnaceNumber = furnaceNumber;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+}

+ 98 - 0
src/main/java/com/jeesite/modules/mes/entity/MesGpyMeas.java

@@ -0,0 +1,98 @@
+package com.jeesite.modules.mes.entity;
+
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.Table;
+
+/**
+ * 光谱仪元素数据 Entity
+ * @author system
+ * @version 2026-05-21
+ */
+@Table(name="mes_gpy_meas", alias="a", label="光谱仪元素数据", columns={
+		@Column(name="id", attrName="id", label="id", isPK=true),
+		@Column(name="mes_gpy_id", attrName="mesGpyId", label="mes_gpy表id"),
+		@Column(name="element_name", attrName="elementName", label="元素名称"),
+		@Column(name="replicate_0", attrName="replicate0", label="第一次测量结果"),
+		@Column(name="replicate_1", attrName="replicate1", label="第二次测量结果"),
+		@Column(name="mean", attrName="mean", label="平均值"),
+		@Column(name="lower_acceptance_limit", attrName="lowerAcceptanceLimit", label="可接受最小值"),
+		@Column(name="upper_acceptance_limit", attrName="upperAcceptanceLimit", label="可接受最大值"),
+	}, orderBy="a.id DESC"
+)
+public class MesGpyMeas extends DataEntity<MesGpyMeas> {
+
+	private static final long serialVersionUID = 1L;
+
+	private String mesGpyId;				// mes_gpy表id
+	private String elementName;				// 元素名称
+	private String replicate0;				// 第一次测量结果
+	private String replicate1;				// 第二次测量结果
+	private String mean;					// 平均值
+	private String lowerAcceptanceLimit;	// 可接受最小值
+	private String upperAcceptanceLimit;	// 可接受最大值
+
+	public MesGpyMeas() {
+		this(null);
+	}
+
+	public MesGpyMeas(String id) {
+		super(id);
+	}
+
+	public String getMesGpyId() {
+		return mesGpyId;
+	}
+
+	public void setMesGpyId(String mesGpyId) {
+		this.mesGpyId = mesGpyId;
+	}
+
+	public String getElementName() {
+		return elementName;
+	}
+
+	public void setElementName(String elementName) {
+		this.elementName = elementName;
+	}
+
+	public String getReplicate0() {
+		return replicate0;
+	}
+
+	public void setReplicate0(String replicate0) {
+		this.replicate0 = replicate0;
+	}
+
+	public String getReplicate1() {
+		return replicate1;
+	}
+
+	public void setReplicate1(String replicate1) {
+		this.replicate1 = replicate1;
+	}
+
+	public String getMean() {
+		return mean;
+	}
+
+	public void setMean(String mean) {
+		this.mean = mean;
+	}
+
+	public String getLowerAcceptanceLimit() {
+		return lowerAcceptanceLimit;
+	}
+
+	public void setLowerAcceptanceLimit(String lowerAcceptanceLimit) {
+		this.lowerAcceptanceLimit = lowerAcceptanceLimit;
+	}
+
+	public String getUpperAcceptanceLimit() {
+		return upperAcceptanceLimit;
+	}
+
+	public void setUpperAcceptanceLimit(String upperAcceptanceLimit) {
+		this.upperAcceptanceLimit = upperAcceptanceLimit;
+	}
+}

+ 41 - 0
src/main/java/com/jeesite/modules/mes/service/MesGpyMeasService.java

@@ -0,0 +1,41 @@
+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.service.CrudService;
+import com.jeesite.modules.mes.dao.MesGpyMeasDao;
+import com.jeesite.modules.mes.entity.MesGpyMeas;
+
+/**
+ * 光谱仪元素数据 Service
+ * @author system
+ * @version 2026-05-21
+ */
+@Service
+public class MesGpyMeasService extends CrudService<MesGpyMeasDao, MesGpyMeas> {
+
+	@Override
+	public MesGpyMeas get(MesGpyMeas mesGpyMeas) {
+		return super.get(mesGpyMeas);
+	}
+
+	@Override
+	public List<MesGpyMeas> findList(MesGpyMeas mesGpyMeas) {
+		return super.findList(mesGpyMeas);
+	}
+
+	@Override
+	@Transactional
+	public void save(MesGpyMeas mesGpyMeas) {
+		super.save(mesGpyMeas);
+	}
+
+	@Override
+	@Transactional
+	public void delete(MesGpyMeas mesGpyMeas) {
+		super.delete(mesGpyMeas);
+	}
+}

+ 53 - 0
src/main/java/com/jeesite/modules/mes/service/MesGpyService.java

@@ -0,0 +1,53 @@
+package com.jeesite.modules.mes.service;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.modules.mes.dao.MesGpyDao;
+import com.jeesite.modules.mes.entity.MesGpy;
+
+/**
+ * 光谱仪数据 Service
+ * @author system
+ * @version 2026-05-21
+ */
+@Service
+public class MesGpyService extends CrudService<MesGpyDao, MesGpy> {
+
+	@Override
+	public MesGpy get(MesGpy mesGpy) {
+		return super.get(mesGpy);
+	}
+
+	@Override
+	public Page<MesGpy> findPage(MesGpy mesGpy) {
+		return super.findPage(mesGpy);
+	}
+
+	@Override
+	public List<MesGpy> findList(MesGpy mesGpy) {
+		return super.findList(mesGpy);
+	}
+
+	@Override
+	@Transactional
+	public void save(MesGpy mesGpy) {
+		super.save(mesGpy);
+	}
+
+	@Override
+	@Transactional
+	public void updateStatus(MesGpy mesGpy) {
+		super.updateStatus(mesGpy);
+	}
+
+	@Override
+	@Transactional
+	public void delete(MesGpy mesGpy) {
+		super.delete(mesGpy);
+	}
+}

+ 114 - 0
src/main/java/com/jeesite/modules/mes/web/MesGpyController.java

@@ -0,0 +1,114 @@
+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.MesGpy;
+import com.jeesite.modules.mes.entity.MesGpyMeas;
+import com.jeesite.modules.mes.service.MesGpyMeasService;
+import com.jeesite.modules.mes.service.MesGpyService;
+
+/**
+ * 光谱仪Controller
+ * @author system
+ * @version 2026-05-21
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesGpy")
+public class MesGpyController extends BaseController {
+
+	@Autowired
+	private MesGpyService mesGpyService;
+
+	@Autowired
+	private MesGpyMeasService mesGpyMeasService;
+	
+	/**
+	 * 获取数据
+	 */
+	@ModelAttribute
+	public MesGpy get(String id, boolean isNewRecord) {
+		return mesGpyService.get(id, isNewRecord);
+	}
+	
+	/**
+	 * 查询列表
+	 */
+	@RequiresPermissions("mes:mesGpy:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesGpy mesGpy, Model model) {
+		model.addAttribute("mesGpy", mesGpy);
+		return "modules/mes/mesGpyList";
+	}
+	
+	/**
+	 * 查询列表数据
+	 */
+	@RequiresPermissions("mes:mesGpy:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesGpy> listData(MesGpy mesGpy, HttpServletRequest request, HttpServletResponse response) {
+		mesGpy.setPage(new Page<>(request, response));
+		Page<MesGpy> page = mesGpyService.findPage(mesGpy);
+		return page;
+	}
+
+	/**
+	 * 查看编辑表单
+	 */
+	@RequiresPermissions("mes:mesGpy:view")
+	@RequestMapping(value = "form")
+	public String form(MesGpy mesGpy, Model model) {
+		model.addAttribute("mesGpy", mesGpy);
+		return "modules/mes/mesGpyForm";
+	}
+
+	/**
+	 * 查询元素测量数据列表
+	 */
+	@RequiresPermissions("mes:mesGpy:view")
+	@RequestMapping(value = "measListData")
+	@ResponseBody
+	public List<MesGpyMeas> measListData(String mesGpyId) {
+		MesGpyMeas query = new MesGpyMeas();
+		query.setMesGpyId(mesGpyId);
+		return mesGpyMeasService.findList(query);
+	}
+
+	/**
+	 * 保存数据
+	 */
+	@RequiresPermissions("mes:mesGpy:edit")
+	@PostMapping(value = "save")
+	@ResponseBody
+	public String save(@Validated MesGpy mesGpy) {
+		mesGpyService.save(mesGpy);
+		return renderResult(Global.TRUE, text("保存光谱仪成功!"));
+	}
+	
+	/**
+	 * 删除数据
+	 */
+	@RequiresPermissions("mes:mesGpy:edit")
+	@RequestMapping(value = "delete")
+	@ResponseBody
+	public String delete(MesGpy mesGpy) {
+		mesGpyService.delete(mesGpy);
+		return renderResult(Global.TRUE, text("删除光谱仪成功!"));
+	}
+	
+}

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

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

+ 488 - 0
src/main/java/com/jeesite/modules/scheduling/GpyXmlScheduling.java

@@ -0,0 +1,488 @@
+package com.jeesite.modules.scheduling;
+
+import com.jeesite.modules.mes.entity.MesGpy;
+import com.jeesite.modules.mes.entity.MesGpyMeas;
+import com.jeesite.modules.mes.service.MesGpyMeasService;
+import com.jeesite.modules.mes.service.MesGpyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 光谱仪XML文件定时解析任务
+ * 定时扫描 F:\guangpuyi 目录下的 xml 文件,解析后写入 mes_gpy 表和 mes_gpy_meas 表,
+ * 成功后将文件移到 backup 子目录,避免重复导入。
+ *
+ * @author system
+ * @version 2026-05-21
+ */
+@Configuration
+@EnableScheduling
+public class GpyXmlScheduling {
+
+    private static final Logger logger = LoggerFactory.getLogger(GpyXmlScheduling.class);
+
+    /** 光谱仪 文件存放目录 */
+    private static final String XML_DIR = "F:\\guangpuyi";
+
+
+    private static final String BACKUP_DIR = "F:\\guangpuyi\\backup";
+
+    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+
+    // 自增ID计数器
+    private static final AtomicInteger ID_SEQ = new AtomicInteger((int)(System.currentTimeMillis() / 1000));
+
+    @Autowired
+    private MesGpyService mesGpyService;
+
+    @Autowired
+    private MesGpyMeasService mesGpyMeasService;
+
+    /**
+     * 每 30 秒执行一次扫描
+     */
+    @Scheduled(fixedRate = 30000)
+    private void scanAndImport() {
+        try {
+            File dir = new File(XML_DIR);
+            if (!dir.exists() || !dir.isDirectory()) {
+                return;
+            }
+
+            File[] xmlFiles = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".xml"));
+            if (xmlFiles == null || xmlFiles.length == 0) {
+                return;
+            }
+
+            // 确保备份目录存在
+            File backupDir = new File(BACKUP_DIR);
+            if (!backupDir.exists()) {
+                backupDir.mkdirs();
+            }
+
+            for (File xmlFile : xmlFiles) {
+                try {
+                    parseAndSave(xmlFile);
+                    // 处理成功,移动到备份目录
+                    File dest = new File(backupDir, xmlFile.getName());
+                    if (dest.exists()) {
+                        dest.delete();
+                    }
+                    boolean moved = xmlFile.renameTo(dest);
+                    if (!moved) {
+                        logger.warn("文件移动失败: {}", xmlFile.getName());
+                    } else {
+                        logger.info("光谱仪文件处理完成: {}", xmlFile.getName());
+                    }
+                } catch (Exception e) {
+                    logger.error("解析光谱仪文件失败: " + xmlFile.getName(), e);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("光谱仪定时任务异常", e);
+        }
+    }
+
+    /**
+     * 解析单个 XML 文件并入库
+     */
+    private void parseAndSave(File xmlFile) throws Exception {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        Document doc = builder.parse(xmlFile);
+        doc.getDocumentElement().normalize();
+
+        // 获取 SampleResult 节点
+        NodeList sampleResultList = doc.getElementsByTagName("SampleResult");
+        if (sampleResultList.getLength() == 0) {
+            logger.warn("文件中没有 SampleResult 节点: {}", xmlFile.getName());
+            return;
+        }
+
+        Element sampleResult = (Element) sampleResultList.item(0);
+
+        // --- 从 SampleResult 属性中提取字段 ---
+        String sampleResultName = sampleResult.getAttribute("Name");
+        String recalculationDateTimeStr = sampleResult.getAttribute("RecalculationDateTime");
+        String methodName = sampleResult.getAttribute("MethodName");
+        String origin = sampleResult.getAttribute("Origin");
+        String corrType = sampleResult.getAttribute("CorrType");
+        String reproTestType = sampleResult.getAttribute("ReproTestType");
+
+        // --- 从 SampleIDs 中提取字段 ---
+        String submitInspection = "";
+        String batchNumber = "";
+        String submissionTime = "";
+        String bottleModelSpec = "";
+        String bottleModelId = "";
+        String furnaceNumber = "";
+
+        NodeList sampleIds = sampleResult.getElementsByTagName("SampleID");
+        for (int i = 0; i < sampleIds.getLength(); i++) {
+            Element sampleId = (Element) sampleIds.item(i);
+            String type = sampleId.getAttribute("Type");
+            String isSampleName = sampleId.getAttribute("IsSampleName");
+            String idName = getTextContent(sampleId, "IDName");
+            String idValue = getTextContent(sampleId, "IDValue");
+
+            if ("GradeNorm".equals(type)) {
+                bottleModelSpec = idValue;
+            } else if ("GradeName".equals(type)) {
+                bottleModelId = idValue;
+            } else if ("Text".equals(type) && "False".equals(isSampleName)) {
+                // 按 IDName 精确匹配
+                if ("送检部门".equals(idName)) {
+                    submitInspection = idValue;
+                } else if ("批次号".equals(idName)) {
+                    batchNumber = idValue;
+                } else if ("送检时间".equals(idName)) {
+                    submissionTime = idValue;
+                } else if (idName != null && idName.contains("炉号/包数")) {
+                    furnaceNumber = idValue;
+                }
+            }
+        }
+
+        // --- 从 MeasurementStatistics > Measurement 中提取检测结果 ---
+        String checkType = "";
+        String checkStatus = "";
+        String gradeVerificationName = "";
+        String gradeVerificationSimilarity = "";
+
+        NodeList statisticsList = sampleResult.getElementsByTagName("MeasurementStatistics");
+        if (statisticsList.getLength() > 0) {
+            Element statistics = (Element) statisticsList.item(0);
+            NodeList measurementList = statistics.getElementsByTagName("Measurement");
+            if (measurementList.getLength() > 0) {
+                Element measurement = (Element) measurementList.item(0);
+                checkType = measurement.getAttribute("CheckType");
+                checkStatus = measurement.getAttribute("CheckStatus");
+                gradeVerificationName = measurement.getAttribute("GradeName");
+                gradeVerificationSimilarity = measurement.getAttribute("GradeSimilarityPercentage");
+            }
+        }
+
+        // --- 从 MeasurementReplicate 中提取最早的测量时间 ---
+        Date measureDateTime = null;
+        NodeList replicates = sampleResult.getElementsByTagName("MeasurementReplicate");
+        if (replicates.getLength() > 0) {
+            Element firstReplicate = (Element) replicates.item(0);
+            String mdt = firstReplicate.getAttribute("MeasureDateTime");
+            if (mdt != null && !mdt.isEmpty()) {
+                measureDateTime = SDF.parse(mdt);
+            }
+        }
+
+        // --- 解析重新计算时间 ---
+        Date recalculationDateTime = null;
+        if (recalculationDateTimeStr != null && !recalculationDateTimeStr.isEmpty()) {
+            recalculationDateTime = SDF.parse(recalculationDateTimeStr);
+        }
+
+        // --- 构建 mes_gpy 实体并保存 ---
+        String gpyId = String.valueOf(ID_SEQ.incrementAndGet());
+
+        // 从文件名提取编码    1#集中炉_20260521152155.xml → 20260521152155
+        String code = extractCodeFromFileName(xmlFile.getName());
+
+        MesGpy mesGpy = new MesGpy();
+        mesGpy.setId(gpyId);
+        mesGpy.setIsNewRecord(true);
+        mesGpy.setSampleResultName(sampleResultName);
+        mesGpy.setMeasureDateTime(measureDateTime);
+        mesGpy.setRecalculationDateTime(recalculationDateTime);
+        mesGpy.setMethodName(methodName);
+        mesGpy.setOrigin(origin);
+        mesGpy.setCheckType(checkType);
+        mesGpy.setCheckStatus(checkStatus);
+        mesGpy.setGradeVerificationName(gradeVerificationName);
+        mesGpy.setGradeVerificationSimilarity(gradeVerificationSimilarity);
+        mesGpy.setCorrectionType(corrType);
+        mesGpy.setOutlierTestType(reproTestType);
+        mesGpy.setSubmitInspection(submitInspection);
+        mesGpy.setBatchNumber(batchNumber);
+        mesGpy.setSubmissionTime(submissionTime);
+        mesGpy.setBottleModelSpecification(bottleModelSpec);
+        mesGpy.setBottleModelId(bottleModelId);
+        mesGpy.setFurnaceNumber(furnaceNumber);
+        mesGpy.setCode(code);
+
+        mesGpyService.save(mesGpy);
+        logger.info("光谱仪数据入库成功: name={}, method={}, checkStatus={}",
+                sampleResultName, methodName, checkStatus);
+
+        // 解析元素数据
+        parseAndSaveElements(sampleResult, gpyId);
+    }
+
+    /**
+     * 解析元素测量数据
+     * 从 MeasurementReplicates 中取每次激发的 Reported 值,
+     * 从 MeasurementStatistics 中取 Mean 值和 AcceptanceLimit
+     */
+    private void parseAndSaveElements(Element sampleResult, String gpyId) {
+        try {
+            // 1. 收集各次激发的元素 Reported 值
+            //    key=元素名称, value=按 replicate 序号存的值列表
+            Map<String, List<String>> replicateValues = new LinkedHashMap<>();
+
+            NodeList replicateNodes = sampleResult.getElementsByTagName("MeasurementReplicate");
+            for (int r = 0; r < replicateNodes.getLength(); r++) {
+                Element replicate = (Element) replicateNodes.item(r);
+                // 取 Measurement 下的 Elements
+                NodeList measurementNodes = replicate.getElementsByTagName("Measurement");
+                if (measurementNodes.getLength() == 0) continue;
+                Element measurement = (Element) measurementNodes.item(0);
+                NodeList elements = measurement.getElementsByTagName("Element");
+
+                for (int e = 0; e < elements.getLength(); e++) {
+                    Element elem = (Element) elements.item(e);
+                    String elemName = elem.getAttribute("ElementName");
+                    String elemType = elem.getAttribute("Type");
+                    // 跳过伪元素(如 OR)
+                    if ("Pseudo".equals(elemType)) continue;
+
+                    // 取 StatType="Reported" 且 Type="Conc" 的 ResultValue
+                    String reportedValue = getReportedValue(elem);
+
+                    replicateValues.computeIfAbsent(elemName, k -> new ArrayList<>());
+                    List<String> vals = replicateValues.get(elemName);
+                    // 确保按序号填充
+                    while (vals.size() <= r) {
+                        vals.add("");
+                    }
+                    vals.set(r, reportedValue);
+                }
+            }
+
+            // 2. 从 MeasurementStatistics 中取 Mean 和 AcceptanceLimit
+            Map<String, String> meanMap = new LinkedHashMap<>();
+            Map<String, String> lowerLimitMap = new LinkedHashMap<>();
+            Map<String, String> upperLimitMap = new LinkedHashMap<>();
+
+            NodeList statisticsList = sampleResult.getElementsByTagName("MeasurementStatistics");
+            if (statisticsList.getLength() > 0) {
+                Element statistics = (Element) statisticsList.item(0);
+                NodeList measurementNodes = statistics.getElementsByTagName("Measurement");
+                if (measurementNodes.getLength() > 0) {
+                    Element measurement = (Element) measurementNodes.item(0);
+                    NodeList elements = measurement.getElementsByTagName("Element");
+
+                    for (int e = 0; e < elements.getLength(); e++) {
+                        Element elem = (Element) elements.item(e);
+                        String elemName = elem.getAttribute("ElementName");
+                        String elemType = elem.getAttribute("Type");
+                        if ("Pseudo".equals(elemType)) continue;
+
+                        // 取 Mean 值(StatType="Mean", Type="Conc")
+                        String meanValue = getMeanValue(elem);
+                        meanMap.put(elemName, meanValue);
+
+                        // 取 AcceptanceLimit(从 Reported 的 ResultValueLimits 中)
+                        String[] limits = getAcceptanceLimits(elem);
+                        lowerLimitMap.put(elemName, limits[0]);
+                        upperLimitMap.put(elemName, limits[1]);
+                    }
+                }
+            }
+
+            // 3. 组装并保存 mes_gpy_meas
+            for (Map.Entry<String, List<String>> entry : replicateValues.entrySet()) {
+                String elemName = entry.getKey();
+                List<String> reps = entry.getValue();
+
+                MesGpyMeas meas = new MesGpyMeas();
+                meas.setId(String.valueOf(ID_SEQ.incrementAndGet()));
+                meas.setIsNewRecord(true);
+                meas.setMesGpyId(gpyId);
+                meas.setElementName(elemName);
+                meas.setReplicate0(reps.size() > 0 ? reps.get(0) : "");
+                meas.setReplicate1(reps.size() > 1 ? reps.get(1) : "");
+                meas.setMean(meanMap.getOrDefault(elemName, ""));
+                meas.setLowerAcceptanceLimit(lowerLimitMap.getOrDefault(elemName, ""));
+                meas.setUpperAcceptanceLimit(upperLimitMap.getOrDefault(elemName, ""));
+
+                mesGpyMeasService.save(meas);
+            }
+
+            logger.info("光谱仪元素数据入库成功: gpyId={}, 元素数量={}", gpyId, replicateValues.size());
+        } catch (Exception e) {
+            logger.error("解析元素数据失败: gpyId=" + gpyId, e);
+        }
+    }
+
+    /**
+     * 从 Element 节点中获取 Type="Conc" + StatType="Reported" 的 ResultValue
+     * 根据 CalibrationStatus 添加 < 或 > 前缀:
+     *   UnderRange → "<值"
+     *   OverRange  → ">值"
+     *   InRange    → "值"
+     */
+    private String getReportedValue(Element elem) {
+        NodeList results = elem.getElementsByTagName("ElementResult");
+        for (int i = 0; i < results.getLength(); i++) {
+            Element result = (Element) results.item(i);
+            if ("Conc".equals(result.getAttribute("Type"))
+                    && "Reported".equals(result.getAttribute("StatType"))) {
+                String value = getTextContent(result, "ResultValue");
+                String calibStatus = result.getAttribute("CalibrationStatus");
+                return addRangePrefix(value, calibStatus);
+            }
+        }
+        // 如果没有 Reported,取 StatType="None" 且 Type="Conc"
+        for (int i = 0; i < results.getLength(); i++) {
+            Element result = (Element) results.item(i);
+            if ("Conc".equals(result.getAttribute("Type"))
+                    && "None".equals(result.getAttribute("StatType"))) {
+                String value = getTextContent(result, "ResultValue");
+                String calibStatus = result.getAttribute("CalibrationStatus");
+                return addRangePrefix(value, calibStatus);
+            }
+        }
+        return "";
+    }
+
+    /**
+     * 根据 CalibrationStatus 添加范围前缀,并将科学计数法转为普通小数
+     */
+    private String addRangePrefix(String value, String calibrationStatus) {
+        if (value == null || value.isEmpty()) {
+            return "";
+        }
+        // 将科学计数法转为普通小数格式(如 5E-05 → 0.00005)
+        value = convertScientificToDecimal(value);
+        if ("UnderRange".equals(calibrationStatus)) {
+            return "<" + value;
+        } else if ("OverRange".equals(calibrationStatus)) {
+            return ">" + value;
+        }
+        return value;
+    }
+
+    /**
+     * 将科学计数法字符串转为普通小数字符串
+     * 例如: "5E-05" → "0.00005", "1.2E-03" → "0.0012"
+     * 非科学计数法的直接原样返回
+     */
+    private String convertScientificToDecimal(String value) {
+        if (value == null || value.isEmpty()) {
+            return value;
+        }
+        // 判断是否包含 E 或 e(科学计数法标志)
+        if (value.toUpperCase().contains("E")) {
+            try {
+                java.math.BigDecimal bd = new java.math.BigDecimal(value);
+                return bd.stripTrailingZeros().toPlainString();
+            } catch (NumberFormatException e) {
+                // 解析失败则原样返回
+                return value;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * 从 MeasurementStatistics 的 Element 节点中获取平均值
+     * 优先取 StatType="Reported"(修剪后的报告值),与 replicate 取值逻辑一致
+     */
+    private String getMeanValue(Element elem) {
+        NodeList results = elem.getElementsByTagName("ElementResult");
+        // 优先取 Reported
+        for (int i = 0; i < results.getLength(); i++) {
+            Element result = (Element) results.item(i);
+            if ("Conc".equals(result.getAttribute("Type"))
+                    && "Reported".equals(result.getAttribute("StatType"))) {
+                String value = getTextContent(result, "ResultValue");
+                String calibStatus = result.getAttribute("CalibrationStatus");
+                return addRangePrefix(value, calibStatus);
+            }
+        }
+        // 没有 Reported 则取 Mean
+        for (int i = 0; i < results.getLength(); i++) {
+            Element result = (Element) results.item(i);
+            if ("Conc".equals(result.getAttribute("Type"))
+                    && "Mean".equals(result.getAttribute("StatType"))) {
+                String value = getTextContent(result, "ResultValue");
+                String calibStatus = result.getAttribute("CalibrationStatus");
+                return addRangePrefix(value, calibStatus);
+            }
+        }
+        return "";
+    }
+
+    /**
+     * 从 Element 节点中获取 AcceptanceLimit
+     * 优先从 StatType="Reported" 的 ResultValueLimits 中取
+     * @return [lowerAcceptanceLimit, upperAcceptanceLimit]
+     */
+    private String[] getAcceptanceLimits(Element elem) {
+        String lower = "";
+        String upper = "";
+
+        NodeList results = elem.getElementsByTagName("ElementResult");
+        for (int i = 0; i < results.getLength(); i++) {
+            Element result = (Element) results.item(i);
+            if ("Conc".equals(result.getAttribute("Type"))
+                    && "Reported".equals(result.getAttribute("StatType"))) {
+                NodeList limits = result.getElementsByTagName("ResultValueLimit");
+                for (int j = 0; j < limits.getLength(); j++) {
+                    Element limit = (Element) limits.item(j);
+                    String limitType = limit.getAttribute("Type");
+                    String limitValue = convertScientificToDecimal(limit.getTextContent().trim());
+                    if ("LowerAcceptanceLimit".equals(limitType)) {
+                        lower = limitValue;
+                    } else if ("UpperAcceptanceLimit".equals(limitType)) {
+                        upper = limitValue;
+                    }
+                }
+                // 找到 Reported 就不再继续
+                if (!lower.isEmpty() || !upper.isEmpty()) {
+                    break;
+                }
+            }
+        }
+        return new String[]{lower, upper};
+    }
+
+    /**
+     * 获取子元素文本内容
+     */
+    private String getTextContent(Element parent, String tagName) {
+        NodeList list = parent.getElementsByTagName(tagName);
+        if (list.getLength() > 0) {
+            String text = list.item(0).getTextContent();
+            return text != null ? text.trim() : "";
+        }
+        return "";
+    }
+
+    private String extractCodeFromFileName(String fileName) {
+        // 去掉扩展名
+        String name = fileName;
+        int dotIdx = name.lastIndexOf('.');
+        if (dotIdx > 0) {
+            name = name.substring(0, dotIdx);
+        }
+        // 取最后一个下划线后面的部分
+        int underscoreIdx = name.lastIndexOf('_');
+        if (underscoreIdx >= 0 && underscoreIdx < name.length() - 1) {
+            return name.substring(underscoreIdx + 1);
+        }
+        return name;
+    }
+}

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

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

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

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

+ 157 - 0
src/main/resources/views/modules/mes/mesGpyForm.html

@@ -0,0 +1,157 @@
+<% layout('/layouts/default.html', {title: '光谱仪管理', libs: ['validate', 'dataGrid']}){ %>
+<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(mesGpy.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="${mesGpy}" action="${ctx}/mes/mesGpy/save" method="post" class="form-horizontal">
+			<div class="box-body">
+				<div class="form-unit">${text('基本信息')}</div>
+				<#form:hidden path="id"/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('样品结果名称')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="sampleResultName" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('测量日期时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="measureDateTime" readonly="true" maxlength="20" class="form-control laydate"
+									dataFormat="datetime" data-type="datetime" data-format="yyyy-MM-dd HH:mm"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('方法名称')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="methodName" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('检查结果')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="checkStatus" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('送检部门')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="submitInspection" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('批次号')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="batchNumber" maxlength="50" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('送检时间')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="submissionTime" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('牌号规范')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="bottleModelSpecification" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('牌号ID')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="bottleModelId" maxlength="50" 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:mesGpy: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 class="box box-main" style="margin-top:10px;">
+		<div class="box-header with-border">
+			<div class="box-title">
+				<i class="fa icon-chemistry"></i> ${text('元素测量数据')}
+			</div>
+		</div>
+		<div class="box-body">
+			<table id="measDataGrid"></table>
+		</div>
+	</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");
+    }
+});
+
+// 元素测量数据表格
+$('#measDataGrid').dataGrid({
+	url: "${ctx}/mes/mesGpy/measListData?mesGpyId=${mesGpy.id}",
+	method: "get",
+	datatype: "json",
+	pager: false,
+	rownumbers: true,
+	columnModel: [
+		{header:'${text("元素名称")}', name:'elementName', width:100, align:"center", frozen:true},
+		{header:'${text("第一次测量")}', name:'replicate0', width:180, align:"right"},
+		{header:'${text("第二次测量")}', name:'replicate1', width:180, align:"right"},
+		{header:'${text("平均值")}', name:'mean', width:180, align:"right"},
+		{header:'${text("可接受最小值")}', name:'lowerAcceptanceLimit', width:120, align:"right"},
+		{header:'${text("可接受最大值")}', name:'upperAcceptanceLimit', width:120, align:"right"}
+	]
+});
+</script>

+ 132 - 0
src/main/resources/views/modules/mes/mesGpyList.html

@@ -0,0 +1,132 @@
+<% 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:mesGpy:edit')){ %>
+					<a href="${ctx}/mes/mesGpy/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="${mesGpy}" action="${ctx}/mes/mesGpy/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="sampleResultName" 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="code" 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="measureDateTime" readonly="true" maxlength="20" class="form-control laydate width-datetime"
+							dataFormat="datetime" data-type="datetime" data-format="yyyy-MM-dd HH:mm"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('方法名称')}:</label>
+					<div class="control-inline">
+						<#form:input path="methodName" 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="checkStatus" 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="submitInspection" 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="batchNumber" maxlength="50" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('送检时间')}:</label>
+					<div class="control-inline">
+						<#form:input path="submissionTime" 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="bottleModelSpecification" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('牌号ID')}:</label>
+					<div class="control-inline">
+						<#form:input path="bottleModelId" maxlength="50" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
+					<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
+				</div>
+			</#form:form>
+			<table id="dataGrid"></table>
+			<div id="dataGridPage"></div>
+		</div>
+	</div>
+</div>
+<% } %>
+<script>
+// 初始化DataGrid对象
+$('#dataGrid').dataGrid({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("样品结果名称")}', name:'sampleResultName', index:'a.sample_result_name', width:150, align:"left"},
+		{header:'${text("编码")}', name:'code', index:'a.code', width:150, align:"left" , frozen:true, formatter: function(val, obj, row, act){
+				return '<a href="${ctx}/mes/mesGpy/form?id='+row.id+'" class="btnList" data-title="${text("编辑光谱仪")}">'+(val||row.id)+'</a>';
+			}},
+		{header:'${text("测量日期时间")}', name:'measureDateTime', index:'a.measure_date_time', width:150, align:"center"},
+		// {header:'${text("重新计算日期时间")}', name:'recalculationDateTime', index:'a.recalculation_date_time', width:150, align:"center"},
+		{header:'${text("方法名称")}', name:'methodName', index:'a.method_name', width:150, align:"left"},
+
+		// {header:'${text("组织")}', name:'origin', index:'a.origin', width:150, align:"left"},
+		// {header:'${text("检查类型")}', name:'checkType', index:'a.check_type', width:150, align:"left"},
+		{header:'${text("检查结果")}', name:'checkStatus', index:'a.check_status', width:150, align:"left"},
+		// {header:'${text("验证姓名")}', name:'gradeVerificationName', index:'a.grade_verification_name', width:150, align:"left"},
+		// {header:'${text("成绩验证相似性")}', name:'gradeVerificationSimilarity', index:'a.grade_verification_similarity', width:150, align:"left"},
+		// {header:'${text("纠正类型")}', name:'correctionType', index:'a.correction_type', width:150, align:"left"},
+		// {header:'${text("异常值检验类型")}', name:'outlierTestType', index:'a.outlier_test_type', width:150, align:"left"},
+		// {header:'${text("状态")}', name:'status', index:'a.status', width:150, align:"left"},
+		{header:'${text("送检部门")}', name:'submitInspection', index:'a.submit_inspection', width:150, align:"left"},
+		{header:'${text("批次号")}', name:'batchNumber', index:'a.batch_number', width:150, align:"left"},
+		{header:'${text("送检时间")}', name:'submissionTime', index:'a.submission_time', width:150, align:"left"},
+		{header:'${text("牌号规范")}', name:'bottleModelSpecification', index:'a.bottle_model_specification', width:150, align:"left"},
+		{header:'${text("牌号ID")}', name:'bottleModelId', index:'a.bottle_model_id', width:150, align:"left"}
+
+		// {header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
+		// 	var actions = [];
+		// 	//<% if(hasPermi('mes:mesGpy:edit')){ %>
+		// 		actions.push('<a href="${ctx}/mes/mesGpy/form?id='+row.id+'" class="btnList" title="${text("编辑光谱仪")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+		// 		actions.push('<a href="${ctx}/mes/mesGpy/delete?id='+row.id+'" class="btnList" title="${text("删除光谱仪")}" data-confirm="${text("确认要删除该光谱仪吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+		// 	//<% } %>
+		// 	return actions.join('');
+		// }
+		// }
+	],
+	// 加载成功后执行事件
+	ajaxSuccess: function(data){
+
+	}
+});
+</script>

+ 109 - 0
src/main/resources/views/modules/mes/mesGpyMeasForm.html

@@ -0,0 +1,109 @@
+<% 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(mesGpyMeas.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="${mesGpyMeas}" action="${ctx}/mes/mesGpyMeas/save" method="post" class="form-horizontal">
+			<div class="box-body">
+				<div class="form-unit">${text('基本信息')}</div>
+				<#form:hidden path="id"/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('mes_gpy表id')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="mesGpyId" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('元素名称')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="elementName" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('第一次测量结果')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="replicate0" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('第二次测量结果')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="replicate1" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('平均值')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="mean" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('可接受最大值')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="lowerAcceptanceLimit" maxlength="255" class="form-control"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required hide">*</span> ${text('可接受最小值')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="upperAcceptanceLimit" 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:mesGpyMeas: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>

+ 100 - 0
src/main/resources/views/modules/mes/mesGpyMeasList.html

@@ -0,0 +1,100 @@
+<% 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:mesGpyMeas:edit')){ %>
+					<a href="${ctx}/mes/mesGpyMeas/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="${mesGpyMeas}" action="${ctx}/mes/mesGpyMeas/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('mes_gpy表id')}:</label>
+					<div class="control-inline">
+						<#form:input path="mesGpyId" 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="elementName" 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="replicate0" 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="replicate1" 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="mean" 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="lowerAcceptanceLimit" 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="upperAcceptanceLimit" maxlength="255" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
+					<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
+				</div>
+			</#form:form>
+			<table id="dataGrid"></table>
+			<div id="dataGridPage"></div>
+		</div>
+	</div>
+</div>
+<% } %>
+<script>
+// 初始化DataGrid对象
+$('#dataGrid').dataGrid({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("mes_gpy表id")}', name:'mesGpyId', index:'a.mes_gpy_id', width:150, align:"left", frozen:true, formatter: function(val, obj, row, act){
+			return '<a href="${ctx}/mes/mesGpyMeas/form?id='+row.id+'" class="btnList" data-title="${text("编辑光谱仪元素表")}">'+(val||row.id)+'</a>';
+		}},
+		{header:'${text("元素名称")}', name:'elementName', index:'a.element_name', width:150, align:"left"},
+		{header:'${text("第一次测量结果")}', name:'replicate0', index:'a.replicate_0', width:150, align:"left"},
+		{header:'${text("第二次测量结果")}', name:'replicate1', index:'a.replicate_1', width:150, align:"left"},
+		{header:'${text("平均值")}', name:'mean', index:'a.mean', width:150, align:"left"},
+		{header:'${text("可接受最大值")}', name:'lowerAcceptanceLimit', index:'a.lower_acceptance_limit', width:150, align:"left"},
+		{header:'${text("可接受最小值")}', name:'upperAcceptanceLimit', index:'a.upper_acceptance_limit', width:150, align:"left"},
+		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
+			var actions = [];
+			//<% if(hasPermi('mes:mesGpyMeas:edit')){ %>
+				actions.push('<a href="${ctx}/mes/mesGpyMeas/form?id='+row.id+'" class="btnList" title="${text("编辑光谱仪元素表")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesGpyMeas/delete?id='+row.id+'" class="btnList" title="${text("删除光谱仪元素表")}" data-confirm="${text("确认要删除该光谱仪元素表吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+			//<% } %>
+			return actions.join('');
+		}}
+	],
+	// 加载成功后执行事件
+	ajaxSuccess: function(data){
+		
+	}
+});
+</script>