diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java b/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
index 25bbb384..d8dba299 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
@@ -805,4 +805,51 @@ public class DateUtils extends PropertyEditorSupport {
         return days;
     }
 
+    /**
+     *  获取开始时间和结束时间之间的全部小时信息
+     * @param beginDay
+     * @param endDay
+     * @return
+     */
+    public static List<String> getAllDayTime(String beginDay, String endDay){
+        List<String> dayTimes = new ArrayList<>();
+        try {
+            //开始日期
+            Calendar begin = Calendar.getInstance();
+            begin.setTime(DateUtils.parseDate(beginDay, "yyyy-MM-dd"));
+            //将开始日期的24个小时放入集合中
+            for (int i=0; i< 24; i++) {
+                String dayTime = beginDay;
+                if (i < 10) {
+                    dayTime+=" 0"+i;
+                } else {
+                    dayTime+=" "+i;
+                }
+                dayTime+=":00:00";
+                dayTimes.add(dayTime);
+            }
+            //结束日期
+            Calendar end = Calendar.getInstance();
+            end.setTime(DateUtils.parseDate(endDay, "yyyy-MM-dd"));
+            //判断  如果结束日期的时间在开始日期的时间之后
+            while(end.getTime().after(begin.getTime())){
+                //开始日期需要+1天
+                begin.add(Calendar.DAY_OF_MONTH, 1);
+                for (int i=0; i< 24; i++) {
+                    String dayTime = DateUtils.formatDate(begin.getTime(),"yyyy-MM-dd");
+                    if (i < 10) {
+                        dayTime+=" 0"+i;
+                    } else {
+                        dayTime+=" "+i;
+                    }
+                    dayTime+=":00:00";
+                    dayTimes.add(dayTime);
+                }
+            }
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+        return dayTimes;
+    }
+
 }
