jingbo 2 дней назад
Родитель
Сommit
c1e0d1deef

+ 1 - 0
.classpath

@@ -21,4 +21,5 @@
 	<classpathentry kind="lib" path="lib/sqlite-jdbc-3.36.0.3.jar"/>
 	<classpathentry kind="lib" path="lib/commons-codec-1.15.jar"/>
 	<classpathentry kind="lib" path="lib/fastjson2-2.0.16.jar"/>
+	<classpathentry kind="lib" path="lib/iot-communication-1.4.4.jar"/>
 </classpath>

+ 155 - 0
src/com/mes/device/DeviceStateReporter.java

@@ -0,0 +1,155 @@
+package com.mes.device;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.mes.util.HttpUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Properties;
+
+/**
+ * 工位客户端设备状态上报(按 gw + lineSn)
+ */
+public class DeviceStateReporter {
+
+    public static final Logger log = LoggerFactory.getLogger(DeviceStateReporter.class);
+
+    /** 正常运行 */
+    public static final String STATE_RUNNING = "1";
+    /** 工位退出/收班 */
+    public static final String STATE_STOP = "7";
+
+    private static DeviceStateReporter instance;
+
+    private String serverIp;
+    private String gw;
+    private String gw2;
+    private String lineSn;
+
+    private DeviceStateReporter() {
+    }
+
+    public static DeviceStateReporter getInstance() {
+        if (instance == null) {
+            synchronized (DeviceStateReporter.class) {
+                if (instance == null) {
+                    instance = new DeviceStateReporter();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 从配置文件初始化
+     */
+    public void initFromConfig() {
+        try {
+            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
+            Properties pro = new Properties();
+            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+            pro.load(br);
+            br.close();
+            is.close();
+            init(
+                    pro.getProperty("mes.server_ip", "").trim(),
+                    pro.getProperty("mes.gw", "").trim(),
+                    pro.getProperty("mes.line_sn", "").trim()
+            );
+        } catch (Exception e) {
+            log.error("初始化设备状态上报失败", e);
+        }
+    }
+
+    public void init(String serverIp, String gw, String lineSn) {
+        this.serverIp = serverIp;
+        this.gw = gw;
+        this.gw2 = gw;
+        this.lineSn = lineSn;
+        log.info("设备状态上报初始化: gw={}, lineSn={}", gw, lineSn);
+    }
+
+    /**
+     * 双工位初始化
+     */
+    public void initDual(String serverIp, String gw1, String gw2, String lineSn) {
+        this.serverIp = serverIp;
+        this.gw = gw1;
+        this.gw2 = gw2;
+        this.lineSn = lineSn;
+        log.info("设备状态上报初始化: gw1={}, gw2={}, lineSn={}", gw1, gw2, lineSn);
+    }
+
+    /**
+     * 异步上报(单工位)
+     */
+    public void reportAsync(final String state, final String content) {
+        reportBothAsync(state, content);
+    }
+
+    /**
+     * 异步上报(双工位)
+     */
+    public void reportBothAsync(final String state, final String content) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                reportBothSync(state, content);
+            }
+        }, "device-state-report-thread").start();
+    }
+
+    /**
+     * 同步上报(单工位,兼容旧调用)
+     */
+    public boolean reportSync(String state, String content) {
+        return reportBothSync(state, content);
+    }
+
+    /**
+     * 同步上报(双工位各报一条)
+     */
+    public boolean reportBothSync(String state, String content) {
+        boolean ok1 = reportSyncForGw(gw, state, content);
+        if (isBlank(gw2) || gw2.equals(gw)) {
+            return ok1;
+        }
+        boolean ok2 = reportSyncForGw(gw2, state, content);
+        return ok1 && ok2;
+    }
+
+    /**
+     * 同步上报指定工位
+     */
+    public boolean reportSyncForGw(String targetGw, String state, String content) {
+        if (isBlank(serverIp) || isBlank(targetGw) || isBlank(lineSn)) {
+            log.warn("设备状态上报跳过:配置不完整 serverIp={}, gw={}, lineSn={}", serverIp, targetGw, lineSn);
+            return false;
+        }
+        try {
+            String url = "http://" + serverIp + ":8980/js/a/mes/mesDevice/reportState";
+            JSONObject body = new JSONObject();
+            body.put("gw", targetGw);
+            body.put("lineSn", lineSn);
+            body.put("state", state);
+            body.put("content", content == null ? "" : content);
+            String result = HttpUtils.sendPostRequestJson(url, body.toJSONString());
+            log.info("设备状态上报: gw={}, state={}, content={}, result={}", targetGw, state, content, result);
+            if (isBlank(result) || "false".equalsIgnoreCase(result)) {
+                return false;
+            }
+            JSONObject retObj = JSONObject.parseObject(result);
+            return retObj != null && "true".equalsIgnoreCase(String.valueOf(retObj.get("result")));
+        } catch (Exception e) {
+            log.error("设备状态上报异常: gw={}, state={}, content={}", targetGw, state, content, e);
+            return false;
+        }
+    }
+
+    private boolean isBlank(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+}

+ 158 - 0
src/com/mes/ui/BindMaterialPanel.java

@@ -0,0 +1,158 @@
+package com.mes.ui;
+
+import com.alibaba.fastjson2.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableModel;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+/**
+ * 绑定物料面板(按工位)
+ */
+public class BindMaterialPanel extends JPanel {
+
+    private static final Logger log = LoggerFactory.getLogger(BindMaterialPanel.class);
+
+    private static final String[] COLUMN_NAMES = {"物料名称", "绑定批次", "剩余次数", "操作"};
+
+    private final String oprno;
+    private JTable table;
+    private DefaultTableModel tableModel;
+    private Object[][] rowData;
+
+    public BindMaterialPanel(String oprno) {
+        this.oprno = oprno;
+        initUI();
+        refreshData();
+    }
+
+    private void initUI() {
+        setLayout(new BorderLayout());
+        tableModel = new DefaultTableModel(COLUMN_NAMES, 0) {
+            @Override
+            public boolean isCellEditable(int row, int column) {
+                return column == 3;
+            }
+        };
+        table = new JTable(tableModel);
+        table.setRowHeight(40);
+        table.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        table.getColumnModel().getColumn(3).setCellRenderer(new TableCellRendererButton());
+        table.getColumnModel().getColumn(3).setCellEditor(new BindMaterialCellEditor(this));
+        add(new JScrollPane(table), BorderLayout.CENTER);
+    }
+
+    /**
+     * 刷新物料列表
+     */
+    public void refreshData() {
+        try {
+            JSONObject retObj = DataUtil.getBindMaterail(oprno);
+            tableModel.setRowCount(0);
+            if (retObj == null || retObj.get("result") == null
+                    || !retObj.get("result").toString().equalsIgnoreCase("true")) {
+                return;
+            }
+            List<BindMaterialResp> arrs = retObj.getList("data", BindMaterialResp.class);
+            if (arrs == null) {
+                return;
+            }
+            rowData = new Object[arrs.size()][7];
+            int i = 0;
+            for (BindMaterialResp item : arrs) {
+                rowData[i][0] = item.getMaterialTitle();
+                rowData[i][1] = item.getBatchSn();
+                rowData[i][2] = item.getLastTimes();
+                rowData[i][3] = "";
+                rowData[i][4] = item.getCraft();
+                rowData[i][5] = item.getMaterialId();
+                rowData[i][6] = item.getType();
+                tableModel.addRow(new Object[]{
+                        rowData[i][0], rowData[i][1], rowData[i][2], rowData[i][3]
+                });
+                i++;
+            }
+            table.repaint();
+        } catch (Exception e) {
+            log.error("加载工位 {} 物料失败", oprno, e);
+        }
+    }
+
+    /**
+     * 扫码绑定物料
+     */
+    public void scanBatchSn(int selectedRow) {
+        if (rowData == null || selectedRow < 0 || selectedRow >= rowData.length) {
+            return;
+        }
+        BindMaterialResp bindMaterialResp = new BindMaterialResp();
+        bindMaterialResp.setMaterialTitle(rowData[selectedRow][0] + "");
+        bindMaterialResp.setBatchSn(rowData[selectedRow][1] + "");
+        bindMaterialResp.setLastTimes(rowData[selectedRow][2] + "");
+        bindMaterialResp.setCraft(rowData[selectedRow][4] + "");
+        bindMaterialResp.setMaterialId(rowData[selectedRow][5] + "");
+        bindMaterialResp.setType(rowData[selectedRow][6] + "");
+
+        String scanBarcodeTitle = "请扫物料:" + bindMaterialResp.getMaterialTitle() + "(" + oprno + ")";
+        String scanBarcode = JOptionPane.showInputDialog(null, scanBarcodeTitle);
+        if (scanBarcode == null || scanBarcode.equalsIgnoreCase("")) {
+            return;
+        }
+
+        JSONObject retObj = DataUtil.saveBindMaterail(
+                scanBarcode,
+                bindMaterialResp.getCraft(),
+                bindMaterialResp.getMaterialId(),
+                bindMaterialResp.getType(),
+                oprno
+        );
+        if (retObj != null && retObj.get("result") != null
+                && retObj.get("result").toString().equalsIgnoreCase("true")) {
+            MesClient.setMenuStatus("扫物料:" + bindMaterialResp.getMaterialTitle() + "成功", 0);
+            refreshData();
+        } else if (retObj == null || retObj.get("result") == null) {
+            MesClient.setMenuStatus("请求失败,请重试", -1);
+        } else if (retObj.get("result").toString().equalsIgnoreCase("false")) {
+            MesClient.setMenuStatus(retObj.getString("message"), -1);
+        }
+    }
+
+    public String getOprno() {
+        return oprno;
+    }
+
+    /**
+     * 物料扫码按钮编辑器
+     */
+    private static class BindMaterialCellEditor extends DefaultCellEditor {
+        private final BindMaterialPanel panel;
+        private final JButton btn;
+
+        BindMaterialCellEditor(BindMaterialPanel panel) {
+            super(new JTextField());
+            this.panel = panel;
+            setClickCountToStart(1);
+            btn = new JButton("扫码");
+            btn.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    int selectedRow = panel.table.getSelectedRow();
+                    panel.scanBatchSn(selectedRow);
+                    fireEditingStopped();
+                }
+            });
+        }
+
+        @Override
+        public Component getTableCellEditorComponent(JTable table, Object value,
+                                                     boolean isSelected, int row, int column) {
+            panel.table.setRowSelectionInterval(row, row);
+            return btn;
+        }
+    }
+}

