sunxianglong 17 時間 前
親
コミット
86a8a1eabb

+ 31 - 16
src/com/mes/ui/DataUtil.java

@@ -216,11 +216,11 @@ public class DataUtil {
     /**
      * 查询称重工作记录(后台 mesWuliaoCz/pclist)
      * @param lc 炉次(可选)
-     * @param type 物料类型(可选)
+     * @param bc 班次(可选)
      * @param pageNo 页码
      * @param pageSize 每页条数
      */
-    public static WorkRecordResp getWeighRecordList(String lc, String type, int pageNo, int pageSize) {
+    public static WorkRecordResp getWeighRecordList(String lc, String bc, int pageNo, int pageSize) {
         WorkRecordResp resp = new WorkRecordResp();
         try {
             String encoding = "UTF-8";
@@ -238,8 +238,8 @@ public class DataUtil {
             if (lc != null && !lc.isEmpty()) {
                 params.append("&lc=").append(URLEncoder.encode(lc, encoding));
             }
-            if (type != null && !type.isEmpty()) {
-                params.append("&type=").append(URLEncoder.encode(type, encoding));
+            if (bc != null && !bc.isEmpty()) {
+                params.append("&bc=").append(URLEncoder.encode(bc, encoding));
             }
 
             log.info("查询称重记录: url={}, params={}", url, params);
@@ -273,9 +273,11 @@ public class DataUtil {
                     data.setId(item.getString("id"));
                     data.setLc(item.getString("lc"));
                     data.setBc(item.getString("bc"));
-                    data.setType(item.getString("type"));
-                    data.setZl(item.getString("zl"));
-                    // 操作人:优先 remarks,其次 createBy.userName/userCode
+                    data.setYzl(item.getString("yzl"));
+                    data.setHzl(item.getString("hzl"));
+                    data.setYQpZl(item.getString("yQpZl"));
+                    data.setHQpZl(item.getString("hQpZl"));
+                    data.setHlBl(item.getString("hlBl"));
                     String updateBy = item.getString("remarks");
                     if (updateBy == null || updateBy.isEmpty()) {
                         Object createBy = item.get("createBy");
@@ -303,14 +305,11 @@ public class DataUtil {
     }
 
     /**
-     * 称重数据提交到服务器
-     * @param lc 炉次
-     * @param bc 班次
-     * @param type 物料类型
-     * @param zl 重量
-     * @param user 操作人
+     * 称重数据提交到服务器(一次提交本炉合计)
+     * 回炉料比例 = (回炉料 - 回炉料去皮) / (原铝锭 + 回炉料 - 回炉料去皮 - 原铝锭去皮)
      */
-    public static JSONObject submitWeigh(String lc, String bc, String type, String zl, String user) {
+    public static JSONObject submitWeigh(String lc, String bc, String yzl, String hzl,
+                                         String yQpZl, String hQpZl, String hlBl, String user) {
         try {
             String encoding = "UTF-8";
             InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
@@ -323,8 +322,11 @@ public class DataUtil {
             params.append("__ajax=json");
             params.append("&lc=").append(lc == null ? "" : URLEncoder.encode(lc, encoding));
             params.append("&bc=").append(bc == null ? "" : URLEncoder.encode(bc, encoding));
-            params.append("&type=").append(type == null ? "" : URLEncoder.encode(type, encoding));
-            params.append("&zl=").append(zl == null ? "" : URLEncoder.encode(zl, encoding));
+            params.append("&yzl=").append(yzl == null ? "" : URLEncoder.encode(yzl, encoding));
+            params.append("&hzl=").append(hzl == null ? "" : URLEncoder.encode(hzl, encoding));
+            params.append("&yQpZl=").append(yQpZl == null ? "" : URLEncoder.encode(yQpZl, encoding));
+            params.append("&hQpZl=").append(hQpZl == null ? "" : URLEncoder.encode(hQpZl, encoding));
+            params.append("&hlBl=").append(hlBl == null ? "" : URLEncoder.encode(hlBl, encoding));
             if (user != null && !user.isEmpty()) {
                 params.append("&ucode=").append(URLEncoder.encode(user, encoding));
             }
@@ -340,4 +342,17 @@ public class DataUtil {
             return null;
         }
     }
+
+    /**
+     * 计算回炉料比例:(回炉料-回炉料去皮)/(原铝锭+回炉料-回炉料去皮-原铝锭去皮)
+     * 保留两位小数;分母为0返回null
+     */
+    public static String calcHlBl(double yzl, double hzl, double yQpZl, double hQpZl) {
+        double numer = hzl - hQpZl;
+        double denom = yzl + hzl - hQpZl - yQpZl;
+        if (Math.abs(denom) < 1e-9) {
+            return null;
+        }
+        return String.format("%.2f", numer / denom);
+    }
 }

+ 1 - 1
src/com/mes/ui/LoginFarme.java

@@ -22,7 +22,7 @@ public class LoginFarme extends JFrame {
     static JButton scanLoginButton = new JButton("扫  码  登  录");
 
     public LoginFarme(){
-        setTitle("MES系统客户端:"+MesClient.mes_gw+" - "+MesClient.mes_gw_des);
+        setTitle("MES系统客户端");
 
         ImageIcon bg = new ImageIcon(MesClient.class.getResource("/background.png"));
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

+ 1 - 1
src/com/mes/ui/MesClient.java

@@ -315,7 +315,7 @@ public class MesClient extends JFrame {
 
     public MesClient() {
         setIconImage(Toolkit.getDefaultToolkit().getImage(MesClient.class.getResource("/bg/logo.png")));
-        setTitle("MES系统客户端:"+mes_gw + "- " + mes_gw_des);
+        setTitle("MES系统客户端");
 //        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setBounds(0, 0, 1024, 768);
 

+ 300 - 156
src/com/mes/ui/WeighSubmitPanel.java

@@ -10,22 +10,21 @@ import org.slf4j.LoggerFactory;
 import javax.swing.*;
 import javax.swing.border.LineBorder;
 import java.awt.*;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.Statement;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * 称重提交面板
- * 展示炉次、班次、实时净重、物料类型、当前时间
- * 净重通过 Modbus-TCP 读取 Float 寄存器
+ * 流程:开始本次称重 → 多次记录重量(按物料类型累计)→ 结束本次称重(炉次+1)
  */
 public class WeighSubmitPanel extends JPanel {
 
@@ -33,24 +32,48 @@ public class WeighSubmitPanel extends JPanel {
 
     public static final String MATERIAL_INGOT = "原铝锭";
     public static final String MATERIAL_RECYCLE = "回炉料";
+    public static final String MATERIAL_INGOT_TARE = "原铝锭去皮";
+    public static final String MATERIAL_RECYCLE_TARE = "回炉料去皮";
 
-    private JLabel furnaceLabel;
     private JLabel furnaceValueLabel;
-    private JLabel shiftLabel;
     private JLabel shiftValueLabel;
-    private JLabel weightLabel;
     private JLabel weightValueLabel;
-    private JLabel materialLabel;
+    private JLabel modbusStatusLabel;
+    private JLabel timeValueLabel;
+    private JLabel ingotSumValueLabel;
+    private JLabel recycleSumValueLabel;
+    private JLabel ingotTareSumValueLabel;
+    private JLabel recycleTareSumValueLabel;
+    private JLabel ratioValueLabel;
+    private JLabel sessionStatusLabel;
     private JButton btnIngot;
     private JButton btnRecycle;
-    private JLabel timeLabel;
-    private JLabel timeValueLabel;
-    private JButton btnSubmit;
-    private JLabel modbusStatusLabel;
+    private JButton btnIngotTare;
+    private JButton btnRecycleTare;
+    private JButton btnSession;
+    private JButton btnRecord;
 
     private int furnaceNo = 1;
     private String selectedMaterial = MATERIAL_INGOT;
     private double netWeight = 0.0;
+    private boolean sessionActive = false;
+    private double ingotSum = 0.0;
+    private double recycleSum = 0.0;
+    private double ingotTareSum = 0.0;
+    private double recycleTareSum = 0.0;
+    private int sessionCount = 0;
+    private final List<SessionRecord> sessionRecords = new ArrayList<>();
+
+    private static class SessionRecord {
+        final String type;
+        final double weight;
+
+        SessionRecord(String type, double weight) {
+            this.type = type;
+            this.weight = weight;
+        }
+    }
+
     private Timer refreshTimer;
     private Timer modbusTimer;
     private ModbusWeightReader weightReader;
@@ -67,6 +90,7 @@ public class WeighSubmitPanel extends JPanel {
         loadFurnaceNo();
         updateShift();
         updateMaterialButtons();
+        updateSessionUi();
         startRefreshTimer();
         startModbusPolling();
     }
@@ -75,75 +99,47 @@ public class WeighSubmitPanel extends JPanel {
         setLayout(null);
         setBackground(Color.WHITE);
 
-        Font labelFont = new Font("微软雅黑", Font.PLAIN, 22);
-        Font valueFont = new Font("微软雅黑", Font.BOLD, 28);
-        Font weightFont = new Font("微软雅黑", Font.BOLD, 48);
-        Font buttonFont = new Font("微软雅黑", Font.BOLD, 22);
+        Font labelFont = new Font("微软雅黑", Font.PLAIN, 20);
+        Font valueFont = new Font("微软雅黑", Font.BOLD, 26);
+        Font weightFont = new Font("微软雅黑", Font.BOLD, 44);
+        Font buttonFont = new Font("微软雅黑", Font.BOLD, 18);
+        Font sumFont = new Font("微软雅黑", Font.BOLD, 28);
 
         int leftX = 80;
         int labelW = 140;
         int valueX = 230;
-        int valueW = 520;
-        int rowH = 70;
-        int y = 40;
-
-        // 炉次
-        furnaceLabel = new JLabel("炉次:");
-        furnaceLabel.setFont(labelFont);
-        furnaceLabel.setBounds(leftX, y, labelW, rowH);
-        add(furnaceLabel);
-
-        furnaceValueLabel = new JLabel(String.valueOf(furnaceNo));
-        furnaceValueLabel.setFont(valueFont);
-        furnaceValueLabel.setForeground(VALUE_COLOR);
-        furnaceValueLabel.setBounds(valueX, y, valueW, rowH);
-        add(furnaceValueLabel);
-        y += rowH + 10;
-
-        // 班次
-        shiftLabel = new JLabel("班次:");
-        shiftLabel.setFont(labelFont);
-        shiftLabel.setBounds(leftX, y, labelW, rowH);
-        add(shiftLabel);
-
-        shiftValueLabel = new JLabel("白班");
-        shiftValueLabel.setFont(valueFont);
-        shiftValueLabel.setForeground(VALUE_COLOR);
-        shiftValueLabel.setBounds(valueX, y, valueW, rowH);
-        add(shiftValueLabel);
-        y += rowH + 10;
-
-        // 实时净重
-        weightLabel = new JLabel("实时净重:");
-        weightLabel.setFont(labelFont);
-        weightLabel.setBounds(leftX, y, labelW + 20, rowH);
-        add(weightLabel);
+        int valueW = 620;
+        int rowH = 48;
+        int y = 20;
+
+        addLabel("炉次:", labelFont, leftX, y, labelW, rowH);
+        furnaceValueLabel = addValueLabel(String.valueOf(furnaceNo), valueFont, valueX, y, valueW, rowH);
+        y += rowH + 4;
 
+        addLabel("班次:", labelFont, leftX, y, labelW, rowH);
+        shiftValueLabel = addValueLabel("白班", valueFont, valueX, y, valueW, rowH);
+        y += rowH + 4;
+
+        addLabel("实时净重:", labelFont, leftX, y, labelW + 20, rowH);
         weightValueLabel = new JLabel(formatWeight(netWeight));
         weightValueLabel.setFont(weightFont);
-        weightValueLabel.setForeground(new Color(211, 47, 47));
-        weightValueLabel.setHorizontalAlignment(SwingConstants.LEFT);
-        weightValueLabel.setBounds(valueX, y, valueW, rowH + 10);
+        weightValueLabel.setForeground(Color.BLACK);
+        weightValueLabel.setBounds(valueX, y - 4, valueW, rowH + 14);
         add(weightValueLabel);
-        y += rowH + 10;
+        y += rowH + 6;
 
         modbusStatusLabel = new JLabel("Modbus:连接中...");
         modbusStatusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
         modbusStatusLabel.setForeground(Color.GRAY);
-        modbusStatusLabel.setBounds(valueX, y, valueW, 30);
+        modbusStatusLabel.setBounds(valueX, y, valueW, 22);
         add(modbusStatusLabel);
-        y += 40;
-
-        // 物料类型
-        materialLabel = new JLabel("物料类型:");
-        materialLabel.setFont(labelFont);
-        materialLabel.setBounds(leftX, y, labelW + 20, rowH);
-        add(materialLabel);
+        y += 26;
 
+        addLabel("物料类型:", labelFont, leftX, y, labelW + 20, rowH);
         btnIngot = new JButton(MATERIAL_INGOT);
         btnIngot.setFont(buttonFont);
         btnIngot.setFocusPainted(false);
-        btnIngot.setBounds(valueX, y + 8, 180, 55);
+        btnIngot.setBounds(valueX, y + 2, 140, 44);
         btnIngot.addActionListener(e -> {
             selectedMaterial = MATERIAL_INGOT;
             updateMaterialButtons();
@@ -153,50 +149,129 @@ public class WeighSubmitPanel extends JPanel {
         btnRecycle = new JButton(MATERIAL_RECYCLE);
         btnRecycle.setFont(buttonFont);
         btnRecycle.setFocusPainted(false);
-        btnRecycle.setBounds(valueX + 210, y + 8, 180, 55);
+        btnRecycle.setBounds(valueX + 150, y + 2, 140, 44);
         btnRecycle.addActionListener(e -> {
             selectedMaterial = MATERIAL_RECYCLE;
             updateMaterialButtons();
         });
         add(btnRecycle);
-        y += rowH + 30;
-
-        // 当前时间
-        timeLabel = new JLabel("当前时间:");
-        timeLabel.setFont(labelFont);
-        timeLabel.setBounds(leftX, y, labelW + 20, rowH);
-        add(timeLabel);
-
-        timeValueLabel = new JLabel(DateLocalUtils.getCurrentTime());
-        timeValueLabel.setFont(valueFont);
-        timeValueLabel.setForeground(VALUE_COLOR);
-        timeValueLabel.setBounds(valueX, y, valueW, rowH);
-        add(timeValueLabel);
-        y += rowH + 40;
-
-        // 提交按钮
-        btnSubmit = new JButton("称重提交");
-        btnSubmit.setFont(new Font("微软雅黑", Font.BOLD, 28));
-        btnSubmit.setBounds(valueX, y, 280, 70);
-        btnSubmit.setBackground(new Color(25, 118, 210));
-        btnSubmit.setForeground(Color.WHITE);
-        btnSubmit.setFocusPainted(false);
-        btnSubmit.setBorder(new LineBorder(new Color(21, 101, 192), 1));
-        btnSubmit.addActionListener(e -> onSubmit());
-        add(btnSubmit);
-
-        addComponentListener(new ComponentAdapter() {
-            @Override
-            public void componentResized(ComponentEvent e) {
-                // 保持绝对布局,工业触屏固定尺寸即可
-            }
+
+        btnIngotTare = new JButton(MATERIAL_INGOT_TARE);
+        btnIngotTare.setFont(buttonFont);
+        btnIngotTare.setFocusPainted(false);
+        btnIngotTare.setBounds(valueX + 300, y + 2, 150, 44);
+        btnIngotTare.addActionListener(e -> {
+            selectedMaterial = MATERIAL_INGOT_TARE;
+            updateMaterialButtons();
+        });
+        add(btnIngotTare);
+
+        btnRecycleTare = new JButton(MATERIAL_RECYCLE_TARE);
+        btnRecycleTare.setFont(buttonFont);
+        btnRecycleTare.setFocusPainted(false);
+        btnRecycleTare.setBounds(valueX + 460, y + 2, 150, 44);
+        btnRecycleTare.addActionListener(e -> {
+            selectedMaterial = MATERIAL_RECYCLE_TARE;
+            updateMaterialButtons();
         });
+        add(btnRecycleTare);
+        y += rowH + 12;
+
+        // 本次称重累计
+        addLabel("原铝锭:", labelFont, leftX, y, labelW + 20, rowH);
+        ingotSumValueLabel = new JLabel(formatWeight(0));
+        ingotSumValueLabel.setFont(sumFont);
+        ingotSumValueLabel.setForeground(new Color(46, 125, 50));
+        ingotSumValueLabel.setBounds(valueX, y, valueW, rowH);
+        add(ingotSumValueLabel);
+        y += rowH + 2;
+
+        addLabel("回炉料:", labelFont, leftX, y, labelW + 20, rowH);
+        recycleSumValueLabel = new JLabel(formatWeight(0));
+        recycleSumValueLabel.setFont(sumFont);
+        recycleSumValueLabel.setForeground(new Color(245, 124, 0));
+        recycleSumValueLabel.setBounds(valueX, y, valueW, rowH);
+        add(recycleSumValueLabel);
+        y += rowH + 2;
+
+        addLabel("原铝锭去皮:", labelFont, leftX, y, labelW + 40, rowH);
+        ingotTareSumValueLabel = new JLabel(formatWeight(0));
+        ingotTareSumValueLabel.setFont(sumFont);
+        ingotTareSumValueLabel.setForeground(new Color(123, 31, 162));
+        ingotTareSumValueLabel.setBounds(valueX, y, valueW, rowH);
+        add(ingotTareSumValueLabel);
+        y += rowH + 2;
+
+        addLabel("回炉料去皮:", labelFont, leftX, y, labelW + 40, rowH);
+        recycleTareSumValueLabel = new JLabel(formatWeight(0));
+        recycleTareSumValueLabel.setFont(sumFont);
+        recycleTareSumValueLabel.setForeground(new Color(156, 39, 176));
+        recycleTareSumValueLabel.setBounds(valueX, y, valueW, rowH);
+        add(recycleTareSumValueLabel);
+        y += rowH + 2;
+
+        addLabel("回炉料比例:", labelFont, leftX, y, labelW + 40, rowH);
+        ratioValueLabel = new JLabel("--");
+        ratioValueLabel.setFont(sumFont);
+        ratioValueLabel.setForeground(new Color(25, 118, 210));
+        ratioValueLabel.setBounds(valueX, y, valueW, rowH);
+        add(ratioValueLabel);
+        y += rowH + 2;
+
+        sessionStatusLabel = new JLabel("状态:未开始");
+        sessionStatusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        sessionStatusLabel.setForeground(Color.GRAY);
+        sessionStatusLabel.setBounds(valueX, y, valueW, 28);
+        add(sessionStatusLabel);
+        y += 34;
+
+        addLabel("当前时间:", labelFont, leftX, y, labelW + 20, rowH);
+        timeValueLabel = addValueLabel(DateLocalUtils.getCurrentTime(), valueFont, valueX, y, valueW, rowH);
+        y += rowH + 20;
+
+        btnSession = new JButton("开始本次称重");
+        btnSession.setFont(new Font("微软雅黑", Font.BOLD, 26));
+        btnSession.setBounds(valueX, y, 260, 64);
+        btnSession.setBackground(new Color(25, 118, 210));
+        btnSession.setForeground(Color.WHITE);
+        btnSession.setFocusPainted(false);
+        btnSession.setBorder(new LineBorder(new Color(21, 101, 192), 1));
+        btnSession.addActionListener(e -> onSessionToggle());
+        add(btnSession);
+
+        btnRecord = new JButton("记录重量");
+        btnRecord.setFont(new Font("微软雅黑", Font.BOLD, 26));
+        btnRecord.setBounds(valueX + 280, y, 200, 64);
+        btnRecord.setBackground(new Color(46, 125, 50));
+        btnRecord.setForeground(Color.WHITE);
+        btnRecord.setFocusPainted(false);
+        btnRecord.setBorder(new LineBorder(new Color(27, 94, 32), 1));
+        btnRecord.setEnabled(false);
+        btnRecord.addActionListener(e -> onRecordWeight());
+        add(btnRecord);
+    }
+
+    private void addLabel(String text, Font font, int x, int y, int w, int h) {
+        JLabel label = new JLabel(text);
+        label.setFont(font);
+        label.setBounds(x, y, w, h);
+        add(label);
+    }
+
+    private JLabel addValueLabel(String text, Font font, int x, int y, int w, int h) {
+        JLabel label = new JLabel(text);
+        label.setFont(font);
+        label.setForeground(VALUE_COLOR);
+        label.setBounds(x, y, w, h);
+        add(label);
+        return label;
     }
 
     private void updateMaterialButtons() {
-        boolean ingotSelected = MATERIAL_INGOT.equals(selectedMaterial);
-        styleMaterialButton(btnIngot, ingotSelected);
-        styleMaterialButton(btnRecycle, !ingotSelected);
+        styleMaterialButton(btnIngot, MATERIAL_INGOT.equals(selectedMaterial));
+        styleMaterialButton(btnRecycle, MATERIAL_RECYCLE.equals(selectedMaterial));
+        styleMaterialButton(btnIngotTare, MATERIAL_INGOT_TARE.equals(selectedMaterial));
+        styleMaterialButton(btnRecycleTare, MATERIAL_RECYCLE_TARE.equals(selectedMaterial));
     }
 
     private void styleMaterialButton(JButton button, boolean selected) {
@@ -211,14 +286,34 @@ public class WeighSubmitPanel extends JPanel {
         }
     }
 
-    /**
-     * 白班:当天 08:00 ~ 20:00;夜班:20:00 ~ 次日 08:00
-     */
+    private void updateSessionUi() {
+        if (sessionActive) {
+            btnSession.setText("结束本次称重");
+            btnSession.setBackground(new Color(198, 40, 40));
+            btnSession.setBorder(new LineBorder(new Color(183, 28, 28), 1));
+            btnRecord.setEnabled(true);
+            sessionStatusLabel.setText(String.format(
+                    "状态:称重中(本炉第 %d 次)", sessionCount));
+            sessionStatusLabel.setForeground(new Color(46, 125, 50));
+        } else {
+            btnSession.setText("开始本次称重");
+            btnSession.setBackground(new Color(25, 118, 210));
+            btnSession.setBorder(new LineBorder(new Color(21, 101, 192), 1));
+            btnRecord.setEnabled(false);
+            sessionStatusLabel.setText("状态:未开始,请点击“开始本次称重”");
+            sessionStatusLabel.setForeground(Color.GRAY);
+        }
+        ingotSumValueLabel.setText(formatWeight(ingotSum));
+        recycleSumValueLabel.setText(formatWeight(recycleSum));
+        ingotTareSumValueLabel.setText(formatWeight(ingotTareSum));
+        recycleTareSumValueLabel.setText(formatWeight(recycleTareSum));
+        String ratio = DataUtil.calcHlBl(ingotSum, recycleSum, ingotTareSum, recycleTareSum);
+        ratioValueLabel.setText(ratio == null ? "--" : ratio);
+    }
+
     public static String resolveShift(LocalDateTime now) {
         LocalTime time = now.toLocalTime();
-        LocalTime dayStart = LocalTime.of(8, 0);
-        LocalTime nightStart = LocalTime.of(20, 0);
-        if (!time.isBefore(dayStart) && time.isBefore(nightStart)) {
+        if (!time.isBefore(LocalTime.of(8, 0)) && time.isBefore(LocalTime.of(20, 0))) {
             return "白班";
         }
         return "夜班";
@@ -239,16 +334,14 @@ public class WeighSubmitPanel extends JPanel {
                 SwingUtilities.invokeLater(() -> {
                     timeValueLabel.setText(DateLocalUtils.getCurrentTime());
                     updateShift();
-                    // 跨天时自动重置炉次
-                    ensureFurnaceForToday();
+                    if (!sessionActive) {
+                        ensureFurnaceForToday();
+                    }
                 });
             }
         }, 0, 1000);
     }
 
-    /**
-     * 定时通过 Modbus-TCP 读取净重
-     */
     private void startModbusPolling() {
         weightReader = new ModbusWeightReader();
         if (modbusTimer != null) {
@@ -285,11 +378,12 @@ public class WeighSubmitPanel extends JPanel {
         return String.format("%.2f kg", weight);
     }
 
-    /**
-     * 更新实时净重显示
-     */
+    private double round2(double weight) {
+        return Math.round(weight * 100.0) / 100.0;
+    }
+
     public void setNetWeight(double weight) {
-        this.netWeight = Math.round(weight * 100.0) / 100.0;
+        this.netWeight = round2(weight);
         if (SwingUtilities.isEventDispatchThread()) {
             weightValueLabel.setText(formatWeight(netWeight));
         } else {
@@ -297,22 +391,6 @@ public class WeighSubmitPanel extends JPanel {
         }
     }
 
-    public double getNetWeight() {
-        return netWeight;
-    }
-
-    public int getFurnaceNo() {
-        return furnaceNo;
-    }
-
-    public String getSelectedMaterial() {
-        return selectedMaterial;
-    }
-
-    public String getCurrentShift() {
-        return shiftValueLabel.getText();
-    }
-
     private void loadFurnaceNo() {
         ensureFurnaceForToday();
         furnaceValueLabel.setText(String.valueOf(furnaceNo));
@@ -335,7 +413,6 @@ public class WeighSubmitPanel extends JPanel {
                     if (today.equals(recordDate)) {
                         furnaceNo = Math.max(no, 1);
                     } else {
-                        // 新的一天,从 1 重新开始
                         furnaceNo = 1;
                         upsertFurnaceNo(today, furnaceNo);
                     }
@@ -353,21 +430,17 @@ public class WeighSubmitPanel extends JPanel {
     }
 
     private void upsertFurnaceNo(String date, int no) throws Exception {
-        String deleteSql = "DELETE FROM furnace_counter";
-        String insertSql = "INSERT INTO furnace_counter (furnace_no, record_date) VALUES (?, ?)";
         try (Statement del = JdbcUtils.conn.createStatement()) {
-            del.executeUpdate(deleteSql);
+            del.executeUpdate("DELETE FROM furnace_counter");
         }
-        try (PreparedStatement ps = JdbcUtils.conn.prepareStatement(insertSql)) {
+        try (PreparedStatement ps = JdbcUtils.conn.prepareStatement(
+                "INSERT INTO furnace_counter (furnace_no, record_date) VALUES (?, ?)")) {
             ps.setInt(1, no);
             ps.setString(2, date);
             ps.executeUpdate();
         }
     }
 
-    /**
-     * 提交成功后炉次 +1(同一天内)
-     */
     public void incrementFurnaceNo() {
         try {
             String today = LocalDate.now().toString();
@@ -379,65 +452,136 @@ public class WeighSubmitPanel extends JPanel {
         }
     }
 
-    private void onSubmit() {
-        if (selectedMaterial == null || selectedMaterial.isEmpty()) {
-            JOptionPane.showMessageDialog(this, "请选择物料类型", "提示", JOptionPane.WARNING_MESSAGE);
+    private void onSessionToggle() {
+        if (!sessionActive) {
+            startSession();
+        } else {
+            endSession();
+        }
+    }
+
+    private void startSession() {
+        sessionActive = true;
+        ingotSum = 0.0;
+        recycleSum = 0.0;
+        ingotTareSum = 0.0;
+        recycleTareSum = 0.0;
+        sessionCount = 0;
+        sessionRecords.clear();
+        updateSessionUi();
+        MesClient.setMenuStatus("已开始本次称重(炉次 " + furnaceNo + "),可多次记录重量", 0);
+    }
+
+    private void endSession() {
+        if (sessionCount <= 0) {
+            sessionActive = false;
+            updateSessionUi();
+            MesClient.setMenuStatus("本次称重已取消(无记录)", 0);
+            return;
+        }
+
+        final String hlBl = DataUtil.calcHlBl(ingotSum, recycleSum, ingotTareSum, recycleTareSum);
+        if (hlBl == null) {
+            JOptionPane.showMessageDialog(this,
+                    "无法计算回炉料比例:原铝锭+回炉料-回炉料去皮-原铝锭去皮不能为0",
+                    "提交失败", JOptionPane.ERROR_MESSAGE);
             return;
         }
 
-        final String shift = resolveShift(LocalDateTime.now());
-        final String time = DateLocalUtils.getCurrentTime();
-        final String lc = String.valueOf(furnaceNo);
-        final String type = selectedMaterial;
-        final String zl = String.format("%.2f", netWeight);
         String msg = String.format(
-                "确认提交?\n炉次:%s\n班次:%s\n净重:%s\n物料:%s\n时间:%s",
-                lc, shift, formatWeight(netWeight), type, time
+                "确认结束并提交本次称重?\n炉次:%d\n原铝锭:%s\n回炉料:%s\n原铝锭去皮:%s\n回炉料去皮:%s\n回炉料比例:%s\n记录次数:%d\n提交成功后炉次将 +1",
+                furnaceNo, formatWeight(ingotSum), formatWeight(recycleSum),
+                formatWeight(ingotTareSum), formatWeight(recycleTareSum), hlBl, sessionCount
         );
-        int choice = JOptionPane.showConfirmDialog(this, msg, "称重提交确认", JOptionPane.YES_NO_OPTION);
+        int choice = JOptionPane.showConfirmDialog(this, msg, "结束本次称重", JOptionPane.YES_NO_OPTION);
         if (choice != JOptionPane.YES_OPTION) {
             return;
         }
 
-        btnSubmit.setEnabled(false);
-        MesClient.setMenuStatus("正在提交称重数据...", 0);
+        btnSession.setEnabled(false);
+        btnRecord.setEnabled(false);
+        MesClient.setMenuStatus("正在提交本次称重数据...", 0);
+
+        final String shift = resolveShift(LocalDateTime.now());
+        final String lc = String.valueOf(furnaceNo);
+        final String yzl = String.format("%.2f", ingotSum);
+        final String hzl = String.format("%.2f", recycleSum);
+        final String yQpZl = String.format("%.2f", ingotTareSum);
+        final String hQpZl = String.format("%.2f", recycleTareSum);
 
         new SwingWorker<JSONObject, Void>() {
             @Override
             protected JSONObject doInBackground() {
                 MesClient.getUser();
-                return DataUtil.submitWeigh(lc, shift, type, zl, MesClient.user20);
+                return DataUtil.submitWeigh(lc, shift, yzl, hzl, yQpZl, hQpZl, hlBl, MesClient.user20);
             }
 
             @Override
             protected void done() {
-                btnSubmit.setEnabled(true);
+                btnSession.setEnabled(true);
                 try {
                     JSONObject retObj = get();
                     if (retObj != null && retObj.get("result") != null
                             && "true".equalsIgnoreCase(retObj.get("result").toString())) {
-                        MesClient.setMenuStatus("称重提交成功", 0);
+                        sessionActive = false;
                         incrementFurnaceNo();
+                        ingotSum = 0.0;
+                        recycleSum = 0.0;
+                        ingotTareSum = 0.0;
+                        recycleTareSum = 0.0;
+                        sessionCount = 0;
+                        sessionRecords.clear();
+                        updateSessionUi();
+                        MesClient.setMenuStatus("本次称重提交成功,当前炉次:" + furnaceNo, 0);
                         JOptionPane.showMessageDialog(WeighSubmitPanel.this,
                                 "提交成功,下一炉次:" + furnaceNo, "提示", JOptionPane.INFORMATION_MESSAGE);
                     } else {
-                        String errMsg = "请求失败,请重试";
+                        String errMsg = "提交失败,请重试";
                         if (retObj != null && retObj.getString("message") != null) {
                             errMsg = retObj.getString("message");
                         }
                         MesClient.setMenuStatus(errMsg, -1);
                         JOptionPane.showMessageDialog(WeighSubmitPanel.this, errMsg, "提交失败", JOptionPane.ERROR_MESSAGE);
+                        updateSessionUi();
                     }
                 } catch (Exception e) {
-                    log.error("称重提交异常: {}", e.getMessage());
+                    log.error("结束称重提交异常: {}", e.getMessage());
                     MesClient.setMenuStatus("提交异常,请重试", -1);
                     JOptionPane.showMessageDialog(WeighSubmitPanel.this,
                             "提交异常:" + e.getMessage(), "提交失败", JOptionPane.ERROR_MESSAGE);
+                    updateSessionUi();
                 }
             }
         }.execute();
     }
 
+    private void onRecordWeight() {
+        if (!sessionActive) {
+            JOptionPane.showMessageDialog(this, "请先点击“开始本次称重”", "提示", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+        if (selectedMaterial == null || selectedMaterial.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "请选择物料类型", "提示", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        double rounded = round2(netWeight);
+        String type = selectedMaterial;
+        sessionRecords.add(new SessionRecord(type, rounded));
+        if (MATERIAL_INGOT.equals(type)) {
+            ingotSum = round2(ingotSum + rounded);
+        } else if (MATERIAL_RECYCLE.equals(type)) {
+            recycleSum = round2(recycleSum + rounded);
+        } else if (MATERIAL_INGOT_TARE.equals(type)) {
+            ingotTareSum = round2(ingotTareSum + rounded);
+        } else if (MATERIAL_RECYCLE_TARE.equals(type)) {
+            recycleTareSum = round2(recycleTareSum + rounded);
+        }
+        sessionCount++;
+        updateSessionUi();
+        MesClient.setMenuStatus("已记录:" + type + " +" + formatWeight(rounded) + "(结束时统一提交)", 0);
+    }
+
     public void disposePanel() {
         if (refreshTimer != null) {
             refreshTimer.cancel();

+ 38 - 11
src/com/mes/ui/WorkRecordData.java

@@ -7,9 +7,12 @@ public class WorkRecordData {
     private String id;
     private String lc;          // 炉次
     private String bc;          // 班次
-    private String type;        // 物料类型
-    private String zl;          // 重量
-    private String updateBy;    // 操作人(remarks/ucode)
+    private String yzl;         // 原铝锭重量
+    private String hzl;         // 回炉料重量
+    private String yQpZl;       // 原铝锭去皮
+    private String hQpZl;       // 回炉料去皮
+    private String hlBl;        // 回炉料比例
+    private String updateBy;    // 操作人
     private String createDate;  // 创建时间
 
     public String getId() {
@@ -36,20 +39,44 @@ public class WorkRecordData {
         this.bc = bc;
     }
 
-    public String getType() {
-        return type;
+    public String getYzl() {
+        return yzl;
     }
 
-    public void setType(String type) {
-        this.type = type;
+    public void setYzl(String yzl) {
+        this.yzl = yzl;
     }
 
-    public String getZl() {
-        return zl;
+    public String getHzl() {
+        return hzl;
     }
 
-    public void setZl(String zl) {
-        this.zl = zl;
+    public void setHzl(String hzl) {
+        this.hzl = hzl;
+    }
+
+    public String getYQpZl() {
+        return yQpZl;
+    }
+
+    public void setYQpZl(String yQpZl) {
+        this.yQpZl = yQpZl;
+    }
+
+    public String getHQpZl() {
+        return hQpZl;
+    }
+
+    public void setHQpZl(String hQpZl) {
+        this.hQpZl = hQpZl;
+    }
+
+    public String getHlBl() {
+        return hlBl;
+    }
+
+    public void setHlBl(String hlBl) {
+        this.hlBl = hlBl;
     }
 
     public String getUpdateBy() {

+ 21 - 18
src/com/mes/ui/WorkRecordPanel.java

@@ -19,7 +19,7 @@ public class WorkRecordPanel extends JPanel {
 
     private static final Logger log = LoggerFactory.getLogger(WorkRecordPanel.class);
 
-    private static final String[] COLUMN_NAMES = {"炉次", "班次", "物料类型", "重量(kg)", "操作人", "时间"};
+    private static final String[] COLUMN_NAMES = {"炉次", "班次", "原铝锭", "回炉料", "原铝锭去皮", "回炉料去皮", "回炉料比例", "操作人", "时间"};
     private static final int PAGE_SIZE = 20;
 
     private int pageNo = 1;
@@ -35,7 +35,7 @@ public class WorkRecordPanel extends JPanel {
     private JButton btnSearch;
     private JLabel statusLabel;
     private JTextField lcSearchField;
-    private JTextField typeSearchField;
+    private JTextField bcSearchField;
 
     public WorkRecordPanel() {
         initUI();
@@ -77,18 +77,18 @@ public class WorkRecordPanel extends JPanel {
         topPanel.add(lcSearchField);
         xPos += 90;
 
-        JLabel typeLabel = new JLabel("物料:");
-        typeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 13));
-        typeLabel.setBounds(xPos, 10, 40, 30);
-        topPanel.add(typeLabel);
+        JLabel bcLabel = new JLabel("班次:");
+        bcLabel.setFont(new Font("微软雅黑", Font.PLAIN, 13));
+        bcLabel.setBounds(xPos, 10, 40, 30);
+        topPanel.add(bcLabel);
         xPos += 42;
 
-        typeSearchField = new JTextField();
-        typeSearchField.setFont(new Font("微软雅黑", Font.PLAIN, 13));
-        typeSearchField.setBounds(xPos, 10, 120, 30);
-        typeSearchField.addActionListener(e -> doSearch());
-        topPanel.add(typeSearchField);
-        xPos += 130;
+        bcSearchField = new JTextField();
+        bcSearchField.setFont(new Font("微软雅黑", Font.PLAIN, 13));
+        bcSearchField.setBounds(xPos, 10, 100, 30);
+        bcSearchField.addActionListener(e -> doSearch());
+        topPanel.add(bcSearchField);
+        xPos += 110;
 
         btnSearch = new JButton("查询");
         btnSearch.setFont(new Font("微软雅黑", Font.PLAIN, 13));
@@ -181,7 +181,7 @@ public class WorkRecordPanel extends JPanel {
     }
 
     private void setColumnWidths() {
-        int[] widths = {80, 80, 120, 100, 120, 180};
+        int[] widths = {60, 60, 80, 80, 90, 90, 90, 90, 150};
         for (int i = 0; i < widths.length && i < table.getColumnCount(); i++) {
             TableColumn column = table.getColumnModel().getColumn(i);
             column.setPreferredWidth(widths[i]);
@@ -190,7 +190,7 @@ public class WorkRecordPanel extends JPanel {
 
     private void clearSearchFields() {
         lcSearchField.setText("");
-        typeSearchField.setText("");
+        bcSearchField.setText("");
     }
 
     private void doSearch() {
@@ -205,7 +205,7 @@ public class WorkRecordPanel extends JPanel {
 
     public void loadData() {
         final String lc = lcSearchField.getText().trim();
-        final String type = typeSearchField.getText().trim();
+        final String bc = bcSearchField.getText().trim();
 
         SwingWorker<WorkRecordResp, Void> worker = new SwingWorker<WorkRecordResp, Void>() {
             @Override
@@ -214,7 +214,7 @@ public class WorkRecordPanel extends JPanel {
                     statusLabel.setText("正在加载...");
                     setButtonsEnabled(false);
                 });
-                return DataUtil.getWeighRecordList(lc, type, pageNo, PAGE_SIZE);
+                return DataUtil.getWeighRecordList(lc, bc, pageNo, PAGE_SIZE);
             }
 
             @Override
@@ -262,8 +262,11 @@ public class WorkRecordPanel extends JPanel {
                 tableModel.addRow(new Object[]{
                         data.getLc(),
                         data.getBc(),
-                        data.getType(),
-                        data.getZl(),
+                        data.getYzl(),
+                        data.getHzl(),
+                        data.getYQpZl(),
+                        data.getHQpZl(),
+                        data.getHlBl(),
                         data.getUpdateBy(),
                         data.getCreateDate()
                 });

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

@@ -1,6 +1,6 @@
 mes.gw=OP240A
 mes.server_ip=127.0.0.1
-#mes.server_ip=192.168.17.170
+#mes.server_ip=10.0.20.10
 mes.line_sn=XT
 
 # Modbus-TCP 称重