|
|
@@ -88,6 +88,11 @@ public class MainFrame extends JFrame {
|
|
|
private JMenuItem deviceInfoUiItem;
|
|
|
// 界面布局子菜单(mes123解锁后显示)
|
|
|
private JMenu layoutMenu;
|
|
|
+ // 手动提交子菜单(解锁后显示;若勾选"始终显示"则不受解锁控制)
|
|
|
+ private JMenu manualSubmitMenu;
|
|
|
+ // 始终显示子菜单(解锁后显示,用于勾选哪些菜单绕过解锁)
|
|
|
+ private JMenu alwaysShowMenu;
|
|
|
+ private JCheckBoxMenuItem manualSubmitAlwaysItem;
|
|
|
// 工具栏项目显示按钮
|
|
|
private JButton projectMenu;
|
|
|
|
|
|
@@ -262,7 +267,7 @@ public class MainFrame extends JFrame {
|
|
|
featuresItem.addActionListener(e -> showFeaturesDialog());
|
|
|
projectDeviceMenu.add(featuresItem);
|
|
|
|
|
|
- deviceInfoUiItem = new JMenuItem("设备信息显示...");
|
|
|
+ deviceInfoUiItem = new JMenuItem("设备信息显示");
|
|
|
deviceInfoUiItem.setIcon(new ImageIcon(Objects.requireNonNull(getClass().getResource("/resources/image/bg/menu_setting.png"))));
|
|
|
deviceInfoUiItem.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
deviceInfoUiItem.addActionListener(e -> showDeviceInfoUiDialog());
|
|
|
@@ -300,6 +305,48 @@ public class MainFrame extends JFrame {
|
|
|
importLayoutItem.addActionListener(e -> importUILayout());
|
|
|
layoutMenu.add(importLayoutItem);
|
|
|
|
|
|
+ // ========== 子菜单:手动提交(每个工位一个菜单项) ==========
|
|
|
+ // 默认隐藏,解锁后显示;若在"始终显示"中勾选则无视解锁状态
|
|
|
+ manualSubmitMenu = new JMenu("手动提交");
|
|
|
+ manualSubmitMenu.setIcon(new ImageIcon(Objects.requireNonNull(getClass().getResource("/resources/image/bg/reset_logo.png"))));
|
|
|
+ manualSubmitMenu.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
+ manualSubmitMenu.setVisible(false);
|
|
|
+ settingMenu.add(manualSubmitMenu);
|
|
|
+
|
|
|
+ int stationCount = config.getStationCount();
|
|
|
+ for (int i = 0; i < stationCount; i++) {
|
|
|
+ final int idx = i;
|
|
|
+ StationConfig.StationInfo st = config.getStation(i);
|
|
|
+ String label = stationCount > 1
|
|
|
+ ? "手动提交 工位" + (i + 1) + (st != null ? " (" + st.getCode() + ")" : "")
|
|
|
+ : "手动提交" + (st != null ? " (" + st.getCode() + ")" : "");
|
|
|
+ JMenuItem item = new JMenuItem(label);
|
|
|
+ item.setIcon(new ImageIcon(Objects.requireNonNull(getClass().getResource("/resources/image/bg/reset_logo.png"))));
|
|
|
+ item.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
+ item.addActionListener(e -> manualEnableSubmit(idx));
|
|
|
+ manualSubmitMenu.add(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 子菜单:始终显示(管理绕过解锁的白名单) ==========
|
|
|
+ alwaysShowMenu = new JMenu("始终显示");
|
|
|
+ alwaysShowMenu.setIcon(new ImageIcon(Objects.requireNonNull(getClass().getResource("/resources/image/bg/bar_setting.png"))));
|
|
|
+ alwaysShowMenu.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
+ alwaysShowMenu.setVisible(false);
|
|
|
+ settingMenu.add(alwaysShowMenu);
|
|
|
+
|
|
|
+ manualSubmitAlwaysItem = new JCheckBoxMenuItem("手动提交",
|
|
|
+ com.mes.core.UiPrefs.getInstance().isAlwaysShow(com.mes.core.UiPrefs.KEY_MANUAL_SUBMIT));
|
|
|
+ manualSubmitAlwaysItem.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
+ manualSubmitAlwaysItem.addItemListener(e -> {
|
|
|
+ com.mes.core.UiPrefs.getInstance().setAlwaysShow(
|
|
|
+ com.mes.core.UiPrefs.KEY_MANUAL_SUBMIT, manualSubmitAlwaysItem.isSelected());
|
|
|
+ applyLockVisibility(!workflowTabVisible);
|
|
|
+ });
|
|
|
+ alwaysShowMenu.add(manualSubmitAlwaysItem);
|
|
|
+
|
|
|
+ // 初始按偏好设置一次显隐(默认锁定)
|
|
|
+ applyLockVisibility(true);
|
|
|
+
|
|
|
// 内容面板
|
|
|
contentPane = new JPanel();
|
|
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
|
@@ -669,6 +716,46 @@ public class MainFrame extends JFrame {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 手动启用指定工位的 OK/NG 按钮(救急用:设备完成信号缺失或拉铆数量未达预设时)
|
|
|
+ * 参考 OP220A:只解锁按钮,用户自行点 OK 走正常提交路径。
|
|
|
+ */
|
|
|
+ private void manualEnableSubmit(int stationIndex) {
|
|
|
+ if (stationIndex < 0 || stationIndex >= contexts.size()) {
|
|
|
+ log.warn("手动提交: 无效工位索引 {}", stationIndex);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ StationContext context = contexts.get(stationIndex);
|
|
|
+ WorkflowEngine engine = engines.get(stationIndex);
|
|
|
+
|
|
|
+ // 必须先扫码
|
|
|
+ String sn = context.getProductSn();
|
|
|
+ if (sn == null || sn.trim().isEmpty()) {
|
|
|
+ JOptionPane.showMessageDialog(this,
|
|
|
+ "请先扫描工件码再执行手动提交",
|
|
|
+ "手动提交", JOptionPane.WARNING_MESSAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.warn("[{}] 手动提交:强制启用 OK/NG 按钮 (sn={})", context.getStationCode(), sn);
|
|
|
+
|
|
|
+ // 1) 置位 UploadResultStep.canExecute 所需的全部条件
|
|
|
+ context.setQualityPassed(true);
|
|
|
+ context.setWorkStarted(true); // auto 模式下必须
|
|
|
+ context.setMaterialValidated(true); // 有物料配置时必须
|
|
|
+ context.setMaterialBound(true); // 跳过 MBDW 阶段
|
|
|
+ context.setResultUploaded(false);
|
|
|
+ context.setWaitingForUserAction(true);
|
|
|
+
|
|
|
+ // 2) 跳到 upload_result 步骤,保证 submitResult 走 "currentStep instanceof UploadResultStep" 分支
|
|
|
+ engine.jumpToStep("upload_result");
|
|
|
+
|
|
|
+ // 3) 标记按钮强制启用(面板 refresh 时绕过 auto 模式禁用逻辑;reset() 会自动清除)
|
|
|
+ context.setExtra("forceSubmitEnabled", Boolean.TRUE);
|
|
|
+ context.setStatusMessage("手动提交已启用,请点击OK完成", 0);
|
|
|
+ context.updateUI();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 提交结果
|
|
|
* 手动模式下:用户点击OK/NG后,按顺序执行 StartWorkStep -> UploadResultStep
|
|
|
*/
|
|
|
@@ -1196,11 +1283,7 @@ public class MainFrame extends JFrame {
|
|
|
workflowMonitorPanel.refresh();
|
|
|
log.info("流程监控Tab已解锁显示");
|
|
|
}
|
|
|
-
|
|
|
- // 同时显示隐藏的设置菜单项
|
|
|
- editModeSeparator.setVisible(true);
|
|
|
- projectDeviceMenu.setVisible(true);
|
|
|
- layoutMenu.setVisible(true);
|
|
|
+ applyLockVisibility(false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1212,11 +1295,27 @@ public class MainFrame extends JFrame {
|
|
|
workflowTabVisible = false;
|
|
|
log.info("流程监控Tab已隐藏");
|
|
|
}
|
|
|
-
|
|
|
- // 同时隐藏设置菜单项
|
|
|
- editModeSeparator.setVisible(false);
|
|
|
- projectDeviceMenu.setVisible(false);
|
|
|
- layoutMenu.setVisible(false);
|
|
|
+ applyLockVisibility(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据锁定状态统一应用所有"需解锁"菜单的显隐
|
|
|
+ * - locked=true 所有需解锁项默认隐藏;但"始终显示"白名单中的保留可见
|
|
|
+ * - locked=false 所有需解锁项全部可见
|
|
|
+ */
|
|
|
+ private void applyLockVisibility(boolean locked) {
|
|
|
+ boolean unlocked = !locked;
|
|
|
+ if (editModeSeparator != null) editModeSeparator.setVisible(unlocked);
|
|
|
+ if (projectDeviceMenu != null) projectDeviceMenu.setVisible(unlocked);
|
|
|
+ if (layoutMenu != null) layoutMenu.setVisible(unlocked);
|
|
|
+ if (alwaysShowMenu != null) alwaysShowMenu.setVisible(unlocked);
|
|
|
+
|
|
|
+ // 手动提交:尊重"始终显示"勾选
|
|
|
+ if (manualSubmitMenu != null) {
|
|
|
+ boolean always = com.mes.core.UiPrefs.getInstance()
|
|
|
+ .isAlwaysShow(com.mes.core.UiPrefs.KEY_MANUAL_SUBMIT);
|
|
|
+ manualSubmitMenu.setVisible(unlocked || always);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// ========== 项目切换/设备IP修改 ==========
|
|
|
@@ -1687,9 +1786,21 @@ public class MainFrame extends JFrame {
|
|
|
// 物料码输入框联动:勾了冷板或底护板 → 显示;都没勾 → 隐藏
|
|
|
boolean coldOn = Boolean.TRUE.equals(override.get("cold_plate"));
|
|
|
boolean bottomOn = Boolean.TRUE.equals(override.get("bottom_plate"));
|
|
|
+ // 拉铆流程联动:
|
|
|
+ // - 关闭 riveting: 两行(拉铆数量)都隐藏
|
|
|
+ // - 开启 riveting: 自动开启第1行;第2行保持用户设置
|
|
|
+ boolean rivetingOn = Boolean.TRUE.equals(override.get("riveting"));
|
|
|
+ Boolean row1Enabled = pc.getDeviceRow1EnabledOverride();
|
|
|
+ Boolean row2Enabled = pc.getDeviceRow2EnabledOverride();
|
|
|
+ if (!rivetingOn) {
|
|
|
+ row1Enabled = Boolean.FALSE;
|
|
|
+ row2Enabled = Boolean.FALSE;
|
|
|
+ } else {
|
|
|
+ row1Enabled = Boolean.TRUE;
|
|
|
+ }
|
|
|
pc.setDeviceInfoRowsOverride(
|
|
|
- pc.getDeviceRow1EnabledOverride(), pc.getDeviceRow1LabelOverride(),
|
|
|
- pc.getDeviceRow2EnabledOverride(), pc.getDeviceRow2LabelOverride(),
|
|
|
+ row1Enabled, pc.getDeviceRow1LabelOverride(),
|
|
|
+ row2Enabled, pc.getDeviceRow2LabelOverride(),
|
|
|
coldOn || bottomOn);
|
|
|
|
|
|
// 重新加载 yaml 配置(会按新 override 展开 steps)
|
|
|
@@ -1707,6 +1818,10 @@ public class MainFrame extends JFrame {
|
|
|
for (WorkstationPanel p : panels) {
|
|
|
p.refreshDisplayFromConfig(config);
|
|
|
}
|
|
|
+ // 若行数变化涉及组件增删,强制重载布局(与"设备信息显示"对话框保持一致)
|
|
|
+ for (WorkstationPanel p : panels) {
|
|
|
+ try { p.reloadLayoutConfig(); } catch (Exception ex) { /* 忽略 */ }
|
|
|
+ }
|
|
|
|
|
|
JOptionPane.showMessageDialog(this,
|
|
|
"工艺流程已更新,所有工位已重建",
|