+ 58 - 0
src/com/mes/ui/CmtReq.java

@@ -0,0 +1,58 @@
+package com.mes.ui;
+
+public class CmtReq {
+    private Integer id;
+    private String oprno;
+    private String lineSn;
+    private String sn;
+    private String content;
+    private Integer sync;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getOprno() {
+        return oprno;
+    }
+
+    public void setOprno(String oprno) {
+        this.oprno = oprno;
+    }
+
+    public String getLineSn() {
+        return lineSn;
+    }
+
+    public void setLineSn(String lineSn) {
+        this.lineSn = lineSn;
+    }
+
+    public String getSn() {
+        return sn;
+    }
+
+    public void setSn(String sn) {
+        this.sn = sn;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Integer getSync() {
+        return sync;
+    }
+
+    public void setSync(Integer sync) {
+        this.sync = sync;
+    }
+}

+ 58 - 21
src/com/mes/ui/DataUtil.java

@@ -46,21 +46,17 @@ public class DataUtil {
     }
 
     public static JSONObject checkQuality(String sn, String user){
+        return checkQuality(sn, user, MesClient.mes_gw, MesClient.mes_line_sn, MesClient.mes_server_ip);
+    }
+
+    public static JSONObject checkQuality(String sn, String user, String oprno, String lineSn, String serverIp){
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
-            String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductRecord/pccheck";
-            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&ucode="+user;
+            String url = "http://"+serverIp+":8980/js/a/mes/mesProductRecord/pccheck";
+            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&ucode="+user+"&__sid="+MesClient.sessionid;
             log.info("params="+params);
             String result = doPost(url,params);
             log.info("result="+result);
-            if(result.equalsIgnoreCase("false")) {
+            if(result == null || result.equalsIgnoreCase("false")) {
                 return null;
             }else {
                 JdbcUtils.insertData(oprno, "100000", params, "AQDW", sn);
@@ -73,6 +69,29 @@ public class DataUtil {
     }
 
     public static JSONObject sendQuality(String sn,String ret,String user){
+        return sendQualityPc(sn, ret, user, MesClient.mes_gw, MesClient.mes_line_sn, MesClient.mes_server_ip);
+    }
+
+    public static JSONObject sendQualityPc(String sn, String ret, String user, String oprno, String lineSn, String serverIp){
+        try{
+            String url = "http://"+serverIp+":8980/js/a/mes/mesProductRecord/pcresult";
+            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&result="+ret+"&ucode="+user+"&__sid="+MesClient.sessionid;
+            log.info("params="+params);
+            String result = doPost(url,params);
+            log.info("result="+result);
+            if(result == null || result.equalsIgnoreCase("false")) {
+                return null;
+            }else {
+                JdbcUtils.insertData(oprno, "100000", params, "MQDW", sn);
+                return JSONObject.parseObject(result);
+            }
+        }catch (Exception e){
+            log.info("e="+e.getMessage());
+            return null;
+        }
+    }
+
+    public static JSONObject upParams(String upparams) {
         try{
             String enconding = "UTF-8";
             InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
@@ -80,22 +99,17 @@ public class DataUtil {
             BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
             pro.load(br);
             String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
-            String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductRecord/pcresult";
-            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&result="+ret+"&ucode="+user;
+            String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductCmt/batchsave";
+            String params = "__ajax=json&params="+upparams;
             log.info("params="+params);
             String result = doPost(url,params);
             log.info("result="+result);
-
-            if(result.equalsIgnoreCase("false")) {
+            if(result == null || result.equalsIgnoreCase("false")) {
                 return null;
             }else {
-                JdbcUtils.insertData(oprno, "100000", params, "MQDW", sn);
                 return JSONObject.parseObject(result);
             }
         }catch (Exception e){
-            log.info("e="+e.getMessage());
             return null;
         }
     }
@@ -113,6 +127,10 @@ public class DataUtil {
     }
 
     public static JSONObject getBindMaterail() {
+        return getBindMaterail(MesClient.mes_gw);
+    }
+
+    public static JSONObject getBindMaterail(String oprno) {
         try{
             String enconding = "UTF-8";
             InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
@@ -120,7 +138,6 @@ public class DataUtil {
             BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
             pro.load(br);
             String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
             String lineSn = pro.getProperty("mes.line_sn").trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesLineProcessMaterial/materials";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn;
@@ -138,7 +155,28 @@ public class DataUtil {
         }
     }
 
+    /**
+     * 工位是否配置了待绑定物料
+     */
+    public static boolean hasBindMaterial(String oprno) {
+        try {
+            JSONObject retObj = getBindMaterail(oprno);
+            if (retObj == null || retObj.get("result") == null
+                    || !retObj.get("result").toString().equalsIgnoreCase("true")) {
+                return false;
+            }
+            List<BindMaterialResp> arrs = retObj.getList("data", BindMaterialResp.class);
+            return arrs != null && !arrs.isEmpty();
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
     public static JSONObject saveBindMaterail(String batchSn,String craft,String materialId,String type) {
+        return saveBindMaterail(batchSn, craft, materialId, type, MesClient.mes_gw);
+    }
+
+    public static JSONObject saveBindMaterail(String batchSn,String craft,String materialId,String type, String oprno) {
         try{
             String enconding = "UTF-8";
             InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
@@ -146,7 +184,6 @@ public class DataUtil {
             BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
             pro.load(br);
             String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
             String lineSn = pro.getProperty("mes.line_sn").trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesMaterialPrebind/bind";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&batchSn="+batchSn+"&craft="+craft+"&materialId="+materialId+"&type="+type;

+ 62 - 47
src/com/mes/ui/LoginFarme.java

@@ -1,8 +1,6 @@
 package com.mes.ui;
 
 import com.alibaba.fastjson2.JSONObject;
-import com.mes.component.MesRadio;
-import com.mes.component.MesWebView;
 import com.mes.util.Base64Utils;
 import com.mes.util.HttpUtils;
 
@@ -22,7 +20,10 @@ public class LoginFarme extends JFrame {
     static JButton scanLoginButton = new JButton("扫  码  登  录");
 
     public LoginFarme(){
-        setTitle("MES系统客户端:"+MesClient.mes_gw+" - "+MesClient.mes_gw_des);
+        String titleGw = MesClient.isDualStation()
+                ? MesClient.mes_gw1 + " / " + MesClient.mes_gw2
+                : MesClient.mes_gw;
+        setTitle("MES系统客户端115:" + titleGw + " - " + MesClient.mes_gw_des);
 
         ImageIcon bg = new ImageIcon(MesClient.class.getResource("/background.png"));
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -45,11 +46,11 @@ public class LoginFarme extends JFrame {
         userPasswordLabel.setBounds(300, 150, 120, 40);
         userPasswordLabel.setFont(new java.awt.Font("Dialog",   1,   16));
         userNameTxt = new JTextField(20);
-        userNameTxt.setText("system");
+        userNameTxt.setText("");
         userNameTxt.setBounds(400, 105, 150, 30);
         userPasswordTxt = new JPasswordField(20);
         userPasswordTxt.setBounds(400, 155, 150, 30);
-        userPasswordTxt.setText("Aa111111");
+        userPasswordTxt.setText("");
         loginButton.setFont(new java.awt.Font("Dialog",   1,   16));
         loginButton.setBounds(300, 200, 255, 40);
         loginButton.setIcon(new ImageIcon(MesClient.class.getResource("/bg/user.png")));
@@ -156,54 +157,68 @@ public class LoginFarme extends JFrame {
         //获取sessionid,判断权限
         MesClient.sessionid = retObj.get("sessionid").toString();
         if(MesClient.sessionid!=null&&!MesClient.sessionid.equalsIgnoreCase("")) {
-            //请求权限
-            String url_authority = "http://"+MesClient.mes_server_ip+":8980/js/a/mes/mesLineProcess/userAuth?__ajax=json&type=0&__sid="+MesClient.sessionid+"&oprno="+MesClient.mes_gw+"&lineSn="+MesClient.mes_line_sn;
-            String authorityResult = HttpUtils.sendRequest(url_authority);
-            System.out.println("authorityResult="+authorityResult);
-            JSONObject authorityObj = JSONObject.parseObject(authorityResult);
-            if(authorityObj.get("result")!=null&&authorityObj.get("result").toString().equalsIgnoreCase("true")) {
-                JSONObject authObjTmp = JSONObject.parseObject(authorityObj.get("data").toString());
-                MesClient.mes_auth = Integer.parseInt(authObjTmp.getString("auth").toString());
-                if(MesClient.mes_auth==0) {
-                    //无权限登录
-                    JOptionPane.showMessageDialog(MesClient.mesClientFrame,"您无权登录该工位","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+            int auth1 = getUserAuthForStation(MesClient.mes_gw1);
+            if (auth1 == 0) {
+                JOptionPane.showMessageDialog(MesClient.mesClientFrame,
+                        "您无权登录工位:" + MesClient.mes_gw1, "提示窗口", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+            int auth2 = auth1;
+            if (MesClient.isDualStation()) {
+                auth2 = getUserAuthForStation(MesClient.mes_gw2);
+                if (auth2 == 0) {
+                    JOptionPane.showMessageDialog(MesClient.mesClientFrame,
+                            "您无权登录工位:" + MesClient.mes_gw2, "提示窗口", JOptionPane.INFORMATION_MESSAGE);
                     return;
-                }else if(MesClient.mes_auth==1||MesClient.mes_auth==2) {
-                    // 获取等于所处时间-当前小时
-                    LocalDateTime now = LocalDateTime.now();
-                    MesClient.userLoginHours = now.getHour();
-                    //启动timer心跳包
-                    MesClient.startHeartBeatTimer();
-
-                    //1操作工人,2管理员
-                    //登录成功
-                    MesClient.user_menu.setText(user_id);
-                    MesClient.welcomeWin.setVisible(false);
-                    MesClient.mesClientFrame.setVisible(true);
-                    MesClient.startGetCurSn();
-                    // 已弃用WebView(工作记录),改为使用WorkRecordPanel
-                     if(MesClient.jfxPanel == null){
-                         String url = "http://"+ MesClient.mes_server_ip+":8980/js/a/mes/mesProductRecord/work?oprno="+MesClient.mes_gw+"&lineSn="+MesClient.mes_line_sn;
-                         MesClient.jfxPanel = new MesWebView(url);
-                         MesClient.jfxPanel.setSize(990, 550);
-                         MesClient.indexPanelB.add(MesClient.jfxPanel);
-                     }
-
-                    if(MesClient.jfxPanel2 == null){
-                        String url = "http://"+ MesClient.mes_server_ip+":8980/js/a/mes/mesProcessCheckRecord/ulist?ucode="+user_id+"&oprno="+MesClient.mes_gw+"&lineSn="+MesClient.mes_line_sn;
-                        MesClient.jfxPanel2 = new MesWebView(url);
-                        MesClient.jfxPanel2.setSize(990, 550);
-                        MesClient.indexPanelC.add(MesClient.jfxPanel2);
-                    }
-
-                    MesClient.initWarehouseData();
                 }
-
             }
-
+            MesClient.mes_auth = Math.max(auth1, auth2);
+            if(MesClient.mes_auth==1||MesClient.mes_auth==2) {
+                // 获取等于所处时间-当前小时
+                LocalDateTime now = LocalDateTime.now();
+                MesClient.userLoginHours = now.getHour();
+                //启动timer心跳包(界面)
+                MesClient.startHeartBeatTimer();
+                // 上报设备运行状态并启动定时上报
+                MesClient.reportDeviceRunning();
+
+                //1操作工人,2管理员
+                //登录成功
+                MesClient.user_menu.setText(user_id);
+                MesClient.welcomeWin.setVisible(false);
+                MesClient.mesClientFrame.setVisible(true);
+                MesClient.initDualStationCheckTabs(user_id);
+                MesClient.startGetCurSn();
+                MesClient.initWarehouseData();
+            }
         }else {
             JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录失败,用户名或密码错误","提示窗口", JOptionPane.INFORMATION_MESSAGE);
             return;
         }
     }
+
+    /**
+     * 查询用户对指定工位的登录权限
+     */
+    private static int getUserAuthForStation(String oprno) {
+        try {
+            String urlAuthority = "http://" + MesClient.mes_server_ip
+                    + ":8980/js/a/mes/mesLineProcess/userAuth?__ajax=json&type=0&__sid="
+                    + MesClient.sessionid + "&oprno=" + oprno + "&lineSn=" + MesClient.mes_line_sn;
+            String authorityResult = HttpUtils.sendRequest(urlAuthority);
+            System.out.println("authorityResult(" + oprno + ")=" + authorityResult);
+            if (authorityResult == null || authorityResult.equalsIgnoreCase("false")) {
+                return 0;
+            }
+            JSONObject authorityObj = JSONObject.parseObject(authorityResult);
+            if (authorityObj.get("result") != null
+                    && authorityObj.get("result").toString().equalsIgnoreCase("true")) {
+                JSONObject authObjTmp = JSONObject.parseObject(authorityObj.get("data").toString());
+                return Integer.parseInt(authObjTmp.getString("auth").toString());
+            }
+        } catch (Exception e) {
+            System.out.println("getUserAuthForStation error: " + e.getMessage());
+        }
+        return 0;
+    }
 }

Разница между файлами не показана из-за своего большого размера
+ 547 - 267
src/com/mes/ui/MesClient.java


+ 21 - 0
src/com/mes/ui/PlcReadTest.java

@@ -0,0 +1,21 @@
+package com.mes.ui;
+
+import javax.swing.*;
+
+/**
+ * PLC 点位读取测试入口,启动可视化监控窗口。
+ */
+public class PlcReadTest {
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(() -> {
+            try {
+                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+            } catch (Exception ignored) {
+            }
+            String plcIp = PlcReadTestFrame.loadPlcIp();
+            PlcReadTestFrame frame = new PlcReadTestFrame(plcIp);
+            frame.setVisible(true);
+        });
+    }
+}

+ 379 - 0
src/com/mes/ui/PlcReadTestFrame.java

@@ -0,0 +1,379 @@
+package com.mes.ui;
+
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+import java.awt.*;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * PLC 点位实时监控测试窗口(DB200 全部点位,每 4 秒刷新)
+ */
+public class PlcReadTestFrame extends JFrame {
+
+    private static final String DEFAULT_PLC_IP = "192.168.1.1";
+    private static final int DB_NO = 200;
+    private static final long READ_INTERVAL_MS = 1000;
+    private static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    private final S7PLC s7PLC;
+    private final String db;
+    private final List<PlcPointDef> pointDefs = buildPointDefs();
+
+    private JLabel lblPlcInfo;
+    private JLabel lblLastUpdate;
+    private JLabel lblReadStatus;
+    private JButton btnMesAllowTest;
+    private DefaultTableModel tableModel;
+    private Timer readTimer;
+
+    public PlcReadTestFrame(String plcIp) {
+        this.s7PLC = new S7PLC(EPlcType.S1200, plcIp);
+        this.db = "DB" + DB_NO;
+
+        setTitle("PLC 点位监控测试 - OP040~OP060");
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        setBounds(100, 80, 980, 720);
+        setMinimumSize(new Dimension(860, 600));
+
+        initUI(plcIp);
+        startReadTimer();
+        addWindowListener(new java.awt.event.WindowAdapter() {
+            @Override
+            public void windowClosing(java.awt.event.WindowEvent e) {
+                stopReadTimer();
+            }
+        });
+    }
+
+    private void initUI(String plcIp) {
+        JPanel content = new JPanel(new BorderLayout(8, 8));
+        content.setBorder(new EmptyBorder(10, 10, 10, 10));
+        setContentPane(content);
+
+        content.add(buildTopPanel(plcIp), BorderLayout.NORTH);
+        content.add(buildTablePanel(), BorderLayout.CENTER);
+        content.add(buildBottomPanel(), BorderLayout.SOUTH);
+    }
+
+    private JPanel buildTopPanel(String plcIp) {
+        JPanel panel = new JPanel(new BorderLayout(8, 4));
+        panel.setBorder(new TitledBorder("连接信息"));
+
+        lblPlcInfo = new JLabel("PLC IP: " + plcIp + "    数据块: " + db + "    刷新间隔: "
+                + (READ_INTERVAL_MS / 1000) + " 秒    点位数量: " + pointDefs.size());
+        lblPlcInfo.setFont(new Font("微软雅黑", Font.PLAIN, 15));
+        panel.add(lblPlcInfo, BorderLayout.WEST);
+
+        lblLastUpdate = new JLabel("最后更新: --");
+        lblLastUpdate.setFont(new Font("微软雅黑", Font.PLAIN, 15));
+        lblLastUpdate.setHorizontalAlignment(SwingConstants.RIGHT);
+        panel.add(lblLastUpdate, BorderLayout.EAST);
+        return panel;
+    }
+
+    private JScrollPane buildTablePanel() {
+        String[] columns = {"分组", "名称", "PLC地址", "类型", "当前值"};
+        tableModel = new DefaultTableModel(columns, 0) {
+            @Override
+            public boolean isCellEditable(int row, int column) {
+                return false;
+            }
+        };
+
+        JTable table = new JTable(tableModel);
+        table.setRowHeight(32);
+        table.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 14));
+        table.getTableHeader().setReorderingAllowed(false);
+        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+        table.getColumnModel().getColumn(0).setPreferredWidth(100);
+        table.getColumnModel().getColumn(1).setPreferredWidth(180);
+        table.getColumnModel().getColumn(2).setPreferredWidth(120);
+        table.getColumnModel().getColumn(3).setPreferredWidth(70);
+        table.getColumnModel().getColumn(4).setPreferredWidth(140);
+
+        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
+        centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
+        table.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
+        table.getColumnModel().getColumn(3).setCellRenderer(centerRenderer);
+        table.getColumnModel().getColumn(4).setCellRenderer(new PlcValueCellRenderer());
+
+        DefaultTableCellRenderer leftRenderer = new DefaultTableCellRenderer();
+        leftRenderer.setHorizontalAlignment(SwingConstants.LEFT);
+        table.getColumnModel().getColumn(1).setCellRenderer(leftRenderer);
+
+        // 初始化空行
+        for (PlcPointDef def : pointDefs) {
+            tableModel.addRow(new Object[]{def.group, def.name, db + "." + def.offset, def.type, "--"});
+        }
+
+        JScrollPane scrollPane = new JScrollPane(table);
+        scrollPane.setBorder(new TitledBorder("DB200 全部点位(实时)"));
+        return scrollPane;
+    }
+
+    private JPanel buildBottomPanel() {
+        JPanel panel = new JPanel(new BorderLayout());
+        lblReadStatus = new JLabel("状态: 等待首次读取...");
+        lblReadStatus.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        lblReadStatus.setForeground(new Color(0, 100, 0));
+        panel.add(lblReadStatus, BorderLayout.WEST);
+
+        JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
+
+        btnMesAllowTest = new JButton("测试: MES允许进站 → TRUE");
+        btnMesAllowTest.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        btnMesAllowTest.setForeground(new Color(0, 100, 0));
+        btnMesAllowTest.addActionListener(e -> toggleMesAllowEntry());
+        btnPanel.add(btnMesAllowTest);
+
+        JButton refreshBtn = new JButton("立即刷新");
+        refreshBtn.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        refreshBtn.addActionListener(e -> readPointsAsync(true));
+        btnPanel.add(refreshBtn);
+
+        panel.add(btnPanel, BorderLayout.EAST);
+        return panel;
+    }
+
+    /**
+     * 测试写入 MES允许进站(DB200.0.1),点击后在 TRUE/FALSE 间切换
+     */
+    private void toggleMesAllowEntry() {
+        btnMesAllowTest.setEnabled(false);
+        new Thread(() -> {
+            try {
+                Boolean current = s7PLC.readBoolean(db + ".0.1");
+                boolean newVal = !Boolean.TRUE.equals(current);
+                s7PLC.writeBoolean(db + ".0.1", newVal);
+                final String msg = "MES允许进站 已写入: " + (newVal ? "TRUE" : "FALSE");
+                SwingUtilities.invokeLater(() -> {
+                    updateMesAllowButtonText(newVal);
+                    lblReadStatus.setText("状态: " + msg);
+                    lblReadStatus.setForeground(new Color(0, 100, 0));
+                    btnMesAllowTest.setEnabled(true);
+                    readPointsAsync(true);
+                });
+            } catch (Exception e) {
+                SwingUtilities.invokeLater(() -> {
+                    lblReadStatus.setText("状态: MES允许进站写入失败 - " + e.getMessage());
+                    lblReadStatus.setForeground(Color.RED);
+                    btnMesAllowTest.setEnabled(true);
+                });
+            }
+        }, "PlcRead-MesAllowTest").start();
+    }
+
+    /** 根据当前值更新测试按钮文案 */
+    private void updateMesAllowButtonText(boolean currentVal) {
+        if (currentVal) {
+            btnMesAllowTest.setText("测试: MES允许进站 → FALSE");
+            btnMesAllowTest.setForeground(new Color(180, 80, 0));
+        } else {
+            btnMesAllowTest.setText("测试: MES允许进站 → TRUE");
+            btnMesAllowTest.setForeground(new Color(0, 100, 0));
+        }
+    }
+
+    private void startReadTimer() {
+        readTimer = new Timer("PlcReadTestFrame-Timer", true);
+        readTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                readPointsAsync(false);
+            }
+        }, 0, READ_INTERVAL_MS);
+    }
+
+    private void stopReadTimer() {
+        if (readTimer != null) {
+            readTimer.cancel();
+            readTimer = null;
+        }
+    }
+
+    private void readPointsAsync(boolean manual) {
+        new Thread(() -> {
+            List<String[]> rows = new ArrayList<>();
+            int errorCount = 0;
+            for (PlcPointDef def : pointDefs) {
+                String value = readPointValue(def);
+                if (value.startsWith("读取异常")) {
+                    errorCount++;
+                }
+                rows.add(new String[]{def.group, def.name, db + "." + def.offset, def.type, value});
+            }
+            final int errors = errorCount;
+            final String time = LocalDateTime.now().format(TIME_FMT);
+            SwingUtilities.invokeLater(() -> updateTable(rows, time, errors, manual));
+        }, manual ? "PlcRead-Manual" : "PlcRead-Timer").start();
+    }
+
+    private String readPointValue(PlcPointDef def) {
+        try {
+            String addr = db + "." + def.offset;
+            switch (def.type) {
+                case "Bool":
+                    Boolean b = s7PLC.readBoolean(addr);
+                    return b == null ? "null" : (b ? "TRUE" : "FALSE");
+                case "Word":
+                    Short w = s7PLC.readInt16(addr);
+                    return w == null ? "null" : String.valueOf(w);
+                case "Real":
+                    Float r = s7PLC.readFloat32(addr);
+                    return r == null ? "null" : String.format("%.2f", r);
+                default:
+                    return "未知类型";
+            }
+        } catch (Exception e) {
+            return "读取异常: " + e.getMessage();
+        }
+    }
+
+    private void updateTable(List<String[]> rows, String time, int errorCount, boolean manual) {
+        for (int i = 0; i < rows.size() && i < tableModel.getRowCount(); i++) {
+            String[] row = rows.get(i);
+            for (int col = 0; col < row.length; col++) {
+                tableModel.setValueAt(row[col], i, col);
+            }
+        }
+        lblLastUpdate.setText("最后更新: " + time + (manual ? "(手动)" : ""));
+        if (errorCount > 0) {
+            lblReadStatus.setText("状态: 读取完成," + errorCount + " 个点位异常");
+            lblReadStatus.setForeground(Color.RED);
+        } else if (!manual) {
+            lblReadStatus.setText("状态: 读取正常,共 " + pointDefs.size() + " 个点位");
+            lblReadStatus.setForeground(new Color(0, 128, 0));
+        }
+        // 同步 MES允许进站 测试按钮文案
+        syncMesAllowButtonFromTable();
+    }
+
+    /** 从表格中 MES允许进站 行同步按钮显示 */
+    private void syncMesAllowButtonFromTable() {
+        if (btnMesAllowTest == null) {
+            return;
+        }
+        for (int i = 0; i < tableModel.getRowCount(); i++) {
+            if ("MES允许进站".equals(tableModel.getValueAt(i, 1))) {
+                String val = String.valueOf(tableModel.getValueAt(i, 4));
+                updateMesAllowButtonText("TRUE".equals(val));
+                break;
+            }
+        }
+    }
+
+    /** DB200 全部点位定义 */
+    private static List<PlcPointDef> buildPointDefs() {
+        List<PlcPointDef> list = new ArrayList<>();
+        // 状态信号 Bool
+        list.add(new PlcPointDef("状态信号", "心跳信号", "0.0", "Bool"));
+        list.add(new PlcPointDef("状态信号", "MES允许进站", "0.1", "Bool"));
+        list.add(new PlcPointDef("状态信号", "工位A识别", "0.2", "Bool"));
+        list.add(new PlcPointDef("状态信号", "工位B识别", "0.3", "Bool"));
+        list.add(new PlcPointDef("状态信号", "A面启动中", "0.4", "Bool"));
+        list.add(new PlcPointDef("状态信号", "B面启动中", "0.5", "Bool"));
+        list.add(new PlcPointDef("状态信号", "R1焊接中", "0.6", "Bool"));
+        list.add(new PlcPointDef("状态信号", "R2焊接中", "0.7", "Bool"));
+        list.add(new PlcPointDef("状态信号", "屏蔽信号", "1.0", "Bool"));
+        list.add(new PlcPointDef("状态信号", "报警信号", "1.1", "Bool"));
+        list.add(new PlcPointDef("状态信号", "R1焊接完成(单条)", "1.2", "Bool"));
+        // R1 工艺参数
+        list.add(new PlcPointDef("R1工艺参数", "R1焊道序号", "2", "Word"));
+        list.add(new PlcPointDef("R1工艺参数", "R1焊接电流平均值", "4", "Real"));
+        list.add(new PlcPointDef("R1工艺参数", "R1焊接电压平均值", "8", "Real"));
+        list.add(new PlcPointDef("R1工艺参数", "R1送丝速度平均值", "12", "Real"));
+        list.add(new PlcPointDef("R1工艺参数", "R1焊接速度", "16", "Real"));
+        // R2 工艺参数
+        list.add(new PlcPointDef("R2工艺参数", "R2焊接完成(单条)", "20.0", "Bool"));
+        list.add(new PlcPointDef("R2工艺参数", "R2焊道序号", "22", "Word"));
+        list.add(new PlcPointDef("R2工艺参数", "R2焊接电流平均值", "24", "Real"));
+        list.add(new PlcPointDef("R2工艺参数", "R2焊接电压平均值", "28", "Real"));
+        list.add(new PlcPointDef("R2工艺参数", "R2送丝速度平均值", "32", "Real"));
+        list.add(new PlcPointDef("R2工艺参数", "R2焊接速度", "36", "Real"));
+        // 面完成信号
+        list.add(new PlcPointDef("面完成信号", "A面焊接完成", "40.0", "Bool"));
+        list.add(new PlcPointDef("面完成信号", "B面焊接完成", "40.1", "Bool"));
+        return list;
+    }
+
+    public static String loadPlcIp() {
+        try {
+            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
+            if (is != null) {
+                Properties pro = new Properties();
+                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+                pro.load(br);
+                br.close();
+                String ip = pro.getProperty("mes.plc_ip");
+                if (ip != null && !ip.trim().isEmpty()) {
+                    return ip.trim();
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return DEFAULT_PLC_IP;
+    }
+
+    /** 点位定义 */
+    private static class PlcPointDef {
+        final String group;
+        final String name;
+        final String offset;
+        final String type;
+
+        PlcPointDef(String group, String name, String offset, String type) {
+            this.group = group;
+            this.name = name;
+            this.offset = offset;
+            this.type = type;
+        }
+    }
+
+    /** 当前值列渲染:TRUE/FALSE/异常 分色显示 */
+    private static class PlcValueCellRenderer extends DefaultTableCellRenderer {
+        @Override
+        public Component getTableCellRendererComponent(JTable table, Object value,
+                                                       boolean isSelected, boolean hasFocus,
+                                                       int row, int column) {
+            Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+            setHorizontalAlignment(SwingConstants.CENTER);
+            if (!isSelected) {
+                String text = value == null ? "" : value.toString();
+                if ("TRUE".equals(text)) {
+                    setBackground(new Color(210, 245, 210));
+                    setForeground(new Color(0, 120, 0));
+                    setFont(getFont().deriveFont(Font.BOLD));
+                } else if ("FALSE".equals(text)) {
+                    setBackground(Color.WHITE);
+                    setForeground(new Color(100, 100, 100));
+                    setFont(getFont().deriveFont(Font.PLAIN));
+                } else if (text.startsWith("读取异常")) {
+                    setBackground(new Color(255, 230, 230));
+                    setForeground(Color.RED);
+                } else {
+                    setBackground(new Color(240, 248, 255));
+                    setForeground(new Color(0, 70, 140));
+                    setFont(getFont().deriveFont(Font.BOLD));
+                }
+            }
+            return c;
+        }
+    }
+}

+ 259 - 0
src/com/mes/ui/PlcUtil.java

@@ -0,0 +1,259 @@
+package com.mes.ui;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+import com.mes.util.DateLocalUtils;
+import com.mes.util.JdbcUtils;
+
+/**
+ * OP040-OP060 焊接工位 PLC 读写工具(DB200 非优化块)
+ */
+public class PlcUtil {
+
+    private static final String DB = "DB200";
+
+    /**
+     * 获取工作站外面当前是哪一面(工位A/B识别信号)
+     */
+    public static String getOutsideSide(S7PLC s7PLC) {
+        try {
+            Boolean stationA = s7PLC.readBoolean(DB + ".0.2");
+            Boolean stationB = s7PLC.readBoolean(DB + ".0.3");
+            if (Boolean.TRUE.equals(stationA)) {
+                return "A";
+            }
+            if (Boolean.TRUE.equals(stationB)) {
+                return "B";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return MesClient.curPage.isEmpty() ? "A" : MesClient.curPage;
+    }
+
+    /**
+     * 屏蔽信号 DB200.1.0
+     */
+    public static Boolean getShieldSignal(S7PLC s7PLC) {
+        try {
+            return s7PLC.readBoolean(DB + ".1.0");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static boolean setShieldSignal(S7PLC s7PLC, boolean shield) {
+        try {
+            s7PLC.writeBoolean(DB + ".1.0", shield);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * MES允许进站信号
+     */
+    public static boolean setMesAllowEntry(S7PLC s7PLC, boolean allow) {
+        try {
+            s7PLC.writeBoolean(DB + ".0.1", allow);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 任一面开始加工(A/B面启动中)时,立即撤销 MES 允许进站
+     */
+    public static void syncMesAllowOnSideStart(S7PLC s7PLC) {
+        try {
+            Boolean aStart = getAStart(s7PLC);
+            Boolean bStart = getBStart(s7PLC);
+            if (Boolean.TRUE.equals(aStart) || Boolean.TRUE.equals(bStart)) {
+                setMesAllowEntry(s7PLC, false);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static Boolean getAStart(S7PLC s7PLC) {
+        try {
+            return s7PLC.readBoolean(DB + ".0.4");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static Boolean getBStart(S7PLC s7PLC) {
+        try {
+            return s7PLC.readBoolean(DB + ".0.5");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static Boolean getAFinish(S7PLC s7PLC) {
+        try {
+            return s7PLC.readBoolean(DB + ".40.0");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static Boolean getBFinish(S7PLC s7PLC) {
+        try {
+            return s7PLC.readBoolean(DB + ".40.1");
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 质量检查通过后:发送 MES 允许进站,进入等待启动状态
+     */
+    public static void onQualityPass(String side) {
+        if ("A".equals(side)) {
+            MesClient.tjFlaga = 1;
+            MesClient.mesQualityFlagA = true;
+            MesClient.pxstatus.setText("A:质量合格,已发送允许进站,等待启动");
+        } else {
+            MesClient.tjFlagb = 1;
+            MesClient.mesQualityFlagB = true;
+            MesClient.pxstatus.setText("B:质量合格,已发送允许进站,等待启动");
+        }
+        setMesAllowEntry(MesClient.s7PLC, true);
+        MesClient.setMenuStatus(MesClient.pxstatus.getText(), 0);
+    }
+
+    /**
+     * A 面状态机:等待启动 -> 运行采数 -> 完成提交
+     */
+    public static void getStatusA(S7PLC s7PLC) {
+        // A面启动中时,确保 MES 允许进站已撤销
+        if (Boolean.TRUE.equals(getAStart(s7PLC))) {
+            setMesAllowEntry(s7PLC, false);
+        }
+        if (MesClient.tjFlaga == 1) {
+            if (Boolean.TRUE.equals(getAStart(s7PLC))) {
+                MesClient.curFlag = "A";
+                MesClient.tjFlaga = 2;
+                MesClient.pxstatus.setText("A:设备运行中,采集中...");
+                MesClient.hjparams.clear();
+            }
+        } else if (MesClient.tjFlaga == 2) {
+            if (Boolean.TRUE.equals(getAFinish(s7PLC))) {
+                MesClient.tjFlaga = 3;
+                MesClient.pxstatus.setText("A:焊接完成,提交结果中...");
+                submitResult("A", MesClient.product_sn.getText(), MesClient.mes_gw1);
+            }
+        }
+    }
+
+    /**
+     * B 面状态机
+     */
+    public static void getStatusB(S7PLC s7PLC) {
+        // B面启动中时,确保 MES 允许进站已撤销
+        if (Boolean.TRUE.equals(getBStart(s7PLC))) {
+            setMesAllowEntry(s7PLC, false);
+        }
+        if (MesClient.tjFlagb == 1) {
+            if (Boolean.TRUE.equals(getBStart(s7PLC))) {
+                MesClient.curFlag = "B";
+                MesClient.tjFlagb = 2;
+                MesClient.pxstatus.setText("B:设备运行中,采集中...");
+                MesClient.hjparams.clear();
+            }
+        } else if (MesClient.tjFlagb == 2) {
+            if (Boolean.TRUE.equals(getBFinish(s7PLC))) {
+                MesClient.tjFlagb = 3;
+                MesClient.pxstatus.setText("B:焊接完成,提交结果中...");
+                submitResult("B", MesClient.product_sn.getText(), MesClient.mes_gw2);
+            }
+        }
+    }
+
+    /**
+     * 运行中每秒采集 R1/R2 电流、电压、送丝速度
+     */
+    public static void collectWeldingParams(S7PLC s7PLC) {
+        if (MesClient.tjFlaga != 2 && MesClient.tjFlagb != 2) {
+            return;
+        }
+
+        try {
+            Float r1Current = s7PLC.readFloat32(DB + ".4");
+            Float r1Voltage = s7PLC.readFloat32(DB + ".8");
+            Float r1WireFeed = s7PLC.readFloat32(DB + ".12");
+            Float r2Current = s7PLC.readFloat32(DB + ".24");
+            Float r2Voltage = s7PLC.readFloat32(DB + ".28");
+            Float r2WireFeed = s7PLC.readFloat32(DB + ".32");
+
+            String recordTime = DateLocalUtils.getCurrentTime();
+            String paramLine = r1Current + "|" + r1Voltage + "|" + r1WireFeed + "|"
+                    + r2Current + "|" + r2Voltage + "|" + r2WireFeed + "|" + recordTime;
+            MesClient.hjparams.add(paramLine);
+
+            String oprno = "A".equals(MesClient.curFlag) ? MesClient.mes_gw1 : MesClient.mes_gw2;
+            String sn = MesClient.product_sn.getText();
+
+            // 每 60 条批量写入本地数据库
+            if (MesClient.hjparams.size() >= 60) {
+                JdbcUtils.insertCmtData(oprno, MesClient.mes_line_sn, sn, JSON.toJSONString(MesClient.hjparams));
+                MesClient.hjparams.clear();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 焊接完成:刷写剩余参数并提交 OK 结果
+     */
+    private static void submitResult(String side, String sn, String oprno) {
+        flushHjParams(oprno, sn);
+
+        JSONObject result = DataUtil.sendQualityPc(sn, "OK", MesClient.user20, oprno,
+                MesClient.mes_line_sn, MesClient.mes_server_ip);
+        if (result != null && "true".equalsIgnoreCase(result.getString("result"))) {
+            MesClient.setMenuStatus(side + "面提交成功", 0);
+            MesClient.pxstatus.setText(side + ":提交成功");
+            MesClient.resetScanA();
+        } else {
+            MesClient.setMenuStatus(side + "面提交失败,可手动重试", -1);
+            MesClient.pxstatus.setText(side + ":提交失败");
+            MesClient.finish_ok_bt.setEnabled(true);
+            MesClient.finish_ng_bt.setEnabled(true);
+            if ("A".equals(side)) {
+                MesClient.tjStatusa = 1;
+            } else {
+                MesClient.tjStatusb = 1;
+            }
+        }
+    }
+
+    /**
+     * 刷写剩余焊接参数到本地库
+     */
+    public static void flushHjParams(String oprno, String sn) {
+        if (MesClient.hjparams.isEmpty()) {
+            return;
+        }
+        try {
+            JdbcUtils.insertCmtData(oprno, MesClient.mes_line_sn, sn, JSON.toJSONString(MesClient.hjparams));
+            MesClient.hjparams.clear();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 0 - 43
src/com/mes/ui/TableCellEditorButton.java

@@ -1,43 +0,0 @@
-package com.mes.ui;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-public class TableCellEditorButton extends DefaultCellEditor {
-    private JButton btn;
-    public TableCellEditorButton() {
-        super(new JTextField());
-        //设置点击一次就激活,否则默认好像是点击2次激活。
-        this.setClickCountToStart(1);
-        btn = new JButton("扫码");
-        btn.addActionListener(new ActionListener() {
-
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                System.out.println("按钮事件触发----");
-                int selectedRow = MesClient.table.getSelectedRow();//获得选中行的索引
-//                MesClient.rowData[selectedRow][1] = (new Date()).getTime();
-//                MesClient.table.repaint(); //重绘
-
-//                MesClient.scan_type = selectedRow + 4;
-                BindMaterialResp bindMaterialResp = new BindMaterialResp();
-                bindMaterialResp.setMaterialTitle(MesClient.rowData[selectedRow][0] + "");
-                bindMaterialResp.setBatchSn(MesClient.rowData[selectedRow][1] + "");
-                bindMaterialResp.setLastTimes(MesClient.rowData[selectedRow][2] + "");
-                bindMaterialResp.setCraft(MesClient.rowData[selectedRow][4] + "");
-                bindMaterialResp.setMaterialId(MesClient.rowData[selectedRow][5] + "");
-                bindMaterialResp.setType(MesClient.rowData[selectedRow][6] + "");
-
-                MesClient.scanBatchSn(bindMaterialResp);
-            }
-        });
-
-    }
-    @Override
-    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
-
-        return btn;
-    }
-}

+ 66 - 1
src/com/mes/util/JdbcUtils.java

@@ -1,12 +1,16 @@
 package com.mes.util;
 
+import com.mes.ui.CmtReq;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
 
 public class JdbcUtils {
 	public static final Logger log =  LoggerFactory.getLogger(JdbcUtils.class);
@@ -21,7 +25,7 @@ public class JdbcUtils {
             conn = DriverManager.getConnection(DATABASE_URL);//连接数据库zhou.db,不存在则创建
             System.out.println("连接到SQLite数据库成功!");
             create_bw_record();//初始化结构表
-            //create_measure_data();//初始化测试数据
+            create_cmt_data();//初始化焊接参数
         } catch (Exception e) {
             // TODO Auto-generated catch block
         	close();//关闭数据库连接
@@ -127,6 +131,67 @@ public class JdbcUtils {
 		return ret;
 	}
 
+	public static void create_cmt_data() throws SQLException {
+		Statement statement = conn.createStatement();
+		String sqlEquipment = "CREATE TABLE if not exists bw_cmt("
+				+ "id INTEGER PRIMARY KEY AUTOINCREMENT,oprno VARCHAR(20),line_sn VARCHAR(20),"
+				+ "sn VARCHAR(50),content MEDIUMTEXT,create_time DATETIME,sync int(10) NULL DEFAULT 0"
+				+ ")";
+		statement.executeUpdate(sqlEquipment);
+		statement.close();
+	}
+
+	public static boolean insertCmtData(String oprno, String line_sn, String sn, String content) {
+		boolean ret = false;
+		String record_time = DateLocalUtils.getCurrentTime();
+		try {
+			if (JdbcUtils.conn == null || JdbcUtils.conn.isClosed()) {
+				JdbcUtils.openConnection();
+			}
+			Statement statement = conn.createStatement();
+			statement.executeUpdate("INSERT INTO bw_cmt (oprno,line_sn,sn,content,create_time) VALUES"
+					+ " ('" + oprno + "', '" + line_sn + "', '" + sn + "', '" + content + "','" + record_time + "')");
+			statement.close();
+			ret = true;
+		} catch (SQLException e) {
+			ret = false;
+		}
+		return ret;
+	}
+
+	public static void updateProdSync(Integer id, Integer sync) throws SQLException {
+		Statement statement = conn.createStatement();
+		statement.executeUpdate("update bw_cmt set sync = " + sync + " where id = " + id);
+		statement.close();
+	}
+
+	public static List<CmtReq> getCmtParams() {
+		String sql = "select id,oprno,line_sn,sn,content,sync from bw_cmt where sync = 0 order by id asc limit 100";
+		List<CmtReq> prods = new ArrayList<>();
+		try {
+			if (JdbcUtils.conn == null || JdbcUtils.conn.isClosed()) {
+				JdbcUtils.openConnection();
+			}
+			Statement stmt = conn.createStatement();
+			ResultSet ret = stmt.executeQuery(sql);
+			while (ret.next()) {
+				CmtReq cmtReq = new CmtReq();
+				cmtReq.setId(ret.getInt(1));
+				cmtReq.setOprno(ret.getString(2));
+				cmtReq.setLineSn(ret.getString(3));
+				cmtReq.setSn(ret.getString(4));
+				cmtReq.setContent(ret.getString(5));
+				cmtReq.setSync(ret.getInt(6));
+				prods.add(cmtReq);
+			}
+			ret.close();
+			stmt.close();
+		} catch (SQLException e) {
+			e.printStackTrace();
+		}
+		return prods;
+	}
+
     
     public static void close(){
         try {

+ 6 - 1
src/resources/config/config.properties

@@ -1,4 +1,9 @@
 mes.gw=OP040A
+mes.gw1=OP040A
+mes.gw2=OP060A
+mes.plc_ip=192.168.1.1
 #mes.server_ip=127.0.0.1
 mes.server_ip=192.168.9.180
-mes.line_sn=115XT
+mes.line_sn=115XT
+# 设备状态定时上报间隔(分钟)
+mes.device.heartbeat.minutes=5