\ No newline at end of file
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/bizVo/AlertSystemVo.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/bizVo/AlertSystemVo.java
new file mode 100644
index 00000000..c21bf569
--- /dev/null
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/bizVo/AlertSystemVo.java
@@ -0,0 +1,12 @@
+package org.jeecg.modules.base.bizVo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.jeecg.common.api.QueryRequest;
+@Data
+public class AlertSystemVo extends QueryRequest {
+
+    private String code;
+
+    private String content;
+}
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/configuration/GardsAlertSystem.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/configuration/GardsAlertSystem.java
new file mode 100644
index 00000000..580970bd
--- /dev/null
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/configuration/GardsAlertSystem.java
@@ -0,0 +1,35 @@
+package org.jeecg.modules.base.entity.configuration;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("CONFIGURATION.GARDS_ALERT_SYSTEM")
+public class GardsAlertSystem implements Serializable {
+
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+    private String type;
+
+    private String code;
+
+    private String content;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date moddate;
+
+    @TableField(exist = false)
+    private String typeStr;
+
+    public GardsAlertSystem(){ moddate = new Date(); }
+}
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/original/SampleWaterResult.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/original/SampleWaterResult.java
new file mode 100644
index 00000000..20ca5db7
--- /dev/null
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/entity/original/SampleWaterResult.java
@@ -0,0 +1,51 @@
+package org.jeecg.modules.base.entity.original;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("ORIGINAL.SAMPLE_WATER_RESULT")
+public class SampleWaterResult implements Serializable {
+
+    @TableField(value = "SAMPLE_RESULT_ID")
+    private Integer sampleResultId;
+
+    @TableField(value = "SAMPLE_ID")
+    private Integer sampleId;
+
+    @TableField(value = "NUCLIDE_NAME")
+    private String nuclideName;
+
+    @TableField(value = "ENERGY")
+    private Double energy;
+
+    @TableField(value = "CSC_RATIO")
+    private Double cscRatio;
+
+    @TableField(value = "HALF_LIFE")
+    private Double halfLife;
+
+    @TableField(value = "MDA")
+    private Double mda;
+
+    @TableField(value = "ACTIVITY")
+    private Double activity;
+
+    @TableField(value = "SPEC_ACTIVITY")
+    private Double specActivity;
+
+    @TableField(value = "NID_FLAG")
+    private Integer nidFlag;
+
+    @TableField(value = "MODDATE")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date moddate;
+
+}
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/DataType.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/DataType.java
index 741a5673..0335bb87 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/DataType.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/DataType.java
@@ -50,7 +50,11 @@ public enum DataType {
      */
     GASBKPHD("GASBKPHD",".PHD"),
     SPHDP("SPHDP", ".PHD"),
-    SPHDF("SPHDF", ".PHD");
+    SPHDF("SPHDF", ".PHD"),
+
+    GPS("RMSGPS", ".gps"),
+
+    RESULT("HRULT", ".result");
 
     private String type;
 
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SystemType.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SystemType.java
index bfe2422f..9bd0b84e 100644
--- a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SystemType.java
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/enums/SystemType.java
@@ -13,7 +13,11 @@ public enum SystemType {
     /**
      * γ
      */
-    GAMMA("G");
+    GAMMA("G"),
+    /**
+     *  自建台站
+     */
+    SELFSTATION("C");
 
     private String type;
 
diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/modules/entity/vo/ResultNuclide.java b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/entity/vo/ResultNuclide.java
new file mode 100644
index 00000000..060ab8e5
--- /dev/null
+++ b/jeecg-boot-base-core/src/main/java/org/jeecg/modules/entity/vo/ResultNuclide.java
@@ -0,0 +1,26 @@
+package org.jeecg.modules.entity.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class ResultNuclide implements Serializable {
+
+    private String nuclideName;
+
+    private Double energy;
+
+    private Double cscRatio;
+
+    private String halfLife;
+
+    private Double mda;
+
+    private Double activity;
+
+    private Double specActivity;
+
+    private String nidFlag;
+
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/exception/GPSFileReadException.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/exception/GPSFileReadException.java
new file mode 100644
index 00000000..ca1820ed
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/exception/GPSFileReadException.java
@@ -0,0 +1,12 @@
+package org.jeecg.modules.exception;
+
+/*
+    GPS文件读取失败时抛出异常
+ */
+public class GPSFileReadException extends RuntimeException{
+
+    public GPSFileReadException(String message) {
+        super(message);
+    }
+
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/mapper/GardsGPSDataMapper.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/mapper/GardsGPSDataMapper.java
new file mode 100644
index 00000000..d4fced32
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/mapper/GardsGPSDataMapper.java
@@ -0,0 +1,7 @@
+package org.jeecg.modules.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.base.entity.original.GardsGPSData;
+
+public interface GardsGPSDataMapper extends BaseMapper<GardsGPSData> {
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/IGardsGPSDataService.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/IGardsGPSDataService.java
new file mode 100644
index 00000000..6c080daa
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/IGardsGPSDataService.java
@@ -0,0 +1,13 @@
+package org.jeecg.modules.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.base.entity.original.GardsGPSData;
+import org.jeecg.modules.native_jni.struct.GPSSpectrumStruct;
+
+import java.util.List;
+
+public interface IGardsGPSDataService extends IService<GardsGPSData> {
+
+    List<GardsGPSData> create(GPSSpectrumStruct sourceData, String fileName);
+
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/impl/GardsGPSDataServiceImpl.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/impl/GardsGPSDataServiceImpl.java
new file mode 100644
index 00000000..4ec1fffb
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/service/impl/GardsGPSDataServiceImpl.java
@@ -0,0 +1,72 @@
+package org.jeecg.modules.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.modules.base.entity.configuration.GardsStations;
+import org.jeecg.modules.base.entity.original.GardsGPSData;
+import org.jeecg.modules.exception.StationNotFoundException;
+import org.jeecg.modules.mapper.GardsGPSDataMapper;
+import org.jeecg.modules.native_jni.struct.GPSSpectrumStruct;
+import org.jeecg.modules.service.GardsStationsService;
+import org.jeecg.modules.service.IGardsGPSDataService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.ParseException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@DS("ora")
+public class GardsGPSDataServiceImpl extends ServiceImpl<GardsGPSDataMapper, GardsGPSData> implements IGardsGPSDataService {
+
+    @Autowired
+    private GardsStationsService stationsService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public List<GardsGPSData> create(GPSSpectrumStruct sourceData, String fileName) {
+        List<GardsGPSData> dataList = new LinkedList<>();
+        try {
+            //根据台站编码查询台站id
+            GardsStations station = stationsService.check(sourceData.stationCode, fileName);
+            if (Objects.nonNull(station)) {
+                //遍历时间和经纬度数据
+                for (int i=0; i<sourceData.recordDateList.size(); i++) {
+                    GardsGPSData data = new GardsGPSData();
+                    data.setStationId(station.getStationId());
+                    data.setStationCode(sourceData.stationCode);
+                    //拼接记录时间
+                    if (StringUtils.isNotBlank(sourceData.recordDateList.get(i)) && StringUtils.isNotBlank(sourceData.recordTimeList.get(i))) {
+                        String recordTimeStr = sourceData.recordDateList.get(i) + StringPool.SPACE + sourceData.recordTimeList.get(i);
+                        data.setRecordTime(DateUtils.parseDate(recordTimeStr));
+                    } else {
+                        data.setRecordTime(null);
+                    }
+                    //时间间隔
+                    data.setTimeSpan(StringUtils.isNotBlank(sourceData.spanTimeList.get(i))?Integer.valueOf(sourceData.spanTimeList.get(i)):0);
+                    //经度
+                    data.setLon(StringUtils.isNotBlank(sourceData.lonList.get(i))?Double.valueOf(sourceData.lonList.get(i)):null);
+                    //纬度
+                    data.setLat(StringUtils.isNotBlank(sourceData.latList.get(i))?Double.valueOf(sourceData.latList.get(i)):null);
+                    dataList.add(data);
+                }
+                if (CollectionUtils.isNotEmpty(dataList)) {
+                    this.saveBatch(dataList);
+                }
+            }
+            return dataList;
+        } catch (StationNotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/GPSSpectrum.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/GPSSpectrum.java
new file mode 100644
index 00000000..e634758b
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/GPSSpectrum.java
@@ -0,0 +1,277 @@
+package org.jeecg.modules.spectrum;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.apache.commons.io.FileUtils;
+import org.jeecg.common.properties.SpectrumPathProperties;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.modules.ErrorLogManager;
+import org.jeecg.modules.base.entity.original.GardsGPSData;
+import org.jeecg.modules.base.enums.DataType;
+import org.jeecg.modules.base.enums.SampleFileHeader;
+import org.jeecg.modules.eneity.event.FormatErrorEvent;
+import org.jeecg.modules.eneity.event.SpectrumErrorEvent;
+import org.jeecg.modules.enums.ErrorType;
+import org.jeecg.modules.exception.GPSFileReadException;
+import org.jeecg.modules.exception.PHD_ReadException;
+import org.jeecg.modules.file.FileOperation;
+import org.jeecg.modules.native_jni.struct.GPSSpectrumStruct;
+import org.springframework.util.CollectionUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+public class GPSSpectrum extends AbstractSpectrumHandler{
+
+    private List<String> lines = null;
+
+    private GPSSpectrumStruct sourceData = null;
+    /**
+     * 开始存库时间
+     */
+    private Date startIntoDatabaseTime = null;
+    /**
+     * 结束存库时间
+     */
+    private Date endIntoDatabaseTime = null;
+
+    private List<GardsGPSData> gpsData = null;
+
+    /**
+     *  设置过滤链路
+     */
+    @Override
+    protected void setChina() {
+        AbstractSpectrumHandler spectrumHandler = new WaterResultSpectrum();
+        spectrumHandler.initNext(super.spectrumServiceQuotes,super.spectrumFile,super.sourceFilePath,
+                super.currDataType,super.mailContent,super.emlFileName,
+                super.spectrumSource,super.returnFileName, super.batchesCounter);
+        spectrumHandler.setPrevious(this);
+        super.setNext(spectrumHandler);
+    }
+
+    /**
+     *  前置检查
+     */
+    @Override
+    protected void preCheck() {
+        this.readFile();
+    }
+
+    protected void readFile() {
+        //获取文件内容
+        File gpsFile = new File(super.spectrumFile.getAbsolutePath());
+        //判断文件是否存在,如果不存在抛出phd文件读取异常
+        if (!gpsFile.exists()) {
+            throw new GPSFileReadException("This GPS file cannot be found in:"+super.spectrumFile.getAbsolutePath());
+        }
+        //文件内容读取
+        try {
+            lines = FileUtils.readLines(gpsFile, "UTF-8");
+        } catch (IOException e) {
+            ErrorLogManager.getInstance().write(new SpectrumErrorEvent(new Date(), "This GPS file read content error", super.spectrumFile.getName()));
+            throw new GPSFileReadException("This GPS file read content error");
+        }
+    }
+
+    @Override
+    public void handler() throws Exception {
+        if(DataType.GPS.getType().equals(super.currDataType.getType())){
+            try {
+                //前置检查
+                this.preCheck();
+                //打印当前处理的能谱类型
+                super.printCurrDataType();
+                //解析邮件内容
+                this.parseingEmail();
+                //修改能谱文件名称
+                this.updateSpectrumFileName();
+                //保存PHD文件到savefile
+                super.saveFileToSavefile();
+                //结构体数据入库
+                this.handlerOriginalData();
+                //把流程日志保存到日志目录
+                this.saveLogToLogDir();
+                //若本次文件来自于undel目录,解析成功则删除
+                deleteIfFromUndelFile();
+            }catch (Exception e){
+                //异常返回文件名称用于报错日志
+                super.returnFileName.append(super.spectrumFile.getName());
+                //处理解析失败的文件
+                super.handleParseingFailFile(e);
+                throw e;
+            }
+        }
+    }
+
+    /**
+     *  解析邮件内容
+     * @throws Exception
+     */
+    @Override
+    protected void parseingEmail() throws Exception {
+        this.sourceData = new GPSSpectrumStruct();
+        //初始下标是0 0不进行读取
+        int index = 0;
+        //从第第五行开始遍历文件内容
+        for (int i=0; i< lines.size(); i++) {
+            //读取文件行内容
+            String lineContent = lines.get(i);
+            //判断当前行是否包含begin  如果包含 从当前行开始向后读取4行
+            if (lineContent.contains(SampleFileHeader.BEGIN.getMessage())) {
+                index = i + 4;
+            }
+            //切割任意类型空格  获取行内容
+            List<String> contents = Arrays.asList(lineContent.split("\\s+"));
+            //固定格式BEGIN 后的第五行的数据是台站编码
+            if (index > 0 && i == index) {
+                if (StringUtils.isNotBlank(contents.get(0))) {
+                    this.sourceData.stationCode = contents.get(0);
+                } else {
+                    this.sourceData.stationCode = "";
+                }
+                if (StringUtils.isNotBlank(contents.get(1))) {
+                    this.sourceData.receiveDate = contents.get(1);
+                } else {
+                    this.sourceData.receiveDate = "";
+                }
+                if (StringUtils.isNotBlank(contents.get(2))) {
+                    this.sourceData.receiveTime = contents.get(2);
+                } else {
+                    this.sourceData.receiveTime = "";
+                }
+            } else if (index > 0 && i > index) {
+                if (!contents.contains(SampleFileHeader.STOP.getMessage()) ) {
+                    if (StringUtils.isNotBlank(contents.get(0))) {
+                        //记录日期
+                        this.sourceData.recordDateList.add(contents.get(0));
+                    } else {
+                        //记录日期
+                        this.sourceData.recordDateList.add("");
+                    }
+                    if (StringUtils.isNotBlank(contents.get(1))) {
+                        //记录时间
+                        this.sourceData.recordTimeList.add(contents.get(1));
+                    } else {
+                        //记录时间
+                        this.sourceData.recordTimeList.add("");
+                    }
+                    if (StringUtils.isNotBlank(contents.get(2))) {
+                        //数据采集间隔持续时间
+                        this.sourceData.spanTimeList.add(contents.get(2));
+                    } else {
+                        //数据采集间隔持续时间
+                        this.sourceData.spanTimeList.add("");
+                    }
+                    if (StringUtils.isNotBlank(contents.get(3))) {
+                        //经度
+                        this.sourceData.lonList.add(contents.get(3));
+                    } else {
+                        //经度
+                        this.sourceData.lonList.add("");
+                    }
+                    if (StringUtils.isNotBlank(contents.get(4))) {
+                        //纬度
+                        this.sourceData.latList.add(contents.get(4));
+                    } else {
+                        //纬度
+                        this.sourceData.latList.add("");
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected String getFileSaveRelativePath() {
+        final int year = LocalDate.now().getYear();
+        final int month = LocalDate.now().getMonth().getValue();
+        final SpectrumPathProperties properties = super.spectrumServiceQuotes.getSpectrumPathProperties();
+        StringBuilder relativePath = new StringBuilder();
+        relativePath.append(properties.getFilePathMap().get(super.currDataType.getType()));
+        relativePath.append(File.separator);
+        relativePath.append(year);
+        relativePath.append(File.separator);
+        relativePath.append(month>=10?month:"0"+month);
+        return relativePath.toString();
+    }
+
+    @Override
+    protected void updateSpectrumFileName() throws FileNotFoundException {
+        StringBuilder newFileName = new StringBuilder();
+        newFileName.append(this.sourceData.stationCode);
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(super.currDataType.getType());
+        newFileName.append(StringPool.DASH);
+        newFileName.append(this.sourceData.receiveDate.replace(StringPool.SLASH, ""));
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(this.sourceData.receiveTime.replace(StringPool.COLON, ""));
+        newFileName.append(super.currDataType.getSuffix());
+        if(!super.spectrumFile.exists()){
+            //发送格式化错误事件,后续统计报告使用
+            spectrumServiceQuotes.getApplicationContext().publishEvent(new FormatErrorEvent());
+            throw new FileNotFoundException(super.spectrumFile.getAbsolutePath()+" does not exist");
+        }
+        super.spectrumFile = FileOperation.rename(super.spectrumFile,newFileName.toString(),true);
+        //设置能谱文件保存相对路径(包含文件名称)
+        String fileSavePath = this.getFileSaveRelativePath();
+        this.spectrumFileRelativePath = fileSavePath+File.separator+this.spectrumFile.getName();
+    }
+
+    @Override
+    protected void updateErrorSpectrumFileName() throws FileNotFoundException {
+        StringBuilder newFileName = new StringBuilder();
+        newFileName.append(this.sourceData.stationCode);
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(super.currDataType.getType());
+        newFileName.append(StringPool.DASH);
+        newFileName.append(this.sourceData.receiveDate.replace(StringPool.SLASH, ""));
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(this.sourceData.receiveTime.replace(StringPool.COLON, ""));
+        newFileName.append(super.currDataType.getSuffix());
+        if(!super.spectrumFile.exists()){
+            //发送格式化错误事件,后续统计报告使用
+            spectrumServiceQuotes.getApplicationContext().publishEvent(new FormatErrorEvent());
+            throw new FileNotFoundException(super.spectrumFile.getAbsolutePath()+" does not exist");
+        }
+        super.spectrumFile = FileOperation.rename(super.spectrumFile,newFileName.toString(),true);
+    }
+
+    @Override
+    protected void handlerOriginalData() throws Exception {
+        this.startIntoDatabaseTime = new Date();
+        this.gpsData = spectrumServiceQuotes.getGardsGPSDataService().create(this.sourceData, super.spectrumFileRelativePath);
+        this.endIntoDatabaseTime = new Date();
+    }
+
+    /**
+     * 把流程日志保存到日志目录
+     */
+    @Override
+    protected void saveLogToLogDir() throws IOException {
+        //获取健康谱记录ID范围
+        String gpsIdRange = "";
+        if(!CollectionUtils.isEmpty(this.gpsData)){
+            gpsIdRange = this.gpsData.get(0).getGpsId()+"-"+this.gpsData.get(this.gpsData.size()-1).getGpsId();
+        }
+        //组装日志文件内容
+        StringBuilder logContent = new StringBuilder();
+        logContent.append("-------------------------- Write Data into Database at ").append(DateUtils.formatDate(this.startIntoDatabaseTime,"yyyy-MM-dd HH:mm:ss")).append(" ---------------------------");
+        logContent.append(System.lineSeparator()).append(System.lineSeparator());
+        logContent.append("GPS ID: ").append(gpsIdRange).append(" StandardFile:").append(super.spectrumFile.getAbsolutePath());
+        logContent.append(System.lineSeparator()).append(System.lineSeparator());
+        logContent.append("------------------- ").append("Write Data into Database Successfully at ").append(DateUtils.formatDate(this.endIntoDatabaseTime,"yyyy-MM-dd HH:mm:ss")).append(" --------------------");
+
+        final SpectrumPathProperties properties = this.spectrumServiceQuotes.getSpectrumPathProperties();
+        final String dirPath = properties.getRootPath()+properties.getLogPath()+File.separator+this.getFileSaveRelativePath();
+        final String fileName = super.spectrumFile.getName().replace(this.currDataType.getSuffix(),LOG_FILE_SUFFIX);
+        final String finalPath = dirPath+ File.separator+fileName;
+
+        super.sendSpectrumLogToQueue(finalPath,logContent.toString());
+    }
+}
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/HealthStatusSpectrum.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/HealthStatusSpectrum.java
index 2fea9251..75d6c858 100644
--- a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/HealthStatusSpectrum.java
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/HealthStatusSpectrum.java
@@ -48,6 +48,12 @@ public class HealthStatusSpectrum extends AbstractSpectrumHandler{
      */
     @Override
     protected void setChina() {
+        AbstractSpectrumHandler spectrumHandler = new GPSSpectrum();
+        spectrumHandler.initNext(super.spectrumServiceQuotes,super.spectrumFile,super.sourceFilePath,
+                super.currDataType,super.mailContent,super.emlFileName,
+                super.spectrumSource,super.returnFileName, super.batchesCounter);
+        spectrumHandler.setPrevious(this);
+        super.setNext(spectrumHandler);
     }
 
     /**
@@ -102,6 +108,8 @@ public class HealthStatusSpectrum extends AbstractSpectrumHandler{
                 super.handleParseingFailFile(e);
                 throw e;
             }
+        } else {
+            super.next.handler();
         }
     }
 
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/SpectrumServiceQuotes.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/SpectrumServiceQuotes.java
index 82734ebe..df200c2f 100644
--- a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/SpectrumServiceQuotes.java
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/SpectrumServiceQuotes.java
@@ -85,6 +85,9 @@ public class SpectrumServiceQuotes {
     private final RedisUtil redisUtil;
 
     private final MaximumPoolSizeProperties maximumPoolSizeProperties;
+
+    private final IGardsGPSDataService gardsGPSDataService;
+
     /**
      * 原始库插入数据锁
      */
diff --git a/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/WaterResultSpectrum.java b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/WaterResultSpectrum.java
new file mode 100644
index 00000000..708e113f
--- /dev/null
+++ b/jeecg-module-auto-process/src/main/java/org/jeecg/modules/spectrum/WaterResultSpectrum.java
@@ -0,0 +1,219 @@
+package org.jeecg.modules.spectrum;
+
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import org.apache.commons.io.FileUtils;
+import org.jeecg.common.properties.SpectrumPathProperties;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.modules.ErrorLogManager;
+import org.jeecg.modules.base.entity.original.SampleWaterResult;
+import org.jeecg.modules.base.enums.DataType;
+import org.jeecg.modules.base.enums.SampleFileHeader;
+import org.jeecg.modules.eneity.event.FormatErrorEvent;
+import org.jeecg.modules.eneity.event.SpectrumErrorEvent;
+import org.jeecg.modules.exception.GPSFileReadException;
+import org.jeecg.modules.file.FileOperation;
+import org.jeecg.modules.native_jni.struct.WaterResultStruct;
+import org.springframework.util.CollectionUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.*;
+
+public class WaterResultSpectrum extends AbstractSpectrumHandler{
+
+    private List<String> lines = null;
+
+    private WaterResultStruct sourceData = null;
+
+    /**
+     * 开始存库时间
+     */
+    private Date startIntoDatabaseTime = null;
+    /**
+     * 结束存库时间
+     */
+    private Date endIntoDatabaseTime = null;
+
+    private List<SampleWaterResult> waterResultList = null;
+
+    @Override
+    protected void setChina() {
+    }
+
+    @Override
+    protected void preCheck() {
+        this.readFile();
+    }
+
+    protected void readFile() {
+        //获取文件内容
+        File resultFile = new File(super.spectrumFile.getAbsolutePath());
+        //判断文件是否存在,如果不存在抛出phd文件读取异常
+        if (!resultFile.exists()) {
+            throw new GPSFileReadException("This Result file cannot be found in:"+super.spectrumFile.getAbsolutePath());
+        }
+        //文件内容读取
+        try {
+            lines = FileUtils.readLines(resultFile, "UTF-8");
+        } catch (IOException e) {
+            ErrorLogManager.getInstance().write(new SpectrumErrorEvent(new Date(), "This Result file read content error", super.spectrumFile.getName()));
+            throw new GPSFileReadException("This Result file read content error");
+        }
+    }
+
+    @Override
+    public void handler() throws Exception {
+        if(DataType.RESULT.getType().equals(super.currDataType.getType())){
+            try {
+                //前置检查
+                this.preCheck();
+                //打印当前处理的能谱类型
+                super.printCurrDataType();
+                //解析邮件内容
+                this.parseingEmail();
+                //修改能谱文件名称
+                this.updateSpectrumFileName();
+                //保存PHD文件到savefile
+                super.saveFileToSavefile();
+                //结构体数据入库
+                this.handlerOriginalData();
+                //把流程日志保存到日志目录
+                this.saveLogToLogDir();
+                //若本次文件来自于undel目录,解析成功则删除
+                deleteIfFromUndelFile();
+            }catch (Exception e){
+                //异常返回文件名称用于报错日志
+                super.returnFileName.append(super.spectrumFile.getName());
+                //处理解析失败的文件
+                super.handleParseingFailFile(e);
+                throw e;
+            }
+        }
+    }
+
+    @Override
+    protected void parseingEmail() throws Exception {
+        this.sourceData = new WaterResultStruct();
+        //遍历文件内容
+        for (int i=0; i< lines.size(); i++) {
+            //获取行内容
+            String lineContent = lines.get(i);
+            //判断行内容是否包含header的内容
+            if (lineContent.contains(SampleFileHeader.HEADER.getMessage())) {
+                Map<String, String> map = new HashMap<>();
+                this.readContent(i+1, map);
+            }
+
+
+
+        }
+    }
+
+    private int readContent(int index, Map<String, String> map) {
+        int lastIndex = 0;
+        for (int i= index; i<lines.size(); i++) {
+            //从当前下标开始读取内容 直到下一个结束的标识为止 并返回结束标识的下标
+            String lineContent = lines.get(i);
+            //判断当前行是否包含# 或者 STOP 如果都不包含则进行内容读取  如果包含则跳过
+            if (!lineContent.contains("#") && !lineContent.contains(SampleFileHeader.STOP.getMessage())) {
+                //切割任意类型空格  获取行内容
+                List<String> contents = Arrays.asList(lineContent.split("\\s+"));
+                //遍历当前行内容
+                for (int j=0; j<contents.size(); j++) {
+                    String content = contents.get(j);
+
+                }
+            } else {
+                lastIndex = i;
+            }
+        }
+        return lastIndex;
+    }
+
+    @Override
+    protected String getFileSaveRelativePath() {
+        final int year = LocalDate.now().getYear();
+        final int month = LocalDate.now().getMonth().getValue();
+        final SpectrumPathProperties properties = super.spectrumServiceQuotes.getSpectrumPathProperties();
+        StringBuilder relativePath = new StringBuilder();
+        relativePath.append(properties.getFilePathMap().get(super.currDataType.getType()));
+        relativePath.append(File.separator);
+        relativePath.append(year);
+        relativePath.append(File.separator);
+        relativePath.append(month>=10?month:"0"+month);
+        return relativePath.toString();
+    }
+
+    @Override
+    protected void updateSpectrumFileName() throws FileNotFoundException {
+        StringBuilder newFileName = new StringBuilder();
+        newFileName.append(this.sourceData.stationCode);
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(super.currDataType.getType());
+        newFileName.append(StringPool.DASH);
+        newFileName.append(this.sourceData.sampleRefId.substring(5, 17));
+        newFileName.append(super.currDataType.getSuffix());
+        if(!super.spectrumFile.exists()){
+            //发送格式化错误事件,后续统计报告使用
+            spectrumServiceQuotes.getApplicationContext().publishEvent(new FormatErrorEvent());
+            throw new FileNotFoundException(super.spectrumFile.getAbsolutePath()+" does not exist");
+        }
+        super.spectrumFile = FileOperation.rename(super.spectrumFile,newFileName.toString(),true);
+        //设置能谱文件保存相对路径(包含文件名称)
+        String fileSavePath = this.getFileSaveRelativePath();
+        this.spectrumFileRelativePath = fileSavePath+File.separator+this.spectrumFile.getName();
+    }
+
+    @Override
+    protected void updateErrorSpectrumFileName() throws FileNotFoundException {
+        StringBuilder newFileName = new StringBuilder();
+        newFileName.append(this.sourceData.stationCode);
+        newFileName.append(StringPool.UNDERSCORE);
+        newFileName.append(super.currDataType.getType());
+        newFileName.append(StringPool.DASH);
+        newFileName.append(this.sourceData.sampleRefId.substring(5, 17));
+        newFileName.append(super.currDataType.getSuffix());
+        if(!super.spectrumFile.exists()){
+            //发送格式化错误事件,后续统计报告使用
+            spectrumServiceQuotes.getApplicationContext().publishEvent(new FormatErrorEvent());
+            throw new FileNotFoundException(super.spectrumFile.getAbsolutePath()+" does not exist");
+        }
+        super.spectrumFile = FileOperation.rename(super.spectrumFile,newFileName.toString(),true);
+    }
+
+    @Override
+    protected void handlerOriginalData() throws Exception {
+        this.startIntoDatabaseTime = new Date();
+//        this.gpsData = spectrumServiceQuotes.getGardsGPSDataService().create(this.sourceData, super.spectrumFileRelativePath);
+        this.endIntoDatabaseTime = new Date();
+    }
+
+    /**
+     * 把流程日志保存到日志目录
+     */
+    @Override
+    protected void saveLogToLogDir() throws IOException {
+        //获取海水结果谱记录核素ID范围
+        String nuclideIdRange = "";
+        if(!CollectionUtils.isEmpty(this.waterResultList)){
+            nuclideIdRange = this.waterResultList.get(0).getSampleResultId()+"-"+this.waterResultList.get(this.waterResultList.size()-1).getSampleResultId();
+        }
+        //组装日志文件内容
+        StringBuilder logContent = new StringBuilder();
+        logContent.append("-------------------------- Write Data into Database at ").append(DateUtils.formatDate(this.startIntoDatabaseTime,"yyyy-MM-dd HH:mm:ss")).append(" ---------------------------");
+        logContent.append(System.lineSeparator()).append(System.lineSeparator());
+        logContent.append("WATER RESULT NUCLIDE ID: ").append(nuclideIdRange).append(" StandardFile:").append(super.spectrumFile.getAbsolutePath());
+        logContent.append(System.lineSeparator()).append(System.lineSeparator());
+        logContent.append("------------------- ").append("Write Data into Database Successfully at ").append(DateUtils.formatDate(this.endIntoDatabaseTime,"yyyy-MM-dd HH:mm:ss")).append(" --------------------");
+
+        final SpectrumPathProperties properties = this.spectrumServiceQuotes.getSpectrumPathProperties();
+        final String dirPath = properties.getRootPath()+properties.getLogPath()+File.separator+this.getFileSaveRelativePath();
+        final String fileName = super.spectrumFile.getName().replace(this.currDataType.getSuffix(),LOG_FILE_SUFFIX);
+        final String finalPath = dirPath+ File.separator+fileName;
+
+        super.sendSpectrumLogToQueue(finalPath,logContent.toString());
+    }
+
+}
diff --git a/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/GPSSpectrumStruct.java b/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/GPSSpectrumStruct.java
new file mode 100644
index 00000000..c66a4c61
--- /dev/null
+++ b/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/GPSSpectrumStruct.java
@@ -0,0 +1,33 @@
+package org.jeecg.modules.native_jni.struct;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class GPSSpectrumStruct {
+
+    public String stationCode;
+
+    public String receiveDate;
+
+    public String receiveTime;
+
+    public List<String> recordDateList;
+
+    public List<String> recordTimeList;
+
+    public List<String> spanTimeList;
+
+    public List<String> lonList;
+
+    public List<String> latList;
+
+    public GPSSpectrumStruct() {
+        recordDateList = new LinkedList<>();
+        recordTimeList = new LinkedList<>();
+        spanTimeList = new LinkedList<>();
+        lonList = new LinkedList<>();
+        latList = new LinkedList<>();
+    }
+
+
+}
diff --git a/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/WaterResultStruct.java b/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/WaterResultStruct.java
new file mode 100644
index 00000000..30cddfe6
--- /dev/null
+++ b/jeecg-module-beta-gamma-analyser/src/main/java/org/jeecg/modules/native_jni/struct/WaterResultStruct.java
@@ -0,0 +1,28 @@
+package org.jeecg.modules.native_jni.struct;
+
+import org.jeecg.modules.entity.vo.ResultNuclide;
+
+import java.util.LinkedList;
+import java.util.List;
+
+
+public class WaterResultStruct {
+
+    public String stationCode;
+
+    public String detectorCode;
+
+    public String sampleRefId;
+
+    public Double lon;
+
+    public Double lat;
+
+    public List<ResultNuclide> resultNuclideList;
+
+
+    public WaterResultStruct() {
+        resultNuclideList = new LinkedList<>();
+    }
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/cache/SelfCache.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/cache/SelfCache.java
new file mode 100644
index 00000000..1ea4b6d4
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/cache/SelfCache.java
@@ -0,0 +1,48 @@
+package org.jeecg.common.cache;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.jeecg.common.properties.DurationProperties;
+import org.jeecg.modules.entity.vo.SelfStationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class SelfCache {
+
+    @Autowired
+    private DurationProperties durationProperties;
+
+    private Cache<String, SelfStationData> selfCache;
+
+    public void initCache() {
+        selfCache = CacheBuilder.newBuilder()
+                //设置缓存初始大小,应该合理设置,后续会扩容
+                .initialCapacity(10)
+                //最大值
+                .maximumSize(100)
+                //并发数设置
+                .concurrencyLevel(5)
+                //缓存过期时间,写入后XX小时后过期
+                .expireAfterWrite(durationProperties.getCache(), TimeUnit.HOURS)
+                //统计缓存命中率
+                .recordStats()
+                .build();
+    }
+
+
+    public Cache<String, SelfStationData> getSelfCache() {
+        return selfCache;
+    }
+
+    public void setSelfCache(Cache<String, SelfStationData> selfCache) {
+        this.selfCache = selfCache;
+    }
+
+    public void deleteSelfCache(String key){
+        this.selfCache.invalidate(key);
+    }
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/util/SelfStationUtil.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/util/SelfStationUtil.java
new file mode 100644
index 00000000..5ae201a7
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/common/util/SelfStationUtil.java
@@ -0,0 +1,626 @@
+package org.jeecg.common.util;
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.modules.base.abstracts.AbstractLogOrReport;
+import org.jeecg.modules.base.enums.CalName;
+import org.jeecg.modules.entity.vo.*;
+import org.jeecg.modules.native_jni.CalValuesHandler;
+import org.jeecg.modules.native_jni.EnergySpectrumHandler;
+import org.jeecg.modules.native_jni.struct.EnergySpectrumStruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.text.ParseException;
+import java.util.*;
+
+@Component
+@Slf4j
+public class SelfStationUtil extends AbstractLogOrReport {
+
+    @Autowired
+    private FTPUtil ftpUtil;
+
+    public void loadFile(SelfStationData selfStationData, Integer sampleId, String status, String systemType, Map<String, Object> map) {
+        try {
+            EnergySpectrumStruct struct = null;
+            if (systemType.equals("sample")) {
+                //读取sample的分析文件内容
+                struct = selfStationData.getSampleStruct();
+            } else if (systemType.equals("det")) {
+                struct = selfStationData.getDetStruct();
+            }
+            //存储页面操作数据
+            SelfStationVueData selfStationVueData = new SelfStationVueData();
+            //封装散点图下的基础数据信息
+            SpectrumData spectrumData = new SpectrumData();
+            //Station Code
+            String stationCode = struct.site_code;
+            //Detector Code
+            String detectorCode = struct.detector_code;
+            //Data Type
+            String dataType = struct.data_type;
+            //Collection Start
+            Date CollectionStart = null;
+            if ( StringUtils.isNotBlank(struct.collection_start_date) && StringUtils.isNotBlank(struct.collection_start_time) ){
+                CollectionStart = DateUtils.parseDate(struct.collection_start_date + StringPool.SPACE + struct.collection_start_time);
+            }
+            //Collection Stop
+            Date CollectionStop = null;
+            if ( StringUtils.isNotBlank(struct.collection_stop_date) && StringUtils.isNotBlank(struct.collection_stop_time) ){
+                CollectionStop = DateUtils.parseDate(struct.collection_stop_date + StringPool.SPACE + struct.collection_stop_time);
+            }
+            //Collection Time
+            String CollectionTime = "";
+            if ( Objects.nonNull(CollectionStart) && Objects.nonNull(CollectionStop) ){
+                CollectionTime = String.format ("%.2f",Double.valueOf((CollectionStop.getTime() - CollectionStart.getTime())/ 1000));
+            }
+            //Acquisition Start
+            Date AcquisitionStart = null;
+            if ( StringUtils.isNotBlank(struct.acquisition_start_date) && StringUtils.isNotBlank(struct.acquisition_start_time) ){
+                AcquisitionStart = DateUtils.parseDate(struct.acquisition_start_date + StringPool.SPACE + struct.acquisition_start_time);
+            }
+            //Acq Real Time
+            double AcquisitionRealTime = struct.acquisition_real_time;
+            //Acq live Time
+            double AcquisitionLiveTime = struct.acquisition_live_time;
+            //Air Volume[m3]
+            double airVolume = struct.air_volume;
+            //Xe Volume[m3]
+            double xeVolume = struct.sample_volume_of_Xe;
+            //xeCollectionYield
+            double xeCollectionYield = struct.Xe_collection_yield;
+            //gasBkMeasurementId
+            String gasBkMeasurementId = struct.gas_bk_measurement_id;
+            //detectorBkMeasurementId
+            String detectorBkMeasurementId = struct.detector_bk_measurement_id;
+            //measurementId
+            String measurementId = struct.measurement_id;
+            spectrumData.setSampleId(sampleId);
+            spectrumData.setStatus(status);
+            spectrumData.setStationCode(stationCode);
+            spectrumData.setDetectorCode(detectorCode);
+            spectrumData.setDataType(dataType);
+            spectrumData.setCollectionStart(CollectionStart);
+            spectrumData.setCollectionStop(CollectionStop);
+            spectrumData.setCollectionTime(CollectionTime);
+            spectrumData.setAcquisitionStart(AcquisitionStart);
+            spectrumData.setAcquisitionRealTime(String.format("%.2f", AcquisitionRealTime));
+            spectrumData.setAcquisitionLiveTime(String.format("%.2f", AcquisitionLiveTime));
+            spectrumData.setAirVolume(String.format("%.5f", airVolume));
+            spectrumData.setXeVolume(String.format("%.5f", xeVolume));
+            spectrumData.setYield(xeCollectionYield);
+            spectrumData.setGasBkMeasurementId(gasBkMeasurementId);
+            spectrumData.setDetectorBkMeasurementId(detectorBkMeasurementId);
+            spectrumData.setMeasurementId(measurementId);
+            map.put("spectrumData", spectrumData);
+            //根据范围1划分 范围1对应的折线图
+            Map<String, Object> oneMap = statisticsROIList(struct.POI_B_x1.get(0).intValue(), struct.POI_B_x2.get(0).intValue(), struct.b_channels, struct.g_channels, struct.h_counts);
+            if (CollectionUtils.isNotEmpty(oneMap) ) {
+                Integer startChannel = (Integer) oneMap.get("startChannel");
+                Integer endChannel = (Integer) oneMap.get("endChannel");
+                List<SeriseData> seriseDataList = (List<SeriseData>) oneMap.get("dataList");
+                if (systemType.equals("sample")) {
+                    selfStationData.getSampleVueData().setROIOneBetaStart(startChannel);
+                    selfStationData.getSampleVueData().setROIOneBetaStop(endChannel);
+                    selfStationData.getSampleVueData().setROIOneList(seriseDataList);
+                } else if (systemType.equals("det")) {
+                    selfStationData.getDetVueData().setROIOneBetaStart(startChannel);
+                    selfStationData.getDetVueData().setROIOneBetaStop(endChannel);
+                    selfStationData.getDetVueData().setROIOneList(seriseDataList);
+                }
+                map.put("ROIOneStart", startChannel);
+                map.put("ROIOneStop", endChannel);
+                map.put("ROIOneList", seriseDataList);
+            }
+            //根据范围2划分 范围2对应的折线图
+            Map<String, Object> twoMap = statisticsROIList(struct.POI_B_x1.get(1).intValue(), struct.POI_B_x2.get(1).intValue(), struct.b_channels, struct.g_channels, struct.h_counts);
+            if ( CollectionUtils.isNotEmpty(twoMap) ) {
+                Integer startChannel = (Integer) twoMap.get("startChannel");
+                Integer endChannel = (Integer) twoMap.get("endChannel");
+                List<SeriseData> seriseDataList = (List<SeriseData>) twoMap.get("dataList");
+                if (systemType.equals("sample")) {
+                    selfStationData.getSampleVueData().setROITwoBetaStart(startChannel);
+                    selfStationData.getSampleVueData().setROITwoBetaStop(endChannel);
+                    selfStationData.getSampleVueData().setROITwoList(seriseDataList);
+                } else if (systemType.equals("det")) {
+                    selfStationData.getDetVueData().setROITwoBetaStart(startChannel);
+                    selfStationData.getDetVueData().setROITwoBetaStop(endChannel);
+                    selfStationData.getDetVueData().setROITwoList(seriseDataList);
+                }
+                map.put("ROITwoStart", startChannel);
+                map.put("ROITwoStop", endChannel);
+                map.put("ROITwoList", seriseDataList);
+            }
+            //根据范围3划分 范围3对应的折线图
+            Map<String, Object> threeMap = statisticsROIList(struct.POI_B_x1.get(2).intValue(), struct.POI_B_x2.get(2).intValue(), struct.b_channels, struct.g_channels, struct.h_counts);
+            if ( CollectionUtils.isNotEmpty(threeMap) ) {
+                Integer startChannel = (Integer) threeMap.get("startChannel");
+                Integer endChannel = (Integer) threeMap.get("endChannel");
+                List<SeriseData> seriseDataList = (List<SeriseData>) threeMap.get("dataList");
+                if (systemType.equals("sample")) {
+                    selfStationData.getSampleVueData().setROIThreeBetaStart(startChannel);
+                    selfStationData.getSampleVueData().setROIThreeBetaStop(endChannel);
+                    selfStationData.getSampleVueData().setROIThreeList(seriseDataList);
+                } else if (systemType.equals("det")) {
+                    selfStationData.getDetVueData().setROIThreeBetaStart(startChannel);
+                    selfStationData.getDetVueData().setROIThreeBetaStop(endChannel);
+                    selfStationData.getDetVueData().setROIThreeList(seriseDataList);
+                }
+                map.put("ROIThreeStart", startChannel);
+                map.put("ROIThreeStop", endChannel);
+                map.put("ROIThreeList", seriseDataList);
+            }
+            //根据范围4划分 范围4对应的折线图
+            Map<String, Object> fourMap = statisticsROIList(struct.POI_B_x1.get(3).intValue(), struct.POI_B_x2.get(3).intValue(), struct.b_channels, struct.g_channels, struct.h_counts);
+            if ( CollectionUtils.isNotEmpty(fourMap) ) {
+                Integer startChannel = (Integer) fourMap.get("startChannel");
+                Integer endChannel = (Integer) fourMap.get("endChannel");
+                List<SeriseData> seriseDataList = (List<SeriseData>) fourMap.get("dataList");
+                if (systemType.equals("sample")) {
+                    selfStationData.getSampleVueData().setROIFourBetaStart(startChannel);
+                    selfStationData.getSampleVueData().setROIFourBetaStop(endChannel);
+                    selfStationData.getSampleVueData().setROIFourList(seriseDataList);
+                } else if (systemType.equals("det")) {
+                    selfStationData.getDetVueData().setROIFourBetaStart(startChannel);
+                    selfStationData.getDetVueData().setROIFourBetaStop(endChannel);
+                    selfStationData.getDetVueData().setROIFourList(seriseDataList);
+                }
+                map.put("ROIFourStart", startChannel);
+                map.put("ROIFourStop", endChannel);
+                map.put("ROIFourList", seriseDataList);
+            }
+            //散点图
+            //统计散点图
+            //横坐标 beta-gamma
+            long bChannels = struct.b_channels;
+            //纵坐标 gamma
+            long gChannels = struct.g_channels;
+            //值
+            List<Long> hCounts = struct.h_counts;
+            List<HistogramData> histogramDataList = new LinkedList<>();
+            List<HistogramData> histogramDataDList = new LinkedList<>();
+            for (int i=0; i<gChannels; i++){
+                for (int j=0; j< bChannels; j++){
+                    Long index = i * bChannels + j;
+                    Long count = hCounts.get(index.intValue());
+                    if (count > 0){
+                        HistogramData his = new HistogramData();
+                        his.setG(i);
+                        his.setB(j);
+                        his.setC(count);
+                        histogramDataList.add(his);
+                        histogramDataDList.add(his);
+                    }else {
+                        HistogramData his = new HistogramData();
+                        his.setG(i);
+                        his.setB(j);
+                        his.setC(count);
+                        histogramDataDList.add(his);
+                    }
+                }
+            }
+            map.put("histogramDataList", histogramDataList);
+//            map.put("histogramDataDList", histogramDataDList);
+            //gamma能量部分的计算参数  道值
+            List<Double> gCentroidChannel = struct.g_centroid_channel;
+            //gamma能量部分的计算参数  道值对应能量
+            List<Double> gEnergy = struct.g_energy;
+            //调用算法 传入道值和道值对应的能量 得到计算gamma能量公式的参数
+            List<Double> gammaParam = EnergySpectrumHandler.GetFileFittingPara(gCentroidChannel, gEnergy);
+            //存储需要计算gamma能量的道值
+            List<Double> gchannels = new ArrayList<>();
+            for (int i=0; i<gChannels; i++){
+                gchannels.add(Double.valueOf(i));
+            }
+            //调用算法  传递gamma参与计算的道值以及计算公式参数 得到各道值对应的能量
+            List<Double> gammaEnergyList = EnergySpectrumHandler.GetFileFittingData(gchannels, gammaParam);
+            //将gamma能量折线图进行赋值返回
+            map.put("gammaEnergyData", gammaEnergyList);
+            //beta能量部分的计算参数  道值
+            List<Double> bChannel = struct.b_channel;
+            //beta能量部分的计算参数  道值对应的能量
+            List<Double> bElectronEnergy = struct.b_electron_energy;
+            //调用算法  传入道值和道值对应的能量  得到计算beta能量公式的参数
+            List<Double> betaParam = EnergySpectrumHandler.GetFileFittingPara(bChannel, bElectronEnergy);
+            List<Double> bchannels = new ArrayList<>();
+            for (int i=0; i<bChannels; i++){
+                bchannels.add(Double.valueOf(i));
+            }
+            //传入道值和计算公式的参数计算出各道值对应的beta能量
+            List<Double> betaEnergyList = EnergySpectrumHandler.GetFileFittingData(bchannels, betaParam);
+            //将beta能量折线图进行赋值返回
+            map.put("betaEnergyData", betaEnergyList);
+
+            //g_Energy
+            if (CollectionUtils.isNotEmpty(struct.g_energy) && CollectionUtils.isNotEmpty(struct.g_centroid_channel) && CollectionUtils.isNotEmpty(struct.g_uncertainty) && Objects.nonNull(struct.g_record_count)) {
+                if (systemType.equals("sample")) {
+                    GEnergyBlock gEnergyBlock = new GEnergyBlock();
+                    gEnergyBlock.setG_energy(struct.g_energy);
+                    gEnergyBlock.setCentroid_channel(struct.g_centroid_channel);
+                    gEnergyBlock.setUncertainty(struct.g_uncertainty);
+                    gEnergyBlock.setRecord_count(struct.g_record_count);
+                    selfStationData.getSampleVueData().getMapEnerKD().put(CalName.CalPHD.getType(), gEnergyBlock);
+                    //计算得到公式的参数
+                    List<Double> calEnergyParam = CalValuesHandler.calFitPara("Cal_Energy", 2, struct.g_centroid_channel, struct.g_energy, struct.g_uncertainty);
+                    ParameterInfo parameterInfo = new ParameterInfo();
+                    parameterInfo.setP(calEnergyParam);
+                    selfStationData.getSampleVueData().getMapEnerPara().put(CalName.CalPHD.getType(), parameterInfo);
+                }
+            }
+            //g_Resolution
+            if (CollectionUtils.isNotEmpty(struct.g_r_energy) && CollectionUtils.isNotEmpty(struct.g_r_FWHM) && CollectionUtils.isNotEmpty(struct.g_r_uncertainty) && Objects.nonNull(struct.g_r_record_count)) {
+                if (systemType.equals("sample")) {
+                    GResolutionBlock gResolutionBlock = new GResolutionBlock();
+                    gResolutionBlock.setG_energy(struct.g_r_energy);
+                    gResolutionBlock.setFWHM(struct.g_r_FWHM);
+                    gResolutionBlock.setUncertainty(struct.g_r_uncertainty);
+                    gResolutionBlock.setRecord_count(struct.g_r_record_count);
+                    selfStationData.getSampleVueData().getMapResoKD().put(CalName.CalPHD.getType(), gResolutionBlock);
+                    //计算得到公式的参数
+                    List<Double> calEnergyParam = CalValuesHandler.calFitPara("Cal_Resolution", 4, struct.g_r_energy, struct.g_r_FWHM, struct.g_r_uncertainty);
+                    ParameterInfo parameterInfo = new ParameterInfo();
+                    parameterInfo.setP(calEnergyParam);
+                    selfStationData.getSampleVueData().getMapResoPara().put(CalName.CalPHD.getType(), parameterInfo);
+                }
+            }
+            //g_Efficiency
+            if (CollectionUtils.isNotEmpty(struct.g_e_energy) && CollectionUtils.isNotEmpty(struct.g_e_efficiency) && CollectionUtils.isNotEmpty(struct.g_e_uncertainty) && Objects.nonNull(struct.g_e_record_count)) {
+                if (systemType.equals("sample")) {
+                    GEfficiencyBlock gEfficiencyBlock = new GEfficiencyBlock();
+                    gEfficiencyBlock.setG_energy(struct.g_e_energy);
+                    gEfficiencyBlock.setEfficiency(struct.g_e_efficiency);
+                    gEfficiencyBlock.setUncertainty(struct.g_e_uncertainty);
+                    gEfficiencyBlock.setRecord_count(struct.g_e_record_count);
+                    selfStationData.getSampleVueData().getMapEffiKD().put(CalName.CalPHD.getType(), gEfficiencyBlock);
+                    //计算得到公式的参数
+                    List<Double> calEnergyParam = CalValuesHandler.calFitPara("Cal_Efficiency", 1, struct.g_e_energy, struct.g_e_efficiency, struct.g_e_uncertainty);
+                    ParameterInfo parameterInfo = new ParameterInfo();
+                    parameterInfo.setP(calEnergyParam);
+                    selfStationData.getSampleVueData().getMapEffiPara().put(CalName.CalPHD.getType(), parameterInfo);
+                }
+            }
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     *  根据文件路径,类型获取对应的解析文件内容并返回进行存储
+     * @param filePathName
+     * @param type
+     * @param selfStationData
+     * @return
+     */
+    public EnergySpectrumStruct getSourceData(String filePathName, String type, SelfStationData selfStationData) {
+        EnergySpectrumStruct struct = null;
+        File file = null;
+        try {
+            //根据完整的文件路径 获取临时文件
+            file = ftpUtil.downloadFile(filePathName, "betaGamma");
+            if (Objects.nonNull(file)) {
+                if (type.equalsIgnoreCase("sample")) {
+                    selfStationData.setSampleTmpPath(file.getAbsolutePath());
+                } else if (type.equalsIgnoreCase("det")) {
+                    selfStationData.setDetTmpPath(file.getAbsolutePath());
+                }
+                //解析文件内容
+                struct = EnergySpectrumHandler.getSourceData(file.getAbsolutePath());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return struct;
+    }
+
+    /**
+     *  统计道值范围内数量
+     * @param startChannel 起始道值
+     * @param endChannel 结束道值
+     * @param betaChannels 行数
+     * @param gammaChannels 列数
+     * @param h_counts 计数数组
+     */
+    public Map<String, Object> statisticsROIList(Integer startChannel, Integer endChannel, long betaChannels, long gammaChannels, List<Long> h_counts) {
+        Map<String, Object> map = new HashMap<>();
+        //存储同一列不同行加和后的数量
+        List<Integer> sumList = new LinkedList<>();
+        List<SeriseData> seriseDataList = new LinkedList<>();
+        //遍历所有列
+        for (int i=0; i<gammaChannels; i++) {
+            SeriseData seriseData = new SeriseData();
+            seriseData.setX(i);
+            int sum = 0;
+            //根据起始道值和结束道值  获取这一列的所有对应道值的数据
+            for (int j=startChannel; j <= endChannel; j++) {
+                //列数 * 总行数 + 当前行下标  获取对应的数据数组下标
+                int index = (int) (i * betaChannels + j);
+                long count = 0;
+                //判断下标是否在h_counts范围内
+                if (index < h_counts.size()) {
+                    count = h_counts.get(index);
+                }
+                sum+=count;
+            }
+            seriseData.setY(sum);
+            sumList.add(sum);
+            seriseDataList.add(seriseData);
+        }
+        map.put("startChannel", startChannel);
+        map.put("endChannel", endChannel);
+        map.put("dataList", seriseDataList);
+        return map;
+    }
+
+    public String UpdateEquationEnergy(ParameterInfo m_curParam) {
+        String equation ="";
+        int p_size = m_curParam.getP().size()-1;
+        if(p_size >= 2 && m_curParam.getP().get(2) > 0) {
+            // Polynomial: y=a0+a1*x+a2*x^2+a3*x^3
+            equation +="Energy = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" + C * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)));
+            for(int i=3; i<=p_size; i++) {
+                equation += " + C<sup style=\"vertical-align:super;\">" + (i-1) +"</sup> * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i)))+"";
+            }
+        } else if(p_size == 1) {
+            equation = "Energy = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" * C";
+        }
+        return equation;
+    }
+
+    public void UpdateChartEnergy(List<Double> m_vCurEnergy, ParameterInfo m_curParam, List<Double> m_vCurCentroid, SelfStationData selfStationData, Double width, Map<String, Object> map) {
+        int num = m_vCurEnergy.size();
+        if(num < 1){
+            return;
+        }
+        List<ChartData> datalist = new LinkedList<>();
+        if(CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            // 拟合曲线
+            ChartData lData = new ChartData();
+            lData.setColor("rgb(255, 255, 0)");
+            lData.setType("Line");
+
+            List<Double> vChan = new LinkedList<>();
+            double MaxChan = Double.valueOf(selfStationData.getSampleStruct().g_channels);
+            double d = 1;
+            double dStep = MaxChan / width * 2;
+            while(d < MaxChan) {
+                vChan.add(d);
+                d+= dStep;
+            }
+            vChan.add(MaxChan);
+
+            List<Double> vFit = CalValuesHandler.calFcnEval(vChan, m_curParam.getP()).counts;
+            for(int i=0; i<vChan.size(); i++) {
+                if(vFit.get(i) > 0){
+                    SeriseData seriseData = new SeriseData();
+                    seriseData.setX(vChan.get(i));
+                    seriseData.setY(vFit.get(i));
+                    lData.getPointlist().add(seriseData);
+                }
+            }
+            if(lData.getPointlist().size() > 1){
+                datalist.add(lData);
+            }
+        }
+
+        // Channel——Energy 点集
+        ChartData pData = new ChartData();
+        pData.setColor("red");
+        pData.setType("Scatter");
+        for(int i=0; i<num; i++) {
+            SeriseData seriseData = new SeriseData();
+            seriseData.setX(m_vCurCentroid.get(i));
+            seriseData.setY(m_vCurEnergy.get(i));
+            pData.getPointlist().add(seriseData);
+        }
+        datalist.add(pData);
+        map.put("AllData", datalist);
+    }
+
+    public String UpdateEquationResolution(ParameterInfo m_curParam) {
+        String equation = "";
+        int p_size = m_curParam.getP().size()-1;
+        if(p_size >= 2 && m_curParam.getP().get(1) > 0 && m_curParam.getP().get(2) > 0) {
+            // Square root of polynomial: y = sqrt(a0+a1*x+a2*x^2+a3*x^3 )
+            equation += "FWHM = ("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" + E * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)));
+            for(int i=3; i<=p_size; i++) {
+                equation += " + E<sup style=\"vertical-align:super;\">"+(i-1)+"</sup> * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i)));
+            }
+            equation += ")<sup style=\"vertical-align:super;\">"+1+"/"+2+"</sup>";
+        }
+        return equation;
+    }
+
+    public void UpdateChartResolution(List<Double> m_vCurEnergy, ParameterInfo m_curParam, List<Double> m_vCurReso, SelfStationData selfStationData, Double width, Map<String, Object> map) {
+        int num = m_vCurEnergy.size();
+        if(num < 1) return;
+
+        List<ChartData> datalist = new LinkedList<>();
+        if(CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            // 拟合曲线
+            ChartData lData = new ChartData();
+            lData.setColor("rgb(255, 255, 0)");
+            lData.setType("Line");
+
+            List<Double> vChan = new LinkedList<>();
+            vChan.add(1.0);
+            vChan.add(Double.valueOf(selfStationData.getSampleStruct().g_channels));
+
+            List<Double> vEner = CalValuesHandler.calFcnEval(vChan, selfStationData.getSampleVueData().getUsedEnerPara().getP()).counts;
+            double d = vEner.get(0), maxE = vEner.get(1);
+            double dStep = maxE / width * 2;
+
+            vEner.remove(vEner.size()-1);
+            while(d < maxE) {
+                vEner.add(d);
+                d += dStep;
+            }
+            vEner.add(maxE);
+
+            List<Double> vFit = CalValuesHandler.calFcnEval(vEner, m_curParam.getP()).counts;
+            for(int i=0; i<vEner.size(); i++) {
+                if(vFit.get(i) > 0){
+                    SeriseData seriseData = new SeriseData();
+                    seriseData.setX(vEner.get(i));
+                    seriseData.setY(vFit.get(i));
+                    lData.getPointlist().add(seriseData);
+                }
+            }
+            if(lData.getPointlist().size() > 1){
+                datalist.add(lData);
+            }
+        }
+
+        // Channel——Energy 点集
+        ChartData pData = new ChartData();
+        pData.setColor("red");
+        pData.setType("Scatter");
+        for(int i=0; i<num; i++) {
+            SeriseData seriseData = new SeriseData();
+            seriseData.setX(m_vCurEnergy.get(i));
+            seriseData.setY(m_vCurReso.get(i));
+            pData.getPointlist().add(seriseData);
+        }
+        datalist.add(pData);
+        map.put("AllData", datalist);
+    }
+
+    public String UpdateEquationEfficiency(List<Double> m_vCurEnergy, ParameterInfo m_curParam, Integer curRow, Integer funId) {
+        String equation = "";
+        if(m_curParam.getP().size() > 2) {
+            int p_size = m_curParam.getP().size()-1;
+            int e_size = m_vCurEnergy.size();
+            if (Objects.isNull(funId)) {
+                funId = m_curParam.getP().get(0).intValue();
+            }
+            switch(funId) {
+                case 1: // Interpolation: y=yi+(y(i+1)-yi)*(x-xi)/(x(i+1)-xi) for xi<=x<x(i+1)
+                    if(p_size == 2 * e_size && p_size >= 4) {
+                        int i = curRow;
+                        if(i < 0 || i >= e_size) break;
+
+                        double y1, y0, x1, x0;
+                        if(i < e_size - 1)
+                        {
+                            y1 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2+3))));
+                            y0 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2+1))));
+                            x1 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2+2))));
+                            x0 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2))));
+                        } else {
+                            y1 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2+1))));
+                            y0 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2-1))));
+                            x1 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2))));
+                            x0 = Double.valueOf(NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i*2-2))));
+                        }
+                        equation += "Efficiency = "+y0+" + ("+y1+"-"+y0+") * (E - "+x0+") / ("+x1+" - "+x0+")";
+                    }
+                    break;
+                case 5: // HT Efficiency: y = A*exp(-(E1/x)^k)*(1-exp(-(E2/x)^n))
+                    if(p_size == 5) {
+                        for(int i=1; i<=p_size; i++) {
+                            if(m_curParam.getP().get(i) <= 0) break;
+                        }
+                        equation += "Efficiency = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" * exp(-("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" / E)<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(3)))+"</sup>) * "+
+                                "(1-exp(-("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(4)))+" / E)<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(5)))+"</sup>))";
+                    }
+                    break;
+                case 6: // Polynomial in log(y) against log(x): log(y) = a0 + a1*log(x) +a2*log(x)^2+ a3*log(x)^3
+                    if(p_size >= 2) {
+                        equation += "log(Efficiency) = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" + "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" * log(E)";
+                        for(int i=3; i<=p_size; i++) {
+                            equation += " + "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i)))+" * log(E)<sup style=\"vertical-align:super;\">"+(i-1)+"</sup>";
+                        }
+                    }
+                    break;
+                case 8: // Polynomial in log(y) against log(1/x): log(y) = a0 + a1*log(c/x) + a2*log(c/x)^2 + a3*log(c/x)^3 + a4*log(c/x)^4
+                    if(p_size >= 3) {
+                        equation += "log(Efficiency) = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" + "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" * log(C/E)";
+                        for(int i=3; i<=p_size; i++) {
+                            equation += " + "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(i)))+" * log(C/E)<sup style=\"vertical-align:super;\">"+(i-1)+"</sup>";
+                        }
+                    }
+                    break;
+                case 93: // HAE Efficiency (1-3): y=S*exp(-(E1/x)^k)*(1- exp(-(2*E3/(x-E3))^n))
+                    if(p_size == 5) {
+                        equation += "Efficiency = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" * exp(-("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" / E)<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(3)))+"</sup>) * "+
+                                "(1 - exp(-(2 * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(4)))+" / (E - "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(4)))+"))<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(5)))+"</sup>))";
+                    }
+                    break;
+                case 94: // HAE Efficiency (1-2): y=S*exp(-(E1/x)^k)*(1- exp(-b*(1/(x-E2))^m))
+                    if(p_size == 6) {
+                        equation += "Efficiency = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" * exp(-("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" / E)<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(3)))+"</sup>) * "+
+                                "(1 - exp(-"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(4)))+" * (1 / (E - "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(5)))+"))<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(6)))+"</sup>))";
+                    }
+                    break;
+                case 95: // HAE Efficiency (1-2-3): y = S * exp(-(E1/x)^k) * (1- exp(-b*(1/(x-E2))^m)) *(1 - exp(-(2*E3/(E-E3))^n))
+                    if(p_size == 8) {
+                        equation += "Efficiency = "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(1)))+" * exp(-("+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(2)))+" / E)<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(3)))+"</sup>) * "+
+                                "(1 - exp(-"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(4)))+" * (1 / (E - "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(5)))+"))<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(6)))+"</sup>)) * "+
+                                "(1 - exp(-(2 * "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(7)))+" / (E - "+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(7)))+"))<sup style=\"vertical-align:super;\">"+NumberFormatUtil.numberFormat(String.valueOf(m_curParam.getP().get(8)))+"</sup>))";
+                    }
+                    break;
+            }
+        }
+        return equation;
+    }
+
+    public void UpdateChartEfficiency(List<Double> m_vCurEnergy, ParameterInfo m_curParam, List<Double> m_vCurEffi, SelfStationData selfStationData, Double width, Map<String, Object> map) {
+        int num = m_vCurEnergy.size();
+        if(num < 1) return;
+
+        List<ChartData> datalist = new LinkedList<>();
+        if(CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            // 拟合曲线
+            ChartData lData = new ChartData();
+            lData.setColor("rgb(255, 255, 0)");
+            lData.setType("Line");
+
+            List<Double> vChan = new LinkedList<>();
+            vChan.add(1.0);
+            vChan.add(Double.valueOf(selfStationData.getSampleStruct().g_channels));
+
+            List<Double> vEner = CalValuesHandler.calFcnEval(vChan, selfStationData.getSampleVueData().getUsedEnerPara().getP()).counts;
+            double d = vEner.get(0);
+            double maxE = vEner.get(1);
+            double dStep = maxE / width * 2;
+
+            vEner.remove(vEner.size()-1);
+            while(d < maxE) {
+                vEner.add(d);
+                d += dStep;
+            }
+            vEner.add(maxE);
+
+            List<Double> vFit = CalValuesHandler.calFcnEval(vEner, m_curParam.getP()).counts;
+            for(int i=0; i<vEner.size(); i++) {
+                if(vFit.get(i) > 0){
+                    SeriseData seriseData = new SeriseData();
+                    seriseData.setX(vEner.get(i));
+                    seriseData.setY(vFit.get(i));
+                    lData.getPointlist().add(seriseData);
+                }
+            }
+            if(lData.getPointlist().size() > 1){
+                datalist.add(lData);
+            }
+        }
+
+        // Channel——Energy 点集
+        ChartData pData = new ChartData();
+        pData.setColor("red");
+        pData.setType("Scatter");
+        for(int i=0; i<num; i++) {
+            SeriseData seriseData = new SeriseData();
+            seriseData.setX(m_vCurEnergy.get(i));
+            seriseData.setY(m_vCurEffi.get(i));
+            pData.getPointlist().add(seriseData);
+        }
+        datalist.add(pData);
+        map.put("AllData", datalist);
+    }
+
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/controller/SelfStationController.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/controller/SelfStationController.java
new file mode 100644
index 00000000..7f694766
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/controller/SelfStationController.java
@@ -0,0 +1,161 @@
+package org.jeecg.modules.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.entity.vo.ChangeData;
+import org.jeecg.modules.service.ISelfStationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@RestController
+@RequestMapping("selfStation")
+@Api(value = "自建台站管理", tags = "自建台站管理")
+public class SelfStationController {
+
+    @Autowired
+    private ISelfStationService selfStationService;
+
+    @GetMapping("initValue")
+    @ApiOperation(value = "预加载谱文件数据", notes = "预加载谱文件数据")
+    public void initValue(String dbName, Integer sampleId, String analyst, String sampleFileName, String detFileName, HttpServletRequest request) {
+        selfStationService.initValue(dbName, sampleId, analyst, sampleFileName, detFileName, request);
+    }
+
+    @GetMapping("loadFromDB")
+    @ApiOperation(value = "从数据库加载自建台站数据", notes = "从数据库加载自建台站数据")
+    public Result loadFromDB(String dbName, Integer sampleId, String analyst, HttpServletRequest request) {
+        return selfStationService.loadFromDB(dbName, sampleId, analyst, request);
+    }
+
+    @GetMapping("loadFromFile")
+    @ApiOperation(value = "从文件加载自建台站谱数据", notes = "从文件加载自建台站谱数据")
+    public Result loadFromFile(String sampleFileName, String detFileName, HttpServletRequest request) {
+        return selfStationService.loadSelfStationByFile(sampleFileName, detFileName, request);
+    }
+
+    @DeleteMapping("deleteSelfStationCache")
+    public void deleteSelfStationCache(String sampleFileName, HttpServletRequest request) {
+        selfStationService.deleteSelfStationCache(sampleFileName, request);
+    }
+
+    @PutMapping("updateROI")
+    @ApiOperation(value = "更新ROI范围", notes = "更新ROI范围")
+    public Result updateROI(Integer startChannel, Integer endChannel, Integer ROINum, String sampleFileName, HttpServletRequest request) {
+        return selfStationService.updateROI(startChannel, endChannel, ROINum, sampleFileName, request);
+    }
+
+    @GetMapping("energyCalibration")
+    @ApiOperation(value = "查看Energy Calibration数据", notes = "查看Energy Calibration数据")
+    public Result energyCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        return selfStationService.energyCalibration(fileName, currentText, width, request);
+    }
+
+    @PostMapping("changeDataEnergy")
+    @ApiOperation(value = "修改Energy Calibration数据", notes = "修改Energy Calibration数据")
+    public Result changeDataEnergy(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.changeDataEnergy(changeData.getM_vCurCentroid(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getSampleId(), changeData.getFileName(), changeData.getWidth(), request);
+    }
+
+    @PostMapping("applyDataEnergy")
+    @ApiOperation(value = "Apply Energy Calibration数据", notes = "Apply Energy Calibration数据")
+    public Result applyDataEnergy(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.applyDataEnergy(changeData.getM_vCurCentroid(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getCurCalName(), changeData.getSampleId(), changeData.getFileName(), request);
+    }
+
+    @PostMapping("saveDataEnergy")
+    @ApiOperation(value = "保存Energy Calibration数据", notes = "保存Energy Calibration数据")
+    public void saveDataEnergy(@RequestBody ChangeData changeData, HttpServletResponse response) {
+        selfStationService.saveDataEnergy(changeData.getM_vCurCentroid(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), response);
+    }
+
+    @PostMapping("callDataEnergy")
+    @ApiOperation(value = "导入Energy Calibration数据", notes = "导入Energy Calibration数据")
+    public Result callDataEnergy(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        return selfStationService.callDataEnergy(file, sampleFileName, width, currentText, request);
+    }
+
+    @PutMapping("setCurrentEnergy")
+    @ApiOperation(value = "Energy Calibration页面set to current按钮", notes = "Energy Calibration页面set to current按钮")
+    public Result setCurrentEnergy(String fileName, String currentName, HttpServletRequest request) {
+        return selfStationService.setCurrentEnergy(fileName, currentName, request);
+    }
+
+    @GetMapping("resolutionCalibration")
+    @ApiOperation(value = "查看Resolution Calibration数据", notes = "查看Resolution Calibration数据")
+    public Result resolutionCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        return selfStationService.resolutionCalibration(fileName, currentText, width, request);
+    }
+
+    @PostMapping("changeDataResolution")
+    @ApiOperation(value = "修改Resolution Calibration数据", notes = "修改Resolution Calibration数据")
+    public Result changeDataResolution(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.changeDataResolution(changeData.getM_vCurReso(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getSampleId(), changeData.getFileName(), changeData.getWidth(), request);
+    }
+
+    @PostMapping("applyDataResolution")
+    @ApiOperation(value = "Apply Resolution Calibration数据", notes = "Apply Resolution Calibration数据")
+    public Result applyDataResolution(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.applyDataResolution(changeData.getM_vCurReso(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getCurCalName(), changeData.getSampleId(), changeData.getFileName(), request);
+    }
+
+    @PostMapping("saveDataResolution")
+    @ApiOperation(value = "保存Resolution Calibration数据", notes = "保存Resolution Calibration数据")
+    public void saveDataResolution(@RequestBody ChangeData changeData, HttpServletResponse response) {
+        selfStationService.saveDataResolution(changeData.getM_vCurReso(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), response);
+    }
+
+    @PostMapping("callDataResolution")
+    @ApiOperation(value = "导入Resolution Calibration数据", notes = "导入Resolution Calibration数据")
+    public Result callDataResolution(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        return selfStationService.callDataResolution(file, sampleFileName, width, currentText, request);
+    }
+
+    @PutMapping("setCurrentResolution")
+    @ApiOperation(value = "Resolution Calibration页面set to current按钮", notes = "Resolution Calibration页面set to current按钮")
+    public Result setCurrentResolution(String fileName, String currentName, HttpServletRequest request) {
+        return selfStationService.setCurrentResolution(fileName, currentName, request);
+    }
+
+    @GetMapping("EfficiencyCalibration")
+    @ApiOperation(value = "查看Efficiency Calibration数据", notes = "查看Efficiency Calibration数据")
+    public Result EfficiencyCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        return selfStationService.EfficiencyCalibration(fileName, currentText, width, request);
+    }
+
+    @PostMapping("changeDataEfficiency")
+    @ApiOperation(value = "修改Efficiency Calibration数据", notes = "修改Efficiency Calibration数据")
+    public Result changeDataEfficiency(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.changeDataEfficiency(changeData.getM_vCurEffi(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getFuncId(), changeData.getSampleId(), changeData.getFileName(), changeData.getWidth(), changeData.getCurRow(), request);
+    }
+
+    @PostMapping("applyDataEfficiency")
+    @ApiOperation(value = "Apply Efficiency Calibration数据", notes = "Apply Efficiency Calibration数据")
+    public Result applyDataEfficiency(@RequestBody ChangeData changeData, HttpServletRequest request) {
+        return selfStationService.applyDataEfficiency(changeData.getM_vCurEffi(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getM_curParam(), changeData.getCurCalName(), changeData.getSampleId(), changeData.getFileName(), request);
+    }
+
+    @PostMapping("saveDataEfficiency")
+    @ApiOperation(value = "保存Efficiency Calibration数据", notes = "保存Efficiency Calibration数据")
+    public void saveDataEfficiency(@RequestBody ChangeData changeData, HttpServletResponse response) {
+        selfStationService.saveDataEfficiency(changeData.getM_vCurEffi(), changeData.getM_vCurEnergy(), changeData.getM_vCurUncert(), changeData.getFuncId(), response);
+    }
+
+    @PostMapping("callDataEfficiency")
+    @ApiOperation(value = "导入Efficiency Calibration数据", notes = "导入Efficiency Calibration数据")
+    public Result callDataEfficiency(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        return selfStationService.callDataEfficiency(file, sampleFileName, width, currentText, request);
+    }
+
+    @PutMapping("setCurrentEfficiency")
+    @ApiOperation(value = "Efficiency Calibration页面set to current按钮", notes = "Efficiency Calibration页面set to current按钮")
+    public Result setCurrentEfficiency(String fileName, String currentName, HttpServletRequest request) {
+        return selfStationService.setCurrentEfficiency(fileName, currentName, request);
+    }
+
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationData.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationData.java
new file mode 100644
index 00000000..b7d21fb6
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationData.java
@@ -0,0 +1,49 @@
+package org.jeecg.modules.entity.vo;
+
+import lombok.Data;
+import org.jeecg.modules.native_jni.struct.EnergySpectrumStruct;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class SelfStationData implements Serializable {
+
+    /**
+     *  sample临时文件路径
+     */
+    private String sampleTmpPath;
+
+    /**
+     *  det临时文件路径
+     */
+    private String detTmpPath;
+
+    /**
+     *  sample文件分析内容
+     */
+    private EnergySpectrumStruct sampleStruct;
+
+    /**
+     *  det文件分析内容
+     */
+    private EnergySpectrumStruct detStruct;
+
+    /**
+     *  sample对应的操作数据
+     */
+    private SelfStationVueData sampleVueData;
+
+    /**
+     *  det对应的操作数据
+     */
+    private SelfStationVueData detVueData;
+
+    public SelfStationData() {
+        sampleVueData = new SelfStationVueData();
+        detVueData = new SelfStationVueData();
+    }
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationVueData.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationVueData.java
new file mode 100644
index 00000000..0a87d485
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/entity/vo/SelfStationVueData.java
@@ -0,0 +1,115 @@
+package org.jeecg.modules.entity.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class SelfStationVueData implements Serializable {
+
+    /**
+     *  ROI-1结果数据
+     */
+    //折线图横纵坐标数组
+    private List<SeriseData> ROIOneList;
+    //ROI-1范围矩形框起始道值
+    private Integer ROIOneBetaStart;
+    //ROI-1范围矩形框终止道值
+    private Integer ROIOneBetaStop;
+
+    /**
+     *  ROI-2结果数据
+     */
+    //折线图横纵坐标数组
+    private List<SeriseData> ROITwoList;
+    //ROI-2范围矩形框起始道值
+    private Integer ROITwoBetaStart;
+    //ROI-2范围矩形框终止道值
+    private Integer ROITwoBetaStop;
+
+    /**
+     *  ROI-3结果数据
+     */
+    //折线图横纵坐标数组
+    private List<SeriseData> ROIThreeList;
+    //ROI-3范围矩形框起始道值
+    private Integer ROIThreeBetaStart;
+    //ROI-3范围矩形框终止道值
+    private Integer ROIThreeBetaStop;
+
+    /**
+     *  ROI-4结果数据
+     */
+    //折线图横纵坐标数组
+    private List<SeriseData> ROIFourList;
+    //ROI-4范围矩形框起始道值
+    private Integer ROIFourBetaStart;
+    //ROI-4范围矩形框终止道值
+    private Integer ROIFourBetaStop;
+
+    // 当前修改的刻度名称
+    private String newEner;
+
+    private String newReso;
+
+    private String newEffi;
+
+    /**
+     *  使用中的能量参数对应的刻度名称
+     */
+    private String usedEner;
+
+    private String usedReso;
+
+    private String usedEffi;
+
+    // 当前寻峰结果所用的刻度数据
+    private GEnergyBlock usedEnerKD;
+
+    private GResolutionBlock usedResoKD;
+
+    private GEfficiencyBlock usedEffiKD;
+
+    // 存储所有的刻度数据
+    private Map<String, GEnergyBlock> mapEnerKD; // 能量刻度
+
+    private Map<String, GResolutionBlock> mapResoKD; // 分辨率刻度
+
+    private Map<String, GEfficiencyBlock> mapEffiKD; // 效率刻度
+
+    // 当前寻峰结果所用的刻度参数
+    private ParameterInfo usedEnerPara;
+
+    private ParameterInfo usedResoPara;
+
+    private ParameterInfo usedEffiPara;
+
+    // 存储所有的刻度参数
+    private Map<String, ParameterInfo> mapEnerPara;
+
+    private Map<String, ParameterInfo> mapResoPara;
+
+    private Map<String, ParameterInfo> mapEffiPara;
+
+    public SelfStationVueData() {
+        newEner = "PHD";
+        newReso = "PHD";
+        newEffi = "PHD";
+        usedEner= "";
+        usedReso= "";
+        usedEffi= "";
+        mapEnerKD = new HashMap<>();
+        mapResoKD = new HashMap<>();
+        mapEffiKD = new HashMap<>();
+        usedEnerPara = new ParameterInfo();
+        usedResoPara = new ParameterInfo();
+        usedEffiPara = new ParameterInfo();
+        mapEnerPara = new HashMap<>();
+        mapResoPara = new HashMap<>();
+        mapEffiPara = new HashMap<>();
+    }
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/ISelfStationService.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/ISelfStationService.java
new file mode 100644
index 00000000..ce1bff40
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/ISelfStationService.java
@@ -0,0 +1,59 @@
+package org.jeecg.modules.service;
+
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.entity.vo.ParameterInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+public interface ISelfStationService {
+
+    void initValue(String dbName, Integer sampleId, String analyst, String sampleFileName, String detFileName, HttpServletRequest request);
+
+    Result loadFromDB(String dbName, Integer sampleId, String analyst, HttpServletRequest request);
+
+    Result loadSelfStationByFile(String sampleFileName, String detFileName, HttpServletRequest request);
+
+    void deleteSelfStationCache(String sampleFileName, HttpServletRequest request);
+
+    Result updateROI(Integer startChannel, Integer endChannel, Integer ROINum, String sampleFileName, HttpServletRequest request);
+
+    Result energyCalibration(String fileName, String currentText, Double width, HttpServletRequest request);
+
+    Result changeDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer sampleId, String fileName, Double width, HttpServletRequest request);
+
+    Result applyDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request);
+
+    void saveDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, HttpServletResponse response);
+
+    Result callDataEnergy(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request);
+
+    Result setCurrentEnergy(String fileName, String currentName, HttpServletRequest request);
+
+    Result resolutionCalibration(String fileName, String currentText, Double width, HttpServletRequest request);
+
+    Result changeDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer sampleId, String fileName, Double width, HttpServletRequest request);
+
+    Result applyDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request);
+
+    void saveDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, HttpServletResponse response);
+
+    Result callDataResolution(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request);
+
+    Result setCurrentResolution(String fileName, String currentName, HttpServletRequest request);
+
+    Result EfficiencyCalibration(String fileName, String currentText, Double width, HttpServletRequest request);
+
+    Result changeDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer funcId, Integer sampleId, String fileName, Double width, Integer curRow, HttpServletRequest request);
+
+    Result applyDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request);
+
+    void saveDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, Integer funId, HttpServletResponse response);
+
+    Result callDataEfficiency(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request);
+
+    Result setCurrentEfficiency(String fileName, String currentName, HttpServletRequest request);
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SelfStationServiceImpl.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SelfStationServiceImpl.java
new file mode 100644
index 00000000..fa9b3f06
--- /dev/null
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SelfStationServiceImpl.java
@@ -0,0 +1,1163 @@
+package org.jeecg.modules.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.google.common.cache.Cache;
+import org.apache.commons.io.FileUtils;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.cache.SelfCache;
+import org.jeecg.common.properties.SpectrumPathProperties;
+import org.jeecg.common.system.util.JwtUtil;
+import org.jeecg.common.util.FTPUtil;
+import org.jeecg.common.util.PHDFileUtil;
+import org.jeecg.common.util.SelfStationUtil;
+import org.jeecg.modules.base.entity.original.GardsSampleData;
+import org.jeecg.modules.entity.vo.*;
+import org.jeecg.modules.mapper.SpectrumAnalysisMapper;
+import org.jeecg.modules.native_jni.CalValuesHandler;
+import org.jeecg.modules.native_jni.EnergySpectrumHandler;
+import org.jeecg.modules.native_jni.struct.EnergySpectrumStruct;
+import org.jeecg.modules.service.ISelfStationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class SelfStationServiceImpl implements ISelfStationService {
+
+    @Autowired
+    private FTPUtil ftpUtil;
+    @Autowired
+    private SpectrumPathProperties spectrumPathProperties;
+    @Autowired
+    private SelfStationUtil selfStationUtil;
+    @Autowired
+    private SelfCache selfStationCache;
+    @Autowired
+    private SpectrumAnalysisMapper spectrumAnalysisMapper;
+
+    @Override
+    public void initValue(String dbName, Integer sampleId, String analyst, String sampleFileName, String detFileName, HttpServletRequest request) {
+        if (StringUtils.isNotBlank(dbName) && Objects.nonNull(sampleId)) {
+            loadFromDB(dbName, sampleId, analyst, request);
+        } else {
+            loadSelfStationByFile(sampleFileName, detFileName, request);
+        }
+    }
+
+    @Override
+    public Result loadFromDB(String dbName, Integer sampleId, String analyst, HttpServletRequest request) {
+        Result result = new Result();
+        Map<String, Map<String, Object>> resultMap = new HashMap<>();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //获取自建台站缓存信息
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        //判断sampleId是否为空
+        if (Objects.isNull(sampleId)){
+            result.error500("Please select a piece of data");
+            return result;
+        }
+        //查询分析id,相关的分析结果
+        Integer analysisID = null;
+        if (dbName.equalsIgnoreCase("auto")){
+            dbName = "RNAUTO";
+            analysisID = spectrumAnalysisMapper.getAnalysisID(dbName, sampleId, "RNAUTO");
+        } else if (dbName.equalsIgnoreCase("man")){
+            dbName = "RNMAN";
+            analysisID = spectrumAnalysisMapper.getAnalysisID(dbName, sampleId, analyst);
+        }
+        try {
+            if (Objects.nonNull(analysisID)) {
+                //查询数据库文件信息
+                SpectrumFileRecord dbSpectrumFilePath = spectrumAnalysisMapper.getDBSpectrumFilePath(dbName, sampleId, analysisID);
+                //判断数据库分析结果基础信息是否为空
+                if (Objects.nonNull(dbSpectrumFilePath)) {
+                    //获取sample相关信息
+                    GardsSampleData sample = null;
+                    String sampleFileName = "";
+                    if (StringUtils.isNotBlank(dbSpectrumFilePath.getSampleFilePath())) {
+                        sample = spectrumAnalysisMapper.findSampleByFilePath(dbSpectrumFilePath.getSampleFilePath());
+                        sampleFileName = dbSpectrumFilePath.getSampleFilePath().substring(dbSpectrumFilePath.getSampleFilePath().lastIndexOf(StringPool.SLASH) + 1);
+                    }
+                    //获取det相关信息
+                    GardsSampleData detBg = null;
+                    String detFileName = "";
+                    if (StringUtils.isNotBlank(dbSpectrumFilePath.getDetBgFilePath())) {
+                        detBg = spectrumAnalysisMapper.findSampleByFilePath(dbSpectrumFilePath.getDetBgFilePath());
+                        detFileName = dbSpectrumFilePath.getDetBgFilePath().substring(dbSpectrumFilePath.getDetBgFilePath().lastIndexOf(StringPool.SLASH)+1);
+                    }
+                    //从缓存中获取公用变量的数据
+                    SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + "-" + userName);
+                    if (Objects.isNull(selfStationData)) {
+                        //初始化自建台站数据对象
+                        selfStationData = new SelfStationData();
+                        //判断sample文件名是否为空
+                        if (Objects.nonNull(sample)) {
+                            //拼接sample文件路径
+                            String sampleFilePath = ftpUtil.getFtpRootPath() + spectrumPathProperties.getSaveFilePath() + StringPool.SLASH + dbSpectrumFilePath.getSampleFilePath();
+                            //返回结果map
+                            Map<String, Object> map = new HashMap<>();
+                            //获取sample分析后的对象
+                            EnergySpectrumStruct struct = selfStationUtil.getSourceData(sampleFilePath, "sample", selfStationData);
+                            if (Objects.nonNull(struct)) {
+                                selfStationData.setSampleStruct(struct);
+                                selfStationData.setSampleTmpPath(sampleFilePath);
+                                selfStationUtil.loadFile(selfStationData, sample.getSampleId(), sample.getStatus(), "sample", map);
+                                resultMap.put("sample", map);
+                            }
+                        }
+                        //判断det文件名是否为空
+                        if (Objects.nonNull(detBg)) {
+                            //拼接det文件路径
+                            String detFilePath = ftpUtil.getFtpRootPath() + spectrumPathProperties.getSaveFilePath() + StringPool.SLASH + dbSpectrumFilePath.getDetBgFilePath();
+                            //返回结果map
+                            Map<String, Object> map = new HashMap<>();
+                            //获取sample分析后的对象
+                            EnergySpectrumStruct struct = selfStationUtil.getSourceData(detFilePath, "det", selfStationData);
+                            if (Objects.nonNull(struct)) {
+                                selfStationData.setDetStruct(struct);
+                                selfStationData.setDetTmpPath(detFilePath);
+                                selfStationUtil.loadFile(selfStationData, detBg.getSampleId(), detBg.getStatus(), "det", map);
+                                resultMap.put("det", map);
+                            }
+                        }
+                    } else {
+                        if (Objects.nonNull(sample)) {
+                            //返回结果map
+                            Map<String, Object> map = new HashMap<>();
+                            selfStationUtil.loadFile(selfStationData, sample.getSampleId(), sample.getStatus(), "sample", map);
+                            resultMap.put("sample", map);
+                        }
+                        if (Objects.nonNull(detBg)) {
+                            //返回结果map
+                            Map<String, Object> map = new HashMap<>();
+                            selfStationUtil.loadFile(selfStationData, detBg.getSampleId(), detBg.getStatus(), "det", map);
+                            resultMap.put("det", map);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+
+        }
+
+        return result;
+    }
+
+    @Override
+    public Result loadSelfStationByFile(String sampleFileName, String detFileName, HttpServletRequest request) {
+        Result result = new Result();
+        Map<String, Map<String, Object>> resultMap = new HashMap<>();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //解析文件
+        //上传文件路径
+        String path = ftpUtil.getFtpRootPath() + spectrumPathProperties.getUploadPath() + StringPool.SLASH + userName;
+        //获取自建台站缓存信息
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + StringPool.DASH + userName);
+        //判断缓存是否为空
+        if (Objects.isNull(selfStationData)) {
+            //初始化自建台站数据对象
+            selfStationData = new SelfStationData();
+            //判断sample文件名是否为空
+            if (StringUtils.isNotBlank(sampleFileName)) {
+                //拼接sample文件路径
+                String sampleFilePath = path + StringPool.SLASH + sampleFileName;
+                //返回结果map
+                Map<String, Object> map = new HashMap<>();
+                //获取sample分析后的对象
+                EnergySpectrumStruct struct = selfStationUtil.getSourceData(sampleFilePath, "sample", selfStationData);
+                if (Objects.nonNull(struct)) {
+                    selfStationData.setSampleStruct(struct);
+                    selfStationData.setSampleTmpPath(sampleFilePath);
+                    selfStationUtil.loadFile(selfStationData, null, null, "sample", map);
+                    resultMap.put("sample", map);
+                }
+            }
+            //判断det文件名是否为空
+            if (StringUtils.isNotBlank(detFileName)) {
+                //拼接det文件路径
+                String detFilePath = path + StringPool.SLASH + detFileName;
+                //返回结果map
+                Map<String, Object> map = new HashMap<>();
+                //获取sample分析后的对象
+                EnergySpectrumStruct struct = selfStationUtil.getSourceData(detFilePath, "det", selfStationData);
+                if (Objects.nonNull(struct)) {
+                    selfStationData.setDetStruct(struct);
+                    selfStationData.setDetTmpPath(detFilePath);
+                    selfStationUtil.loadFile(selfStationData, null, null, "det", map);
+                    resultMap.put("det", map);
+                }
+            }
+        } else {
+            if (StringUtils.isNotBlank(sampleFileName)) {
+                //返回结果map
+                Map<String, Object> map = new HashMap<>();
+                selfStationUtil.loadFile(selfStationData, null, null, "sample", map);
+                resultMap.put("sample", map);
+            }
+            if (StringUtils.isNotBlank(detFileName)) {
+                //返回结果map
+                Map<String, Object> map = new HashMap<>();
+                selfStationUtil.loadFile(selfStationData, null, null, "det", map);
+                resultMap.put("det", map);
+            }
+        }
+        //将自建台站的数据封装到缓存对象中
+        selfCache.put(sampleFileName + StringPool.DASH + userName, selfStationData);
+        //将缓存对象存入到缓存中
+        selfStationCache.setSelfCache(selfCache);
+        //将返回内容存入返回对象中
+        result.setSuccess(true);
+        result.setResult(resultMap);
+        return result;
+    }
+
+    @Override
+    public void deleteSelfStationCache(String sampleFileName, HttpServletRequest request) {
+        String userName = JwtUtil.getUserNameByToken(request);
+        String key = sampleFileName + StrUtil.DASHED + userName;
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(key);
+        if (StringUtils.isNotBlank(selfStationData.getSampleTmpPath())) {
+            File file = new File(selfStationData.getSampleTmpPath());
+            if (Objects.nonNull(file)) {
+                file.delete();
+            }
+        }
+        if (StringUtils.isNotBlank(selfStationData.getDetTmpPath())) {
+            File file = new File(selfStationData.getDetTmpPath());
+            if (Objects.nonNull(file)) {
+                file.delete();
+            }
+        }
+        // 删除指定key的Cache
+        selfStationCache.deleteSelfCache(key);
+    }
+
+    @Override
+    public Result updateROI(Integer startChannel, Integer endChannel, Integer ROINum, String sampleFileName, HttpServletRequest request) {
+        Result result = new Result();
+        Map<String, Object> map = new HashMap<>();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取自建台站缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        //获取缓存的当前谱对应的数据
+        SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Load basic file information first!");
+            return result;
+        }
+        EnergySpectrumStruct struct = selfStationData.getSampleStruct();
+        Map<String, Object> resultMap = selfStationUtil.statisticsROIList(startChannel, endChannel, struct.b_channels, struct.g_channels, struct.h_counts);
+        if ( CollectionUtils.isNotEmpty(resultMap) ) {
+            Integer startChannelValue = (Integer) resultMap.get("startChannel");
+            Integer endChannelValue = (Integer) resultMap.get("endChannel");
+            List<SeriseData> seriseDataList = (List<SeriseData>) resultMap.get("dataList");
+            if (1 == ROINum) {
+                map.put("ROIOneList", seriseDataList);
+                map.put("ROIOneStart", startChannelValue);
+                map.put("ROIOneStop", endChannelValue);
+            } else if (2 == ROINum) {
+                map.put("ROITwoList", seriseDataList);
+                map.put("ROITwoStart", startChannelValue);
+                map.put("ROITwoStop", endChannelValue);
+            } else if (3 == ROINum) {
+                map.put("ROIThreeList", seriseDataList);
+                map.put("ROIThreeStart", startChannelValue);
+                map.put("ROIThreeStop", endChannelValue);
+            } else if (4 == ROINum) {
+                map.put("ROIFourList", seriseDataList);
+                map.put("ROIFourStart", startChannelValue);
+                map.put("ROIFourStop", endChannelValue);
+            }
+        }
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    @Override
+    public Result energyCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        //获取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isBlank(currentText)) {
+            currentText = selfStationData.getSampleVueData().getUsedEner();
+        }
+        List<String> dataSourceList = selfStationData.getSampleVueData().getMapEnerKD().keySet().stream().collect(Collectors.toList());
+        map.put("list_dataSource", dataSourceList);
+        if (StringUtils.isNotBlank(currentText)) {
+            map.put("currentText", currentText);
+            List<Double> m_vCurCentroid = selfStationData.getSampleVueData().getMapEnerKD().get(currentText).getCentroid_channel();
+            List<Double> m_vCurEnergy = selfStationData.getSampleVueData().getMapEnerKD().get(currentText).getG_energy();
+            List<Double> m_vCurUncert = selfStationData.getSampleVueData().getMapEnerKD().get(currentText).getUncertainty();
+            map.put("uncert", m_vCurUncert);
+            ParameterInfo m_curParam = selfStationData.getSampleVueData().getMapEnerPara().get(currentText);
+            if (Objects.isNull(m_curParam)) {
+                m_curParam = new ParameterInfo();
+            }
+            map.put("param", m_curParam);
+            int num = m_vCurEnergy.size();
+            if (num < 1) {
+                return result;
+            }
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurCentroid, m_curParam.getP()).counts;
+            List<EnergyData> energyDataList = new LinkedList<>();
+            for (int i = 0; i < num; ++i) {
+                EnergyData energyData = new EnergyData();
+                double delta = (m_vCurEnergy.get(i) - vFit.get(i)) / m_vCurEnergy.get(i) * 100;
+                energyData.setChannel(String.valueOf(m_vCurCentroid.get(i)));
+                energyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                energyData.setFit(String.format("%.3f", vFit.get(i)));
+                energyData.setDelta(String.format("%.3f", delta));
+                energyDataList.add(energyData);
+            }
+            map.put("table", energyDataList);
+            String equation = selfStationUtil.UpdateEquationEnergy(m_curParam);
+            map.put("equation", equation);
+            selfStationUtil.UpdateChartEnergy(m_vCurEnergy, m_curParam, m_vCurCentroid, selfStationData, width, map);
+        }
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    @Override
+    public Result changeDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer sampleId, String fileName, Double width, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        //加载缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfCache)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        DataChangeEnergy(m_vCurCentroid, m_vCurEnergy, m_vCurUncert, m_curParam, selfStationData, width, map);
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    private void DataChangeEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, SelfStationData selfStationData, Double width, Map<String, Object> map) {
+        if (m_vCurEnergy.size() < 1) {
+            return;
+        } else if (m_vCurEnergy.size() == 1) {
+            for (int j = m_curParam.getP().size(); j < 2; j++) {
+                m_curParam.getP().add(2.0);
+            }
+            m_curParam.getP().set(1, (m_vCurEnergy.get(0) / m_vCurCentroid.get(0)));
+            for (int j = m_curParam.getPerr().size(); j < 2; j++) {
+                m_curParam.getPerr().add(0.0);
+            }
+        } else {
+            m_curParam.setP(CalValuesHandler.calFitPara("Cal_Energy", 2, m_vCurCentroid, m_vCurEnergy, m_vCurUncert));
+        }
+        map.put("uncert", m_vCurUncert);
+        map.put("param", m_curParam);
+        List<EnergyData> energyDataList = new LinkedList<>();
+        if (CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurCentroid, m_curParam.getP()).counts;
+            for (int j = 0; j < m_vCurEnergy.size(); j++) {
+                EnergyData energyData = new EnergyData();
+                double delta = (m_vCurEnergy.get(j) - vFit.get(j)) / m_vCurEnergy.get(j) * 100;
+                energyData.setChannel(String.valueOf(m_vCurCentroid.get(j)));
+                energyData.setEnergy(String.valueOf(m_vCurEnergy.get(j)));
+                energyData.setFit(String.format("%.3f", vFit.get(j)));
+                energyData.setDelta(String.format("%.3f", delta));
+                energyDataList.add(energyData);
+            }
+        } else {
+            for (int j = 0; j < m_vCurEnergy.size(); j++) {
+                EnergyData energyData = new EnergyData();
+                energyData.setChannel(String.valueOf(m_vCurCentroid.get(j)));
+                energyData.setEnergy(String.valueOf(m_vCurEnergy.get(j)));
+                energyData.setFit("");
+                energyData.setDelta("");
+                energyDataList.add(energyData);
+            }
+            String warning = "Fit failed. Maybe:\nPolynomial isn't suitable for the datas.";
+        }
+        map.put("table", energyDataList);
+        String equation = selfStationUtil.UpdateEquationEnergy(m_curParam);
+        map.put("equation", equation);
+        selfStationUtil.UpdateChartEnergy(m_vCurEnergy, m_curParam, m_vCurCentroid, selfStationData, width, map);
+    }
+
+    @Override
+    public Result applyDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (!curCalName.contains("Input")) {
+            List<String> list_cal = selfStationData.getSampleVueData().getMapEnerKD().keySet().stream().collect(Collectors.toList());
+            curCalName = "Input " + (list_cal.stream().filter(item -> item.contains("Input")).collect(Collectors.toList()).size() + 1);
+            list_cal.add(curCalName);
+            result.setSuccess(true);
+            result.setResult(list_cal);
+        }
+        GEnergyBlock gEnergyBlock = new GEnergyBlock();
+        gEnergyBlock.setCentroid_channel(m_vCurCentroid);
+        gEnergyBlock.setG_energy(m_vCurEnergy);
+        gEnergyBlock.setUncertainty(m_vCurUncert);
+        gEnergyBlock.setRecord_count(m_vCurCentroid.size());
+        selfStationData.getSampleVueData().getMapEnerKD().put(curCalName, gEnergyBlock);
+        selfStationData.getSampleVueData().getMapEnerPara().put(curCalName, m_curParam);
+        return result;
+    }
+
+    @Override
+    public void saveDataEnergy(List<Double> m_vCurCentroid, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, HttpServletResponse response) {
+        StringBuffer strBuffer = new StringBuffer();
+        strBuffer.append("#g_Energy").append("\n");
+        for (int i = 0; i < m_vCurCentroid.size(); i++) {
+            strBuffer.append(m_vCurEnergy.get(i)).append("\t\t").append(m_vCurCentroid.get(i)).append("\t\t").append(m_vCurUncert.get(i)).append("\n");
+        }
+        OutputStream fos = null;
+        try {
+            // 设置响应类型
+            response.setContentType("application/octet-stream");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            // 解决中文不能生成文件
+            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode("EnergyCalibration.Ent", "UTF-8"));
+            fos = response.getOutputStream();
+            fos.write(strBuffer.toString().getBytes());
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                fos.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    public Result callDataEnergy(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //加载缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first");
+            return result;
+        }
+        if (Objects.nonNull(file)) {
+            String fileName = file.getOriginalFilename();
+            // 从最后一个。切割文件名称  获取文件名称后缀
+            String fileSuffix = fileName.substring(fileName.lastIndexOf(StringPool.DOT));
+            if (fileSuffix.equalsIgnoreCase(".ent")) {
+                Map<String, Object> map = new HashMap<>();
+                List<Double> m_vCurCentroid = new LinkedList<>();
+                List<Double> m_vCurEnergy = new LinkedList<>();
+                List<Double> m_vCurUncert = new LinkedList<>();
+                File tmpFile = null;
+                InputStream inputStream = null;
+                try {
+                    // 创建临时文件
+                    tmpFile = File.createTempFile("betaGamma", null);
+                    inputStream = file.getInputStream();
+                    // 复制上传文件的输入流到临时文件
+                    FileUtils.copyInputStreamToFile(inputStream, tmpFile);
+                    // 读取文件所有行
+                    List<String> readLines = FileUtils.readLines(tmpFile, "UTF-8");
+                    // 遍历文件行数据
+                    for (int i = 0; i < readLines.size(); i++) {
+                        String line = readLines.get(i);
+                        if (line.contains("#g_Energy") || line.contains("#Energy")) {
+                            for (int j = i + 1; j < readLines.size(); j++) {
+                                String content = readLines.get(j);
+                                if (!content.contains("#")) {
+                                    List<String> values = Arrays.asList(content.split("\t\t"));
+                                    if (Double.valueOf(values.get(1)) > 0) {
+                                        m_vCurEnergy.add(Double.valueOf(values.get(0)));
+                                        m_vCurCentroid.add(Double.valueOf(values.get(1)));
+                                        m_vCurUncert.add(Double.valueOf(values.get(2)));
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    map.put("uncert", m_vCurUncert);
+                    ParameterInfo m_curParam = new ParameterInfo();
+                    if (StringUtils.isNotBlank(currentText)) {
+                        m_curParam = selfStationData.getSampleVueData().getMapEnerPara().get(currentText);
+                    }
+                    map.put("param", m_curParam);
+                    int num = m_vCurEnergy.size();
+                    if (num < 1) {
+                        return result;
+                    }
+                    List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurCentroid, m_curParam.getP()).counts;
+                    List<EnergyData> energyDataList = new LinkedList<>();
+                    for (int i = 0; i < num; ++i) {
+                        EnergyData energyData = new EnergyData();
+                        double delta = (m_vCurEnergy.get(i) - vFit.get(i)) / m_vCurEnergy.get(i) * 100;
+                        energyData.setChannel(String.valueOf(m_vCurCentroid.get(i)));
+                        energyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                        energyData.setFit(String.format("%.3f", vFit.get(i)));
+                        energyData.setDelta(String.format("%.3f", delta));
+                        energyDataList.add(energyData);
+                    }
+                    map.put("table", energyDataList);
+                    String equation = selfStationUtil.UpdateEquationEnergy(m_curParam);
+                    map.put("equation", equation);
+                    selfStationUtil.UpdateChartEnergy(m_vCurEnergy, m_curParam, m_vCurCentroid, selfStationData, width, map);
+                    result.setSuccess(true);
+                    result.setResult(map);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                } finally {
+                    try {
+                        if (Objects.nonNull(inputStream)) {
+                            inputStream.close();
+                        }
+                        if (Objects.nonNull(tmpFile)) {
+                            tmpFile.delete();
+                        }
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Result setCurrentEnergy(String fileName, String currentName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //加载缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isNotBlank(currentName)) {
+            selfStationData.getSampleVueData().setNewEner(currentName);
+        }
+        selfCache.put(fileName, selfStationData);
+        selfStationCache.setSelfCache(selfCache);
+        result.success("Modified successfully");
+        return result;
+    }
+
+    @Override
+    public Result resolutionCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isBlank(currentText)) {
+            currentText = selfStationData.getSampleVueData().getUsedReso();
+        }
+        List<String> dataSourceList = selfStationData.getSampleVueData().getMapResoKD().keySet().stream().collect(Collectors.toList());
+        map.put("list_dataSource", dataSourceList);
+        if (StringUtils.isNotBlank(currentText)) {
+            map.put("currentText", currentText);
+            List<Double> m_vCurReso = selfStationData.getSampleVueData().getMapResoKD().get(currentText).getFWHM();
+            List<Double> m_vCurEnergy = selfStationData.getSampleVueData().getMapResoKD().get(currentText).getG_energy();
+            List<Double> m_vCurUncert = selfStationData.getSampleVueData().getMapResoKD().get(currentText).getUncertainty();
+            map.put("uncert", m_vCurUncert);
+            ParameterInfo m_curParam = selfStationData.getSampleVueData().getMapResoPara().get(currentText);
+            if (Objects.isNull(m_curParam)) {
+                m_curParam = new ParameterInfo();
+            }
+            map.put("param", m_curParam);
+            int num = m_vCurEnergy.size();
+            if (num < 1) {
+                return result;
+            }
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+            List<ResolutionData> resolutionDataList = new LinkedList<>();
+            for (int i = 0; i < num; ++i) {
+                ResolutionData resolutionData = new ResolutionData();
+                double delta = (m_vCurReso.get(i) - vFit.get(i)) / m_vCurReso.get(i) * 100;
+                resolutionData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                resolutionData.setFwhm(String.valueOf(m_vCurReso.get(i)));
+                resolutionData.setFit(String.format("%.3f", vFit.get(i)));
+                resolutionData.setDelta(String.format("%.3f", delta));
+                resolutionDataList.add(resolutionData);
+            }
+            map.put("table", resolutionDataList);
+            String equation = selfStationUtil.UpdateEquationResolution(m_curParam);
+            map.put("equation", equation);
+            selfStationUtil.UpdateChartResolution(m_vCurEnergy, m_curParam, m_vCurReso, selfStationData, width, map);
+        }
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    @Override
+    public Result changeDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer sampleId, String fileName, Double width, HttpServletRequest request) {
+        Result result = new Result();
+        //读取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        DataChangeResolution(m_vCurReso, m_vCurEnergy, m_vCurUncert, m_curParam, selfStationData, width, map);
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    public void DataChangeResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, SelfStationData selfStationData, Double width, Map<String, Object> map) {
+        m_curParam.setP(CalValuesHandler.calFitPara("Cal_Resolution", 4, m_vCurEnergy, m_vCurReso, m_vCurUncert));
+        map.put("uncert", m_vCurUncert);
+        map.put("param", m_curParam);
+
+        List<ResolutionData> resolutionDataList = new LinkedList<>();
+        if (CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+            for (int i = 0; i < m_vCurEnergy.size(); ++i) {
+                ResolutionData resolutionData = new ResolutionData();
+                double delta = (m_vCurReso.get(i) - vFit.get(i)) / m_vCurReso.get(i) * 100;
+                resolutionData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                resolutionData.setFwhm(String.valueOf(m_vCurReso.get(i)));
+                resolutionData.setFit(String.format("%.3f", vFit.get(i)));
+                resolutionData.setDelta(String.format("%.3f", delta));
+                resolutionDataList.add(resolutionData);
+            }
+        } else {
+            for (int i = 0; i < m_vCurEnergy.size(); ++i) {
+                ResolutionData resolutionData = new ResolutionData();
+                resolutionData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                resolutionData.setFwhm(String.valueOf(m_vCurReso.get(i)));
+                resolutionData.setFit("");
+                resolutionData.setDelta("");
+                resolutionDataList.add(resolutionData);
+            }
+            String Warning = "Fit failed. Maybe\nSquare root of polynomial isn't suitable for the datas.";
+        }
+        map.put("table", resolutionDataList);
+        String equation = selfStationUtil.UpdateEquationResolution(m_curParam);
+        map.put("equation", equation);
+        selfStationUtil.UpdateChartResolution(m_vCurEnergy, m_curParam, m_vCurReso, selfStationData, width, map);
+    }
+
+    @Override
+    public Result applyDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (!curCalName.contains("Input")) {
+            List<String> list_cal = selfStationData.getSampleVueData().getMapResoKD().keySet().stream().collect(Collectors.toList());
+            curCalName = "Input " + (list_cal.stream().filter(item -> item.contains("Input")).collect(Collectors.toList()).size() + 1);
+            list_cal.add(curCalName);
+            result.setSuccess(true);
+            result.setResult(list_cal);
+        }
+        GResolutionBlock gResolutionBlock = new GResolutionBlock();
+        gResolutionBlock.setFWHM(m_vCurReso);
+        gResolutionBlock.setG_energy(m_vCurEnergy);
+        gResolutionBlock.setUncertainty(m_vCurUncert);
+        gResolutionBlock.setRecord_count(m_vCurEnergy.size());
+        selfStationData.getSampleVueData().getMapResoKD().put(curCalName, gResolutionBlock);
+        selfStationData.getSampleVueData().getMapResoPara().put(curCalName, m_curParam);
+        return result;
+    }
+
+    @Override
+    public void saveDataResolution(List<Double> m_vCurReso, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, HttpServletResponse response) {
+        StringBuffer strBuffer = new StringBuffer();
+        strBuffer.append("#g_Resolution").append("\n");
+        for (int i = 0; i < m_vCurReso.size(); i++) {
+            strBuffer.append(m_vCurEnergy.get(i)).append("\t\t").append(m_vCurReso.get(i)).append("\t\t").append(m_vCurUncert.get(i)).append("\n");
+        }
+        OutputStream fos = null;
+        try {
+            // 设置响应类型
+            response.setContentType("application/octet-stream");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            // 解决中文不能生成文件
+            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode("ResolutionCalibration.Ent", "UTF-8"));
+            fos = response.getOutputStream();
+            fos.write(strBuffer.toString().getBytes());
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                fos.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    public Result callDataResolution(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first");
+            return result;
+        }
+        if (Objects.nonNull(file)) {
+            String fileName = file.getOriginalFilename();
+            // 从最后一个。切割文件名称  获取文件名称后缀
+            String fileSuffix = fileName.substring(fileName.lastIndexOf(StringPool.DOT));
+            if (fileSuffix.equalsIgnoreCase(".ent")) {
+                Map<String, Object> map = new HashMap<>();
+                List<Double> m_vCurReso = new LinkedList<>();
+                List<Double> m_vCurEnergy = new LinkedList<>();
+                List<Double> m_vCurUncert = new LinkedList<>();
+                InputStream inputStream = null;
+                File tmpFile = null;
+                try {
+                    // 创建临时文件
+                    tmpFile = File.createTempFile("betaGamma", null);
+                    inputStream = file.getInputStream();
+                    // 复制上传文件的输入流到临时文件
+                    FileUtils.copyInputStreamToFile(inputStream, tmpFile);
+                    // 读取文件所有行
+                    List<String> readLines = FileUtils.readLines(tmpFile, "UTF-8");
+                    // 遍历文件行数据
+                    for (int i = 0; i < readLines.size(); i++) {
+                        String line = readLines.get(i);
+                        if (line.contains("#g_Resolution") || line.contains("#Resolution")) {
+                            for (int j = i + 1; j < readLines.size(); j++) {
+                                String content = readLines.get(j);
+                                if (!content.contains("#")) {
+                                    List<String> values = Arrays.asList(content.split("\t\t"));
+                                    if (Double.valueOf(values.get(0)) > 0) {
+                                        m_vCurEnergy.add(Double.valueOf(values.get(0)));
+                                        m_vCurReso.add(Double.valueOf(values.get(1)));
+                                        m_vCurUncert.add(Double.valueOf(values.get(2)));
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    map.put("uncert", m_vCurUncert);
+                    ParameterInfo m_curParam = new ParameterInfo();
+                    if (StringUtils.isNotBlank(currentText)) {
+                        m_curParam = selfStationData.getSampleVueData().getMapResoPara().get(currentText);
+                    }
+                    map.put("param", m_curParam);
+                    int num = m_vCurEnergy.size();
+                    if (num < 1) {
+                        return result;
+                    }
+                    List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+                    List<ResolutionData> resolutionDataList = new LinkedList<>();
+                    for (int i = 0; i < num; ++i) {
+                        ResolutionData resolutionData = new ResolutionData();
+                        double delta = (m_vCurReso.get(i) - vFit.get(i)) / m_vCurReso.get(i) * 100;
+                        resolutionData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                        resolutionData.setFwhm(String.valueOf(m_vCurReso.get(i)));
+                        resolutionData.setFit(String.format("%.3f", vFit.get(i)));
+                        resolutionData.setDelta(String.format("%.3f", delta));
+                        resolutionDataList.add(resolutionData);
+                    }
+                    map.put("table", resolutionDataList);
+                    String equation = selfStationUtil.UpdateEquationResolution(m_curParam);
+                    map.put("equation", equation);
+                    selfStationUtil.UpdateChartResolution(m_vCurEnergy, m_curParam, m_vCurReso, selfStationData, width, map);
+                    result.setSuccess(true);
+                    result.setResult(map);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                } finally {
+                    try {
+                        if (Objects.nonNull(inputStream)) {
+                            inputStream.close();
+                        }
+                        if (Objects.nonNull(tmpFile)) {
+                            tmpFile.delete();
+                        }
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Result setCurrentResolution(String fileName, String currentName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isNotBlank(currentName)) {
+            selfStationData.getSampleVueData().setNewReso(currentName);
+        }
+        selfCache.put(fileName, selfStationData);
+        selfStationCache.setSelfCache(selfCache);
+        result.success("Modified successfully");
+        return result;
+    }
+
+    @Override
+    public Result EfficiencyCalibration(String fileName, String currentText, Double width, HttpServletRequest request) {
+        Result result = new Result();
+        //读取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        List<String> m_vFuncName = new LinkedList<>();
+        m_vFuncName.add("Interpolation");         // 1
+        m_vFuncName.add("HT Efficiency");         // 5
+        m_vFuncName.add("Log Polynomial");        // 6
+        m_vFuncName.add("Invlog Polynomial");     // 8
+        m_vFuncName.add("HAE Efficiency(1-3)");   // 93
+        m_vFuncName.add("HAE Efficiency(1-2)");   // 94
+        m_vFuncName.add("HAE Efficiency(1-2-3)"); // 95
+        map.put("function", m_vFuncName);
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isBlank(currentText)) {
+            currentText = selfStationData.getSampleVueData().getUsedEffi();
+        }
+        List<String> dataSourceList = selfStationData.getSampleVueData().getMapEffiKD().keySet().stream().collect(Collectors.toList());
+        map.put("list_dataSource", dataSourceList);
+        if (StringUtils.isNotBlank(currentText)) {
+            map.put("currentText", currentText);
+            List<Double> m_vCurEffi = selfStationData.getSampleVueData().getMapEffiKD().get(currentText).getEfficiency();
+            List<Double> m_vCurEnergy = selfStationData.getSampleVueData().getMapEffiKD().get(currentText).getG_energy();
+            List<Double> m_vCurUncert = selfStationData.getSampleVueData().getMapEffiKD().get(currentText).getUncertainty();
+            map.put("uncert", m_vCurUncert);
+            ParameterInfo m_curParam = selfStationData.getSampleVueData().getMapEffiPara().get(currentText);
+            if (Objects.isNull(m_curParam)) {
+                m_curParam = new ParameterInfo();
+            }
+            map.put("param", m_curParam);
+            int num = m_vCurEnergy.size();
+            if (num < 1) {
+                return result;
+            }
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+            List<EfficiencyData> efficiencyDataList = new LinkedList<>();
+            for (int i = 0; i < num; ++i) {
+                double delta = (m_vCurEffi.get(i) - vFit.get(i)) / m_vCurEffi.get(i) * 100;
+                EfficiencyData efficiencyData = new EfficiencyData();
+                efficiencyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                efficiencyData.setEfficiency(String.valueOf(m_vCurEffi.get(i)));
+                efficiencyData.setFit(String.format("%.3f", vFit.get(i)));
+                efficiencyData.setDelta(String.format("%.3f", delta));
+                efficiencyDataList.add(efficiencyData);
+            }
+            map.put("table", efficiencyDataList);
+            String equation = selfStationUtil.UpdateEquationEfficiency(m_vCurEnergy, m_curParam, 0, null);
+            map.put("equation", equation);
+            selfStationUtil.UpdateChartEfficiency(m_vCurEnergy, m_curParam, m_vCurEffi, selfStationData, width, map);
+        }
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    @Override
+    public Result changeDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer funcId, Integer sampleId, String fileName, Double width, Integer curRow, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Map<String, Object> map = new HashMap<>();
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        DataChangeEfficiency(m_vCurEffi, m_vCurEnergy, m_vCurUncert, m_curParam, funcId, selfStationData, width, curRow, map);
+        result.setSuccess(true);
+        result.setResult(map);
+        return result;
+    }
+
+    public void DataChangeEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, Integer funcId, SelfStationData selfStationData, Double width, Integer curRow, Map<String, Object> map) {
+        m_curParam.setP(CalValuesHandler.calFitPara("Cal_Efficiency", funcId, m_vCurEnergy, m_vCurEffi, m_vCurUncert));
+        map.put("uncert", m_vCurUncert);
+        map.put("param", m_curParam);
+
+        List<EfficiencyData> efficiencyDataList = new LinkedList<>();
+        if (CollectionUtils.isNotEmpty(m_curParam.getP())) {
+            List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+            for (int i = 0; i < m_vCurEnergy.size(); ++i) {
+                EfficiencyData efficiencyData = new EfficiencyData();
+                double delta = (m_vCurEffi.get(i) - vFit.get(i)) / m_vCurEffi.get(i) * 100;
+                efficiencyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                efficiencyData.setEfficiency(String.valueOf(m_vCurEffi.get(i)));
+                efficiencyData.setFit(String.format("%.3f", vFit.get(i)));
+                efficiencyData.setDelta(String.format("%.3f", delta));
+                efficiencyDataList.add(efficiencyData);
+            }
+        } else {
+            for (int i = 0; i < m_vCurEnergy.size(); ++i) {
+                EfficiencyData efficiencyData = new EfficiencyData();
+                efficiencyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                efficiencyData.setEfficiency(String.valueOf(m_vCurEffi.get(i)));
+                efficiencyData.setFit("");
+                efficiencyData.setDelta("");
+                efficiencyDataList.add(efficiencyData);
+            }
+            String Warning = "Fit failed. Maybe:\n1. data's number are too little;\n2. %1 isn't suitable for the data.";
+        }
+        map.put("table", efficiencyDataList);
+        String equation = selfStationUtil.UpdateEquationEfficiency(m_vCurEnergy, m_curParam, curRow, funcId);
+        map.put("equation", equation);
+        selfStationUtil.UpdateChartEfficiency(m_vCurEnergy, m_curParam, m_vCurEffi, selfStationData, width, map);
+    }
+
+    @Override
+    public Result applyDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, ParameterInfo m_curParam, String curCalName, Integer sampleId, String fileName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> phdCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = phdCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (!curCalName.contains("Input")) {
+            List<String> list_cal = selfStationData.getSampleVueData().getMapEffiKD().keySet().stream().collect(Collectors.toList());
+            curCalName = "Input " + (list_cal.stream().filter(item -> item.contains("Input")).collect(Collectors.toList()).size() + 1);
+            list_cal.add(curCalName);
+            result.setSuccess(true);
+            result.setResult(list_cal);
+        }
+        GEfficiencyBlock gEfficiencyBlock = new GEfficiencyBlock();
+        gEfficiencyBlock.setEfficiency(m_vCurEffi);
+        gEfficiencyBlock.setG_energy(m_vCurEnergy);
+        gEfficiencyBlock.setUncertainty(m_vCurUncert);
+        gEfficiencyBlock.setRecord_count(m_vCurEnergy.size());
+        selfStationData.getSampleVueData().getMapEffiKD().put(curCalName, gEfficiencyBlock);
+        selfStationData.getSampleVueData().getMapEffiPara().put(curCalName, m_curParam);
+        return result;
+    }
+
+    @Override
+    public void saveDataEfficiency(List<Double> m_vCurEffi, List<Double> m_vCurEnergy, List<Double> m_vCurUncert, Integer funId, HttpServletResponse response) {
+        StringBuffer strBuffer = new StringBuffer();
+        strBuffer.append("#g_Efficiency").append("\n");
+        for (int i = 0; i < m_vCurEffi.size(); i++) {
+            strBuffer.append(m_vCurEnergy.get(i)).append("\t\t").append(m_vCurEffi.get(i)).append("\t\t").append(m_vCurUncert.get(i)).append("\n");
+        }
+        strBuffer.append("FitType = ").append(funId);
+        OutputStream fos = null;
+        try {
+            // 设置响应类型
+            response.setContentType("application/octet-stream");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            // 解决中文不能生成文件
+            response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode("EfficiencyCalibration.Eft", "UTF-8"));
+            fos = response.getOutputStream();
+            fos.write(strBuffer.toString().getBytes());
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                fos.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    public Result callDataEfficiency(MultipartFile file, String sampleFileName, Double width, String currentText, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        //读取缓存
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(sampleFileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first");
+            return result;
+        }
+        if (Objects.nonNull(file)) {
+            String fileName = file.getOriginalFilename();
+            // 从最后一个。切割文件名称  获取文件名称后缀
+            String fileSuffix = fileName.substring(fileName.lastIndexOf(StringPool.DOT));
+            if (fileSuffix.equalsIgnoreCase(".eft") || fileSuffix.equalsIgnoreCase(".ent")) {
+                Map<String, Object> map = new HashMap<>();
+                List<Double> m_vCurEffi = new LinkedList<>();
+                List<Double> m_vCurEnergy = new LinkedList<>();
+                List<Double> m_vCurUncert = new LinkedList<>();
+                Double m_nFunId = 1.0;
+                File tmpFile = null;
+                InputStream inputStream = null;
+                try {
+                    // 创建临时文件
+                    tmpFile = File.createTempFile("betaGamma", null);
+                    inputStream = file.getInputStream();
+                    // 复制上传文件的输入流到临时文件
+                    FileUtils.copyInputStreamToFile(inputStream, tmpFile);
+                    // 读取文件所有行
+                    List<String> readLines = FileUtils.readLines(tmpFile, "UTF-8");
+                    // 遍历文件行数据
+                    for (int i = 0; i < readLines.size(); i++) {
+                        String line = readLines.get(i);
+                        if (line.contains("#g_Efficiency") || line.contains("#Efficiency")) {
+                            for (int j = i + 1; j < readLines.size(); j++) {
+                                String content = readLines.get(j);
+                                if (!content.contains("#") && !content.contains("FitType")) {
+                                    List<String> values = Arrays.asList(content.split("\t\t"));
+                                    if (Double.valueOf(values.get(0)) > 0) {
+                                        m_vCurEnergy.add(Double.valueOf(values.get(0)));
+                                        m_vCurEffi.add(Double.valueOf(values.get(1)));
+                                        m_vCurUncert.add(Double.valueOf(values.get(2)));
+                                    }
+                                }
+                                if (content.contains("FitType")) {
+                                    List<String> values = Arrays.asList(content.split("="));
+                                    if (values.size() == 2) {
+                                        m_nFunId = Double.valueOf(values.get(1).trim());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    map.put("uncert", m_vCurUncert);
+                    ParameterInfo m_curParam = new ParameterInfo();
+                    if (StringUtils.isNotBlank(currentText)) {
+                        m_curParam = selfStationData.getSampleVueData().getMapEffiPara().get(currentText);
+                    }
+                    if (m_curParam.getP().size() > 0) {
+                        m_curParam.getP().set(0, m_nFunId);
+                    } else {
+                        m_curParam.getP().add(m_nFunId);
+                    }
+                    map.put("param", m_curParam);
+                    int num = m_vCurEnergy.size();
+                    if (num < 1) {
+                        return result;
+                    }
+                    List<Double> vFit = CalValuesHandler.calFcnEval(m_vCurEnergy, m_curParam.getP()).counts;
+                    List<EfficiencyData> efficiencyDataList = new LinkedList<>();
+                    for (int i = 0; i < num; ++i) {
+                        double delta = (m_vCurEffi.get(i) - vFit.get(i)) / m_vCurEffi.get(i) * 100;
+                        EfficiencyData efficiencyData = new EfficiencyData();
+                        efficiencyData.setEnergy(String.valueOf(m_vCurEnergy.get(i)));
+                        efficiencyData.setEfficiency(String.valueOf(m_vCurEffi.get(i)));
+                        efficiencyData.setFit(String.format("%.3f", vFit.get(i)));
+                        efficiencyData.setDelta(String.format("%.3f", delta));
+                        efficiencyDataList.add(efficiencyData);
+                    }
+                    map.put("table", efficiencyDataList);
+                    String equation = selfStationUtil.UpdateEquationEfficiency(m_vCurEnergy, m_curParam, 0, null);
+                    map.put("equation", equation);
+                    selfStationUtil.UpdateChartEfficiency(m_vCurEnergy, m_curParam, m_vCurEffi, selfStationData, width, map);
+                    result.setSuccess(true);
+                    result.setResult(map);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                } finally {
+                    try {
+                        if (Objects.nonNull(inputStream)) {
+                            inputStream.close();
+                        }
+                        if (Objects.nonNull(tmpFile)) {
+                            tmpFile.delete();
+                        }
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public Result setCurrentEfficiency(String fileName, String currentName, HttpServletRequest request) {
+        Result result = new Result();
+        //获取用户名
+        String userName = JwtUtil.getUserNameByToken(request);
+        Cache<String, SelfStationData> selfCache = selfStationCache.getSelfCache();
+        SelfStationData selfStationData = selfCache.getIfPresent(fileName + StringPool.DASH + userName);
+        if (Objects.isNull(selfStationData)) {
+            result.error500("Please select the parse file first!");
+            return result;
+        }
+        if (StringUtils.isNotBlank(currentName)) {
+            selfStationData.getSampleVueData().setNewEffi(currentName);
+        }
+        selfCache.put(fileName, selfStationData);
+        selfStationCache.setSelfCache(selfCache);
+        result.success("Modified successfully");
+        return result;
+    }
+
+}
diff --git a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SpectrumAnalysisServiceImpl.java b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SpectrumAnalysisServiceImpl.java
index 8b997d75..4ae9e817 100644
--- a/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SpectrumAnalysisServiceImpl.java
+++ b/jeecg-module-spectrum-analysis/src/main/java/org/jeecg/modules/service/impl/SpectrumAnalysisServiceImpl.java
@@ -363,12 +363,29 @@ public class SpectrumAnalysisServiceImpl extends AbstractLogOrReport implements
                         map.put("qcFileName", qcphd);
                         map.put("qcFileStatus", qcStatus);
                         map.put("sampleSystemType", sampleSystemType);
-                    } else {
+                    } else if (sampleSystemType.equals(SystemType.GAMMA.getType()) || sampleSystemType.equals(SystemType.PARTICULATE.getType())) {
                         map.put("sampleFileName", sampleFileName);
                         map.put("gasFileName", "");
                         map.put("detFileName", "");
                         map.put("qcFileName", "");
                         map.put("sampleSystemType", sampleSystemType);
+                    } else if (sampleSystemType.equals(SystemType.SELFSTATION.getType())) {
+                        //加载并获取当前路径下所有的文件名称并进行名称格式化  仅需要格式化和sample文件同一个台站 名称格式化为最终名称
+                        List<String> fileNames = phdFileUtil.FileNameByStandardForm(filePath, sampleFileName);
+                        //匹配detFile
+                        boolean detStatus = false;
+                        String detaFileName = fileData.get("detaFileName");
+                        String detphd = phdFileUtil.GetMatchFile(detaFileName, fileNames, DataTypeAbbr.DETBKPHD.getType());
+                        if (StringUtils.isNotBlank(detphd)) {
+                            detaFileName = detphd;
+                            detStatus = true;
+                        }
+                        map.put("sampleFileName", sampleFileName);
+                        map.put("gasFileName", "");
+                        map.put("detFileName", detaFileName);
+                        map.put("detFileStatus", detStatus);
+                        map.put("qcFileName", "");
+                        map.put("sampleSystemType", sampleSystemType);
                     }
                 }
                 if (CollectionUtils.isNotEmpty(map)) {
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/GardsAlertSystemController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/GardsAlertSystemController.java
new file mode 100644
index 00000000..7140f3e7
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/GardsAlertSystemController.java
@@ -0,0 +1,44 @@
+package org.jeecg.modules.system.controller;
+
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.base.bizVo.AlertSystemVo;
+import org.jeecg.modules.base.entity.configuration.GardsAlertSystem;
+import org.jeecg.modules.system.service.IGardsAlertSystemService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+@RestController
+@RequestMapping("sys/alertSystem")
+public class GardsAlertSystemController {
+
+    @Autowired
+    private IGardsAlertSystemService alertSystemService;
+
+    @GetMapping( "list")
+    public Result<?> findPage(AlertSystemVo alertSystemVo) {
+        return alertSystemService.findPage(alertSystemVo);
+    }
+
+    @PostMapping( "saveOrUpdate")
+    public Result<?> saveOrUpdate(@RequestBody GardsAlertSystem alertSystem) {
+        return alertSystemService.saveOrUpdate1(alertSystem);
+    }
+
+    @DeleteMapping( "delete")
+    public Result<?> delete(@RequestParam("id") String id) {
+        return alertSystemService.delete(id);
+    }
+
+    @DeleteMapping( "deleteBatch")
+    public Result<?> deleteBatch(@RequestParam("ids") String ids) {
+        return alertSystemService.delete(ids);
+    }
+
+    @GetMapping("codeMap")
+    public Map<String, String> codeMap(){
+        return alertSystemService.codeMap();
+    }
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/GardsAlertSystemMapper.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/GardsAlertSystemMapper.java
new file mode 100644
index 00000000..d525f1a5
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/GardsAlertSystemMapper.java
@@ -0,0 +1,11 @@
+package org.jeecg.modules.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.jeecg.modules.base.entity.configuration.GardsAlertSystem;
+
+@Mapper
+public interface GardsAlertSystemMapper extends BaseMapper<GardsAlertSystem> {
+
+
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/IGardsAlertSystemService.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/IGardsAlertSystemService.java
new file mode 100644
index 00000000..7e1e83f4
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/IGardsAlertSystemService.java
@@ -0,0 +1,22 @@
+package org.jeecg.modules.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.base.bizVo.AlertSystemVo;
+import org.jeecg.modules.base.entity.configuration.GardsAlertSystem;
+
+import java.util.Map;
+
+public interface IGardsAlertSystemService extends IService<GardsAlertSystem> {
+
+    Result<?> findPage(AlertSystemVo alertSystemVo);
+
+    Result<?> saveOrUpdate1(GardsAlertSystem alertSystem);
+
+    Result<?> delete(String id);
+
+    Result<?> deleteBatch(String ids);
+
+    Map<String, String> codeMap();
+}
diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/GardsAlertSystemServiceImpl.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/GardsAlertSystemServiceImpl.java
new file mode 100644
index 00000000..30fc709a
--- /dev/null
+++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/GardsAlertSystemServiceImpl.java
@@ -0,0 +1,110 @@
+package org.jeecg.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.constant.DictConstant;
+import org.jeecg.common.constant.Prompt;
+import org.jeecg.common.system.vo.DictModel;
+import org.jeecg.modules.base.bizVo.AlertSystemVo;
+import org.jeecg.modules.base.entity.configuration.GardsAlertSystem;
+import org.jeecg.modules.system.mapper.GardsAlertSystemMapper;
+import org.jeecg.modules.system.service.IGardsAlertSystemService;
+import org.jeecgframework.minidao.datasource.DataSourceContextHolder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+@DS("ora")
+public class GardsAlertSystemServiceImpl extends ServiceImpl<GardsAlertSystemMapper, GardsAlertSystem> implements IGardsAlertSystemService {
+
+    @Autowired
+    private SysDictServiceImpl dictService;
+
+    @Override
+    public Result<?> findPage(AlertSystemVo alertSystemVo) {
+        Integer pageNo = alertSystemVo.getPageNo();
+        Integer pageSize = alertSystemVo.getPageSize();
+        IPage<GardsAlertSystem> page = new Page<>(pageNo, pageSize);
+        // 封装查询条件
+        String code = alertSystemVo.getCode();
+        String content = alertSystemVo.getContent();
+        LambdaQueryWrapper<GardsAlertSystem> wrapper = new LambdaQueryWrapper<>();
+        wrapper.orderByAsc(GardsAlertSystem::getCode);
+        wrapper.like(StrUtil.isNotBlank(code), GardsAlertSystem::getCode, code);
+        wrapper.like(StrUtil.isNotBlank(content), GardsAlertSystem::getContent, content);
+        page = this.page(page, wrapper);
+        // 手动切换为主数据源
+        DynamicDataSourceContextHolder.push("master");
+        List<DictModel> items = dictService.getItems(DictConstant.ALERT_SYSTEM_CODE);
+        DynamicDataSourceContextHolder.clear();
+        Map<String, String> typeMap = items.stream().collect(Collectors
+                .toMap(DictModel::getValue, DictModel::getText, (oldValue, newValue) -> newValue));
+        page.getRecords().forEach(item -> {
+            String type = item.getType();
+            item.setTypeStr(typeMap.get(type));
+        });
+        return Result.OK(page);
+    }
+
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public Result<?> saveOrUpdate1(GardsAlertSystem alertSystem) {
+        String id = alertSystem.getId();
+        String code = alertSystem.getCode();
+        LambdaQueryWrapper<GardsAlertSystem> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(GardsAlertSystem::getCode, code);
+        if (StrUtil.isBlank(id)){ // 如果是新增,判断code是否已经存在
+            if (CollUtil.isNotEmpty(this.list(wrapper)))
+                return Result.error("Code " + code + " is exist!");
+            if (this.saveOrUpdate(alertSystem))
+                return Result.OK(Prompt.ADD_SUCC);
+            return Result.error(Prompt.ADD_ERR);
+        } else { // 如果是修改,判断code是否修改,如果code修改,判断修改的code是否已经存在
+            GardsAlertSystem alertSystemOld = this.getById(id);
+            String oldCode = alertSystemOld.getCode();
+            if (!StrUtil.equals(code, oldCode))
+                if (CollUtil.isNotEmpty(this.list(wrapper)))
+                    return Result.error("Code " + code + " is exist!");
+            if (this.saveOrUpdate(alertSystem))
+                return Result.OK(Prompt.UPDATE_SUCC);
+            return Result.error(Prompt.UPDATE_ERR);
+        }
+    }
+
+    @Override
+    public Result<?> delete(String id) {
+        boolean success = this.removeById(id);
+        if (success)
+            return Result.OK(Prompt.DELETE_SUCC);
+        return Result.OK(Prompt.DELETE_ERR);
+    }
+
+    @Override
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
+    public Result<?> deleteBatch(String ids) {
+        boolean success = removeBatchByIds(ListUtil.toList(StrUtil.split(ids, StrUtil.COMMA)));
+        if (success)
+            return Result.OK(Prompt.DELETE_SUCC);
+        return Result.OK(Prompt.DELETE_ERR);
+    }
+
+    @Override
+    public Map<String, String> codeMap() {
+        return this.list().stream().collect(Collectors.toMap(GardsAlertSystem::getCode, GardsAlertSystem::getContent));
+    }
+}
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/controller/WebStatisticsController.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/controller/WebStatisticsController.java
index f28a02d5..4373e5c3 100644
--- a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/controller/WebStatisticsController.java
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/controller/WebStatisticsController.java
@@ -88,7 +88,7 @@ public class WebStatisticsController {
 
     @GetMapping("findAlertSohPage")
     @ApiOperation(value = "台站报警数据分页查询", notes = "台站报警数据分页查询")
-    public Result findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds,@DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,@DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime){
+    public Result findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds, String startTime, String endTime){
         return gardsSohDataService.findAlertSohPage(queryRequest, stationIds, startTime, endTime);
     }
 
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/entity/GardsAlertDataWeb.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/entity/GardsAlertDataWeb.java
index e0369000..b7ad2cf1 100644
--- a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/entity/GardsAlertDataWeb.java
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/entity/GardsAlertDataWeb.java
@@ -14,4 +14,6 @@ public class GardsAlertDataWeb extends GardsAlertData {
     @TableField(exist = false)
     private Integer no;
 
+    @TableField(exist = false)
+    private Integer category;
 }
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/feignclient/SystemClient.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/feignclient/SystemClient.java
new file mode 100644
index 00000000..cf21cdac
--- /dev/null
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/feignclient/SystemClient.java
@@ -0,0 +1,16 @@
+package org.jeecg.modules.feignclient;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+
+import java.util.Map;
+
+@Component
+@FeignClient("armd-system")
+public interface SystemClient {
+
+    /* GardsAlertSystemController下相关接口 */
+    @GetMapping("/sys/alertSystem/codeMap")
+    Map<String, String> codeMap();
+}
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/GardsAlertDataMapper.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/GardsAlertDataMapper.java
index c2a8c1c1..0071b991 100644
--- a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/GardsAlertDataMapper.java
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/GardsAlertDataMapper.java
@@ -1,8 +1,12 @@
 package org.jeecg.modules.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.jeecg.modules.entity.GardsAlertDataWeb;
 
-public interface GardsAlertDataMapper extends BaseMapper<GardsAlertDataWeb> {
+import java.util.List;
+import java.util.Map;
 
+public interface GardsAlertDataMapper extends BaseMapper<GardsAlertDataWeb> {
+    Page<GardsAlertDataWeb> page(Page<GardsAlertDataWeb> page, Map<String, Object> params);
 }
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/xml/GardsAlertDataMapper.xml b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/xml/GardsAlertDataMapper.xml
new file mode 100644
index 00000000..313291df
--- /dev/null
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/mapper/xml/GardsAlertDataMapper.xml
@@ -0,0 +1,23 @@
+<?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="org.jeecg.modules.mapper.GardsAlertDataMapper">
+
+    <select id="page" resultType="org.jeecg.modules.entity.GardsAlertDataWeb">
+        SELECT
+            d.*, s.CATEGORY
+        FROM
+            ORIGINAL.GARDS_ALERT_DATA d
+            LEFT JOIN CONFIGURATION.GARDS_STATIONS s ON d.STATION_ID = s.STATION_ID
+        <where>
+            <if test="params.stationIds != null and params.stationIds.size() > 0">
+                d.STATION_ID IN
+                <foreach collection="params.stationIds" index="index" item="stationId" open="(" separator="," close=")">
+                    #{stationId}
+                </foreach>
+            </if>
+            AND d.TIME BETWEEN TO_DATE(#{params.startTime}, 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE(#{params.endTime}, 'YYYY-MM-DD HH24:MI:SS')
+        </where>
+        ORDER BY d.TIME DESC
+    </select>
+
+</mapper>
\ No newline at end of file
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/IGardsSohDataService.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/IGardsSohDataService.java
index 03392863..0549cb72 100644
--- a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/IGardsSohDataService.java
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/IGardsSohDataService.java
@@ -29,7 +29,7 @@ public interface IGardsSohDataService extends IService<GardsSohDataWeb> {
      * @param endTime
      * @return
      */
-    Result findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds, Date startTime, Date endTime);
+    Result findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds, String startTime, String endTime);
 
     /**
      * 获取单个SOH对象
diff --git a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/impl/GardsSohDataServiceImpl.java b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/impl/GardsSohDataServiceImpl.java
index cd9ce9fe..3fcf72b0 100644
--- a/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/impl/GardsSohDataServiceImpl.java
+++ b/jeecg-module-web-statistics/src/main/java/org/jeecg/modules/service/impl/GardsSohDataServiceImpl.java
@@ -1,8 +1,12 @@
 package org.jeecg.modules.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,11 +14,14 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.jeecg.common.api.QueryRequest;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.constant.DateConstant;
+import org.jeecg.common.constant.Prompt;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.common.util.ExportUtil;
 import org.jeecg.common.util.RedisUtil;
 import org.jeecg.modules.entity.GardsAlertDataWeb;
 import org.jeecg.modules.entity.GardsSohDataWeb;
+import org.jeecg.modules.feignclient.SystemClient;
 import org.jeecg.modules.mapper.GardsAlertDataMapper;
 import org.jeecg.modules.mapper.GardsSohDataMapper;
 import org.jeecg.modules.service.IGardsSohDataService;
@@ -28,6 +35,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.text.ParseException;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service("gardsSohDataService")
 @DS("ora")
@@ -35,6 +43,10 @@ public class GardsSohDataServiceImpl extends ServiceImpl<GardsSohDataMapper, Gar
 
     @Autowired
     private RedisUtil redisUtil;
+
+    @Autowired
+    private SystemClient systemClient;
+
     @Autowired
     private GardsAlertDataMapper gardsAlertDataMapper;
 
@@ -86,38 +98,47 @@ public class GardsSohDataServiceImpl extends ServiceImpl<GardsSohDataMapper, Gar
     }
 
     @Override
-    public Result findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds, Date startTime, Date endTime) {
-        try {
-            Result result = new Result();
-            if (Objects.isNull(stationIds)){
-                result.setResult(Collections.emptyList());
-                return result;
-            }
-            if (Objects.isNull(startTime)){
-                result.error500("The start time cannot be empty");
-                return result;
-            }
-            if (Objects.isNull(endTime)){
-                result.error500("The end time cannot be empty");
-                return result;
-            }
-            Date startDate = DateUtils.parseDate(DateUtils.formatDate(startTime, "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
-            Date endDate = DateUtils.parseDate(DateUtils.formatDate(endTime, "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
-            //获取redis中缓存的探测器信息
-            Map<Integer, String> detectorsMap = (Map<Integer, String>)redisUtil.get("detectorsMap");
-            Page<GardsAlertDataWeb> page = new Page<>(queryRequest.getPageNo(), queryRequest.getPageSize());
-            LambdaQueryWrapper<GardsAlertDataWeb> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.in(GardsAlertDataWeb::getStationId, stationIds);
-            queryWrapper.ge(GardsAlertDataWeb::getTime, startDate);
-            queryWrapper.le(GardsAlertDataWeb::getTime, endDate);
-            queryWrapper.orderByDesc(GardsAlertDataWeb::getTime);
-            Page<GardsAlertDataWeb> alertDataPage = gardsAlertDataMapper.selectPage(page, queryWrapper);
-            result.setSuccess(true);
-            result.setResult(alertDataPage);
-            return result;
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
+    public Result<?> findAlertSohPage(QueryRequest queryRequest, Integer[] stationIds, String startTime, String endTime) {
+        if (StrUtil.isBlank(startTime))
+            return Result.error("StartTime" + Prompt.PARAM_REQUIRED);
+        if (StrUtil.isBlank(endTime))
+            return Result.error("EndTime" + Prompt.PARAM_REQUIRED);
+        startTime += DateConstant.TIME_START;
+        endTime += DateConstant.TIME_END;
+        Map<String, Object> params = new HashMap<>();
+        params.put("stationIds", ListUtil.toList(stationIds));
+        params.put("startTime", startTime);
+        params.put("endTime", endTime);
+        Integer pageNo = queryRequest.getPageNo();
+        Integer pageSize = queryRequest.getPageSize();
+        Page<GardsAlertDataWeb> page = new Page<>(pageNo, pageSize);
+
+        Page<GardsAlertDataWeb> alertDataPage = gardsAlertDataMapper.page(page, params);
+        List<GardsAlertDataWeb> records = alertDataPage.getRecords();
+        if (CollUtil.isEmpty(records))
+            return Result.OK(alertDataPage);
+        Map<String, String> codeMap = systemClient.codeMap();
+        String flag1 = "Error code: ";
+        String flag2 = "Error code : ";
+        String regex1 = flag1 + "(\\S+)";
+        String regex2 = flag2 + "(\\S+)";
+        for (GardsAlertDataWeb record : records) {
+            String alertType = record.getAlertType();
+            if (!StrUtil.equals(alertType, "ALERT_SYSTEM"))
+                continue;
+            String alertText = record.getAlertText();
+            boolean c1 = StrUtil.contains(alertText, flag1);
+            boolean c2 = StrUtil.contains(alertText, flag2);
+            if (!c1 && !c2) continue;
+            String flag = c1 ? flag1 : flag2;
+            String regex = c1 ? regex1 : regex2;
+            String code = ReUtil.getGroup1(regex, alertText);
+            String replace = flag + codeMap.get(code);
+            String replaced = ReUtil.getGroup0(regex, alertText);
+            alertText = StrUtil.replace(alertText, replaced, replace);
+            record.setAlertText(alertText);
         }
+        return Result.OK(alertDataPage);
     }
 
     @Override
diff --git a/jeecg-server-cloud/armd-cloud-nacos/src/main/resources/application.yml b/jeecg-server-cloud/armd-cloud-nacos/src/main/resources/application.yml
index ffc1c3a8..316cb2e9 100644
--- a/jeecg-server-cloud/armd-cloud-nacos/src/main/resources/application.yml
+++ b/jeecg-server-cloud/armd-cloud-nacos/src/main/resources/application.yml
@@ -15,11 +15,11 @@ db:
   password:
     '0': ${MYSQL-PWD:123456}
   url:
-    '0': jdbc:postgresql://${MYSQL-HOST:182.92.183.230}:${MYSQL-PORT:5432}/${MYSQL-DB:nacos}?tcpKeepAlive=true&reWriteBatchedInserts=true&ApplicationName=nacos_java
+    '0': jdbc:postgresql://${MYSQL-HOST:127.0.0.1}:${MYSQL-PORT:5432}/${MYSQL-DB:nacos}?tcpKeepAlive=true&reWriteBatchedInserts=true&ApplicationName=nacos_java
     #'0': jdbc:postgresql://${MYSQL-HOST:172.21.50.118}:${MYSQL-PORT:5432}/${MYSQL-DB:nacos}?tcpKeepAlive=true&reWriteBatchedInserts=true&ApplicationName=nacos_java
   user:
-    '0': ${MYSQL-USER:temp}
-    #'0': ${MYSQL-USER:postgres}
+    #'0': ${MYSQL-USER:temp}
+    '0': ${MYSQL-USER:postgres}
   pool:
     config:
       driver-class-name: org.postgresql.Driver
diff --git a/jeecg-server-cloud/armd-spectrum-analysis-start/src/main/java/org/jeecg/JeecgSpectrumAnalysisApplication.java b/jeecg-server-cloud/armd-spectrum-analysis-start/src/main/java/org/jeecg/JeecgSpectrumAnalysisApplication.java
index 5ca9816c..b56896b1 100644
--- a/jeecg-server-cloud/armd-spectrum-analysis-start/src/main/java/org/jeecg/JeecgSpectrumAnalysisApplication.java
+++ b/jeecg-server-cloud/armd-spectrum-analysis-start/src/main/java/org/jeecg/JeecgSpectrumAnalysisApplication.java
@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.cache.BetaCache;
 import org.jeecg.common.cache.LocalCache;
+import org.jeecg.common.cache.SelfCache;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.service.IGardsNuclLibService;
 import org.jeecg.modules.service.IDataService;
@@ -34,6 +35,8 @@ public class JeecgSpectrumAnalysisApplication extends SpringBootServletInitializ
     @Autowired
     private BetaCache betaCache;
     @Autowired
+    private SelfCache selfCache;
+    @Autowired
     private IGammaService gammaService;
     @Autowired
     private IGardsNuclCoincidenceSumSpectrumService nuclCoincidenceSumSpectrumService;
@@ -92,6 +95,7 @@ public class JeecgSpectrumAnalysisApplication extends SpringBootServletInitializ
         //创建缓存
         betaCache.initCache();
         localCache.initCache();
+        selfCache.initCache();
         gammaService.readMDCParameter();
         nuclLibService.getNuclideMap();
         nuclCoincidenceSumSpectrumService.getNuclCoincidenceMap();