Sfoglia il codice sorgente

修改只记录人员编号

callm 4 giorni fa
parent
commit
09acf839e7

+ 64 - 0
UAS_MES_YDCY/.workbuddy/memory/2026-10-10.md

@@ -196,5 +196,69 @@ private void HandleEmCode()
 ## 自检
 括号平衡:`Query_LoadMan.cs` 45/45、129/129、33/33;`Query_LoadMan.Designer.cs` 6/6、116/116、1/1 ✅
 
+---
+
+# 追加:全面移除人员名称(同日,**回退了上面绝大部分「名称」相关改动**)
+
+## 用户原话
+> Query_LoadMan修改一下不显示人员名称这些,也不用卡控人员在SOPEMPLOYEEDETAIL表中,
+> 扫描的时候人员格式也修改一下不用工号/姓名,只扫描工号,也只记录工号
+
+> ⚠️ 这条把前面几轮的「姓名」需求**整体撤销**了。原因推测:SOPEMPLOYEEDETAIL 里没有对应人员,
+> 卡控会导致真正在岗的人上不了线;扫描枪实际只输出工号,`工号/姓名` 格式是过度设计。
+
+## 改动文件
+`Query_LoadMan.cs`(+16/-84)、`Query_LoadMan.Designer.cs`(-12)——**只有这两个文件**,`git diff --stat` 已确认。
+
+## 具体删改(共 6 处)
+
+| # | 位置 | 改动 |
+|---|---|---|
+| 1 | Designer `AddRange` | 移除 `this.lm_emname` 列 |
+| 2 | Designer 列定义块 | 删掉 `lm_emname` 的 7 行属性设置 + 字段声明 |
+| 3 | `LoadGridData` SQL | 去掉 `lm.lm_emname`、`nvl(...) emname` 两列,**并删掉整个 `left join (select sed_emcode,max(sed_emname)...) se` 子查询** |
+| 4 | `DoEmCode` | 删 `SplitEmInfo` 解析、删 `SOPEMPLOYEEDETAIL` 存在性卡控;`emcode` 直接 `em_code.Text.Trim()` |
+| 5 | `DoEmCode` insert | `insert into loadman(lm_id,lm_linecode,lm_emcode,lm_uptime,lm_inman)` —— **列清单去掉 `lm_emname`**,值也随之少一项 |
+| 6 | `ConfirmDown_Click` | 删 `emname` 局部变量与其取值,提示语由 `emcode + " " + emname` 改成只 `emcode` |
+
+**整个方法删除**:`SplitEmInfo()`(37 行)——不再需要格式解析。
+
+**提示文案统一**:「人员编号」→「人员工号」(`Load` 初始提示、`UpLoadMan_CheckedChanged`、`DownLoadMan_CheckedChanged` 三处)。
+
+### 上线分支简化后
+```csharp
+string emcode = em_code.Text.Trim();     // 只取工号
+if (emcode == "") { ...红字提示... return; }
+if (UpLoadMan.Checked)
+{
+    if (linecode == "") { ...请先选择线别... return; }
+    //(原来这里有一段 SOPEMPLOYEEDETAIL 查名称 + 不存在则拦截,已整段删除)
+    DataTable dtOn = ... // 同线重复上线检查
+    dh.ExecuteSql("insert into loadman(lm_id,lm_linecode,lm_emcode,lm_uptime,lm_inman)" +
+        "values(loadman_seq.nextval,'" + linecode + "','" + emcode + "',sysdate,'" + User.UserName + "')", "insert");
+    OperateResult.AppendText("<<" + emcode + " 在" + linecode + "上线成功\n", Color.Green, em_code);
+}
+```
+下线分支同理:删掉 `downName` 那段 `getFieldDataByCondition("loadman","max(lm_emname)",...)` 兜底查询。
+
+## ⚠️ 必须提醒用户的遗留问题
+**`loadman.lm_emname` 这个 DB 列仍然存在,只是不再由本界面写入**(insert 不含该列)。
+- 若该列是 `not null` 约束,**insert 会直接报错** → 需要在库里改成允许空,或给默认值。
+  (看历史代码第 160 行原本是显式写 `lm_emname`,说明该列大概率可空,但没实际验证过。)
+- 其他界面若读 `lm_emname` 显示,会看到本界面产生的记录该列为空。
+
+## 保留未动的逻辑(用户说「只改这些」)
+- 回车双保险拦截(`em_code_KeyDown` + `Em_code_KeyPress` + `_emBusy`)
+- 批量勾选下线 + 全选/取消全选按钮
+- 自动从原线体下线再上新线体的互斥逻辑
+- 同名/已在线上 的重复上线拦截
+
+## 自检
+- 括号平衡(Python 剥字面量后):`Query_LoadMan.cs` 39/39、102/102、25/25;`Query_LoadMan.Designer.cs` 6/6、115/115、1/1 ✅
+- 残留引用检查:`lm_emname` **0 处**、`SplitEmInfo` **0 处**、`emname` **0 处**;
+  `SOPEMPLOYEEDETAIL` 只剩 2 处,**均在 `///` 文档注释里**(不是代码)→ 已确认无实际查询。
+- `git --no-pager diff --stat -- UAS_MES_YDCY/` 只有这两个文件。
+- 仍需在 VS 编译确认(本地无法编译)。
+
 
 

+ 19 - 11
UAS_MES_YDCY/.workbuddy/memory/MEMORY.md

@@ -83,17 +83,20 @@
   `Controls.Add(按钮)` 放列表**最前**(z-order 最底,不会被遮挡)。
 - **判断是否有勾选**:用 `Cells["列名"].FormattedValue.ToString() == "True"`,
   **不要用 `.Value`**——未手动点过的复选框 `.Value` 可能是 `null`,而 `FormattedValue` 已是 `"False"`。
-- **批量更新**:遍历 `DGV.Rows` 筛勾选行 → 按**主键 `lm_id`** 逐条 update(比按业务字段稳,因 DGV 只加载未下线记录),
-  逐条 try/catch 累计成功/失败数,最后汇总一行提示 + `LoadGridData()` 刷新。
+- **批量更新**:遍历 `DGV.Rows` 筛勾选行 → 按**主键**逐条 update(`Query_LoadMan` 用 `lm_id`),
+  逐条 try/catch 累计成功/失败数,最后汇总一行提示 + 刷新方法。
 - 提示输出用 **(string, Color) 两参数重载**,避开 (string,Color,Control) 重载内部 `ctl.Text=""` 误清输入框。
 - 刷新后勾选状态会因重新绑定被清空,属预期。
 - **全选按钮**(切换式):先扫一遍判断是否已全部勾选,`bool setValue = !allChecked` → 点一下全勾、再点一下全不勾;
   逐行 `Cells["列名"].Value = setValue`,再调 **`DGV.RefreshEdit()`** 让复选框立即重绘
-  (只改 cell value 不调 `RefreshEdit()` 时显示可能不刷新)。**不要顺便调 `LoadGridData()`**——全选只改界面状态,不该重新查库。
+  (只改 cell value 不调 `RefreshEdit()` 时显示可能不刷新)。**不要顺便调刷新方法**——全选只改界面状态,不该重新查库。
 - 按钮文案跟随状态切换(`"全选"` ⇄ `"取消全选"`)时,**必须同时在数据刷新方法末尾复位文案**
   (重新绑定后复选框必然清空),否则会出现「按钮写着取消全选、实际一个都没勾」的错位。
 - ⚠️ 布局坑:`RadioButton` 等 `AutoSize=true` 的控件,`Size` 属性写了也不生效,实际宽度由文本决定。
   给新按钮找位置时**不能只看 `Location`**,要按「Location.X + 实际文本宽度」估算右边界,否则会撞上。
+- ⚠️ **删除 DGV 列要同时改 3 处**:`AddRange` 数组、该列的属性设置块(`// 列名` 注释段)、
+  末尾的 `private ... 列字段;` 声明。漏任一处要么编译报错(字段不存在),要么运行期多/少一列。
+  若 `.cs` 里有 `row.Cells["列名"]` 引用该列,**必须一起删**,否则运行期抛 `ArgumentException`。
 
 ## 扫码输入框(SnCollectionBox)的回车坑 —— 只在功能界面内解决
 - `SnCollectionBox_KeyDown`(在 `SnCollectionBox.Designer.cs` 里 hook)的 Enter 分支末尾有 **`this.SelectAll()`**。
@@ -130,13 +133,16 @@
   而 `RichTextAutoBottom` 的 `InitializeComponent` 只做 `components = new Container()`,**不注册任何事件**,
   所以 `AppendText(str, Color, ctl)` 的 `ctl.Text=""` 不会重复触发扫描框回车。
 
-## 扫描格式解析:工号/人员姓名
-- 扫描枪常输出 `工号/人员姓名` 两段。分隔符集合建议 `{ "/", "\\", "/", "|", "|", " ", " ", "、" }`(半角+全角斜杠/竖线、空格、中文顿号)。
-- 用 `text.Split(sep, StringSplitOptions.RemoveEmptyEntries)` → `parts[0]` 工号、`parts[1]` 姓名。
-  ⚠️ 这个重载**不带 `TrimEntries`**(.NET Core 3.0+ 才新增),只能手动 `.Trim()`。
-- 判「格式错」的条件:**原文含分隔符,但解析后任一段为空** → 覆盖 `"/张三"`、`"E001/"`、`"E001//张三"`。
-- 扫描内容常带末尾 `\r`:**`\r` 不要放进分隔符集合**,靠第 2 段结尾的 `.Trim()` 自然清掉即可。
-- 兼容原则:**纯工号(无分隔符)走原来的查表逻辑;带姓名(有分隔符)则完全跳过查表**。
+## 扫描格式解析:工号/人员姓名(⚠️ 方案最终被用户放弃,见下)
+- ~~扫描枪常输出 `工号/人员姓名` 两段~~ —— **`Query_LoadMan` 已改回「只扫工号、只记工号」**,
+  该解析整体删除(含 `SplitEmInfo` 方法)。**不要再为新界面默认加姓名解析。**
+- 教训:**不要凭「扫描枪常见格式」自行加姓名解析和人员存在性卡控**。
+  `SOPEMPLOYEEDETAIL` 未必有全部在岗人员,卡控会让人上不了线;
+  名字属于附加信息,若用户没明确要求「显示姓名/校验人员」,就只用工号。
+- 保留此节仅因分隔符集合仍可能在别处有用:`{ "/", "\\", "/", "|", "|", " ", " ", "、" }`;
+  用 `text.Split(sep, StringSplitOptions.RemoveEmptyEntries)`(⚠️ 此重载**不带 `TrimEntries`**,.NET Core 3.0+ 才有),
+  只能手动 `.Trim()`;**`\r` 不要放进分隔符集合**,靠末段 `.Trim()` 清掉即可。
+
 
 ## 工艺路线三表关联(makeserial + craft + craftdetail)
 项目里反复出现同一组关联,记住键名可以少查:
@@ -181,7 +187,9 @@
   - **`字段` 参数可传聚合表达式**(如 `"max(sed_emname)"`),一次查询同时完成「校验存在」+「取名称」:
     无记录时返回 `DBNull`,`DBNull.ToString() == ""`,判空即可覆盖两种情况,可替代 `CheckExist`。
 - 表命名:工序表 `step`(`st_code`/`st_name`),工序类型表 `steptype`(`STP_CODE`/`STP_NAME`,注意是 STP_ 前缀)。
-- 员工上下线表 `loadman`:`LM_ID`(`loadman_seq.nextval`)/`LM_LINECODE`/`LM_EMCODE`/`LM_EMNAME`/`LM_UPTIME`/`LM_DOWNTIME`/`LM_INMAN`;同构的 `loadmake`(工单上下线)有现成界面 `Query_LoadMake` 可作模板。在线判定 = `lm_downtime is null`。
+- 员工上下线表 `loadman`:`LM_ID`(`loadman_seq.nextval`)/`LM_LINECODE`/`LM_EMCODE`/`LM_UPTIME`/`LM_DOWNTIME`/`LM_INMAN`;
+  `LM_EMNAME` 列仍存在但 **`Query_LoadMan` 已不再写入**(只记工号)。
+  同构的 `loadmake`(工单上下线)有现成界面 `Query_LoadMake` 可作模板。在线判定 = `lm_downtime is null`。
 - 人员名称来源 `SOPEMPLOYEEDETAIL`(`sed_emcode`/`sed_emname`):**同一 `sed_emcode` 可能多条**,取名称统一用 `max(sed_emname)` + `group by sed_emcode` 去重。
 - SQL 多为拼字符串 + Oracle 函数(`nvl`、`ROWNUM`、`DUAL`)。
 - **操作日志表 `commandlog`**:统一调 `LogicHandler.DoCommandLog(caller, userCode, makeCode, lineCode, sourceCode, operate, result, sncode, checkno)`(`UAS_MES_NEW.PublicMethod`),内部固定 insert + `commandlog_seq.nextval` + `sysdate`,调用方不传 ID/时间。惯例:`Tag.ToString(), User.UserCode, 工单号, User.UserLineCode, User.UserSourceCode, "操作名", "结果", sncode, ""`。

+ 0 - 12
UAS_MES_YDCY/FunctionCode/Query/Query_LoadMan.Designer.cs

@@ -34,7 +34,6 @@ namespace UAS_MES_NEW.Query
             this.choose = new System.Windows.Forms.DataGridViewCheckBoxColumn();
             this.lm_id = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.lm_emcode = new System.Windows.Forms.DataGridViewTextBoxColumn();
-            this.lm_emname = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.lm_linecode = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.lm_uptime = new System.Windows.Forms.DataGridViewTextBoxColumn();
             this.lm_inman = new System.Windows.Forms.DataGridViewTextBoxColumn();
@@ -172,7 +171,6 @@ namespace UAS_MES_NEW.Query
             this.choose,
             this.lm_id,
             this.lm_emcode,
-            this.lm_emname,
             this.lm_linecode,
             this.lm_uptime,
             this.lm_inman});
@@ -209,15 +207,6 @@ namespace UAS_MES_NEW.Query
             this.lm_emcode.ReadOnly = true;
             this.lm_emcode.Width = 180;
             //
-            // lm_emname
-            //
-            this.lm_emname.DataPropertyName = "lm_emname";
-            this.lm_emname.HeaderText = "人员名称";
-            this.lm_emname.MinimumWidth = 10;
-            this.lm_emname.Name = "lm_emname";
-            this.lm_emname.ReadOnly = true;
-            this.lm_emname.Width = 120;
-            //
             // lm_linecode
             //
             this.lm_linecode.DataPropertyName = "lm_linecode";
@@ -294,7 +283,6 @@ namespace UAS_MES_NEW.Query
         private System.Windows.Forms.DataGridViewCheckBoxColumn choose;
         private System.Windows.Forms.DataGridViewTextBoxColumn lm_id;
         private System.Windows.Forms.DataGridViewTextBoxColumn lm_emcode;
-        private System.Windows.Forms.DataGridViewTextBoxColumn lm_emname;
         private System.Windows.Forms.DataGridViewTextBoxColumn lm_linecode;
         private System.Windows.Forms.DataGridViewTextBoxColumn lm_uptime;
         private System.Windows.Forms.DataGridViewTextBoxColumn lm_inman;

+ 16 - 72
UAS_MES_YDCY/FunctionCode/Query/Query_LoadMan.cs

@@ -33,7 +33,7 @@ namespace UAS_MES_NEW.Query
             li_code.Condition = "li_statuscode='AUDITED'";
             li_code.DbChange += Li_code_DbChange;
             //初始提示
-            OperateResult.AppendText(">>请选择线别,输入人员编号后回车执行" + (UpLoadMan.Checked ? "上线" : "下线") + ";下线也可勾选列表后点\"确认下线\"批量处理\n", Color.Black);
+            OperateResult.AppendText(">>请选择线别,输入人员工号后回车执行" + (UpLoadMan.Checked ? "上线" : "下线") + ";下线也可勾选列表后点\"确认下线\"批量处理\n", Color.Black);
             LoadGridData();
             em_code.Focus();
         }
@@ -53,8 +53,8 @@ namespace UAS_MES_NEW.Query
         }
 
         /// <summary>
-        /// 人员编号输入框,回车后按选中的模式执行上线/下线
-        /// 兼容两种输入格式:①只输入工号(名称从 SOPEMPLOYEEDETAIL 查) ②扫描/输入「工号/人员姓名」(直接解析,不再查表)
+        /// 人员工号输入框,回车后按选中的模式执行上线/下线
+        /// 只接受工号,不解析姓名,也不校验人员是否存在于 SOPEMPLOYEEDETAIL
         /// </summary>
         private void em_code_KeyDown(object sender, KeyEventArgs e)
         {
@@ -106,17 +106,11 @@ namespace UAS_MES_NEW.Query
         private void DoEmCode()
         {
             string linecode = li_code.Text.Trim();
-            string emcode = "";
-            string emname = "";
-            //解析输入内容:扫描枪输出「工号/人员姓名」两段格式,手工输入则只有工号
-            if (!SplitEmInfo(em_code.Text, out emcode, out emname))
-            {
-                OperateResult.AppendText("<<扫描内容格式有误,应为「工号/人员姓名」\n", Color.Red, em_code);
-                return;
-            }
+            //只取工号:扫描枪或手工输入均只记工号,不做姓名解析
+            string emcode = em_code.Text.Trim();
             if (emcode == "")
             {
-                OperateResult.AppendText("<<人员编号不能为空\n", Color.Red, em_code);
+                OperateResult.AppendText("<<人员工号不能为空\n", Color.Red, em_code);
                 return;
             }
             if (UpLoadMan.Checked)
@@ -127,19 +121,6 @@ namespace UAS_MES_NEW.Query
                     OperateResult.AppendText("<<请先选择线别\n", Color.Red, li_code);
                     return;
                 }
-                //上线:扫描格式已带姓名则直接用;只输入工号时才去 SOPEMPLOYEEDETAIL 取名称
-                if (emname == "")
-                {
-                    //同一 sed_emcode 可能多条,取最大值聚合
-                    emname = dh.getFieldDataByCondition("SOPEMPLOYEEDETAIL", "max(sed_emname)", "sed_emcode='" + emcode + "'").ToString().Trim();
-                    if (emname == "")
-                    {
-                        OperateResult.AppendText("<<" + emcode + "人员编号不存在\n", Color.Red, em_code);
-                        em_code.Clear();
-                        em_code.Focus();
-                        return;
-                    }
-                }
                 //一个人只能同时一条线上线:若已在别的线体上线,先把原线体自动下线,再在新线体上线
                 DataTable dtOn = (DataTable)dh.ExecuteSql("select lm_linecode from loadman where lm_emcode='" + emcode + "' and lm_downtime is null", "select");
                 if (dtOn.Rows.Count > 0)
@@ -157,9 +138,9 @@ namespace UAS_MES_NEW.Query
                     dh.ExecuteSql("update loadman set lm_downtime=sysdate where lm_emcode='" + emcode + "' and lm_downtime is null", "update");
                     OperateResult.AppendText(">>" + emcode + "已从" + oldLineCode + "自动下线\n", Color.Black);
                 }
-                dh.ExecuteSql("insert into loadman(lm_id,lm_linecode,lm_emcode,lm_emname,lm_uptime,lm_inman)" +
-                    "values(loadman_seq.nextval,'" + linecode + "','" + emcode + "','" + emname + "',sysdate,'" + User.UserName + "')", "insert");
-                OperateResult.AppendText("<<" + emcode + " " + emname + " 在" + linecode + "上线成功\n", Color.Green, em_code);
+                dh.ExecuteSql("insert into loadman(lm_id,lm_linecode,lm_emcode,lm_uptime,lm_inman)" +
+                    "values(loadman_seq.nextval,'" + linecode + "','" + emcode + "',sysdate,'" + User.UserName + "')", "insert");
+                OperateResult.AppendText("<<" + emcode + " 在" + linecode + "上线成功\n", Color.Green, em_code);
             }
             else
             {
@@ -173,10 +154,7 @@ namespace UAS_MES_NEW.Query
                     return;
                 }
                 dh.ExecuteSql("update loadman set lm_downtime=sysdate where lm_emcode='" + emcode + "' and lm_downtime is null", "update");
-                //姓名优先取扫描解析出的,否则用 loadman 里记录的名称
-                string downName = emname == "" ? dh.getFieldDataByCondition("loadman", "max(lm_emname)",
-                    "lm_emcode='" + emcode + "' and lm_downtime is null").ToString().Trim() : emname;
-                OperateResult.AppendText("<<" + emcode + (downName == "" ? "" : " " + downName) + " 已从"
+                OperateResult.AppendText("<<" + emcode + " 已从"
                     + dtOn.Rows[0]["lm_linecode"].ToString() + "下线\n", Color.Green, em_code);
             }
             //数据变更后刷新
@@ -185,34 +163,6 @@ namespace UAS_MES_NEW.Query
             em_code.Focus();
         }
 
-        /// <summary>
-        /// 解析人员输入内容,兼容两种格式:
-        /// ①「工号/人员姓名」(扫描枪常用格式,分隔符支持 / \ 全角/ 竖线 | ,也兼容空格和中文顿号) → 工号与姓名都带出
-        /// ②只有工号(手工输入) → 姓名返回空串,由调用方决定是否去 SOPEMPLOYEEDETAIL 查
-        /// 分隔符在首尾或出现多次时视为格式错误,返回 false
-        /// </summary>
-        private bool SplitEmInfo(string input, out string emcode, out string emname)
-        {
-            emcode = "";
-            emname = "";
-            if (input == null)
-                return true;
-            string text = input.Trim();
-            if (text == "")
-                return true;
-            string[] sep = new string[] { "/", "\\", "/", "|", "|", " ", " ", "、" };
-            string[] parts = text.Split(sep, StringSplitOptions.RemoveEmptyEntries);
-            if (parts.Length == 0)
-                return true;
-            emcode = parts[0].Trim();
-            if (parts.Length > 1)
-                emname = parts[1].Trim();
-            //带分隔符却没解析出两段,说明格式不对(如以分隔符开头或多余分隔符)
-            if (text.IndexOfAny(new char[] { '/', '\\', '/', '|', '|', ' ', ' ', '、' }) >= 0 && (emcode == "" || emname == ""))
-                return false;
-            return true;
-        }
-
         /// <summary>
         /// 全选/取消全选(切换式):点击时若已全部勾选则全部取消,否则全部勾选
         /// 只操作复选框单元格的值,不触发数据刷新
@@ -274,7 +224,6 @@ namespace UAS_MES_NEW.Query
             DataGridViewRow row;
             string lmId;
             string emcode;
-            string emname;
             string linecode;
             int sucCount = 0;
             int failCount = 0;
@@ -288,18 +237,17 @@ namespace UAS_MES_NEW.Query
                     continue;
                 lmId = row.Cells["lm_id"].Value.ToString();
                 emcode = row.Cells["lm_emcode"].Value == null ? "" : row.Cells["lm_emcode"].Value.ToString();
-                emname = row.Cells["lm_emname"].Value == null ? "" : row.Cells["lm_emname"].Value.ToString();
                 linecode = row.Cells["lm_linecode"].Value == null ? "" : row.Cells["lm_linecode"].Value.ToString();
                 try
                 {
                     dh.ExecuteSql("update loadman set lm_downtime=sysdate where lm_id='" + lmId + "' and lm_downtime is null", "update");
                     sucCount++;
-                    OperateResult.AppendText("<<" + emcode + " " + emname + " 已从" + linecode + "下线\n", Color.Green);
+                    OperateResult.AppendText("<<" + emcode + " 已从" + linecode + "下线\n", Color.Green);
                 }
                 catch (Exception ex)
                 {
                     failCount++;
-                    OperateResult.AppendText("<<" + emcode + " " + emname + " 下线失败:" + ex.Message + "\n", Color.Red);
+                    OperateResult.AppendText("<<" + emcode + " 下线失败:" + ex.Message + "\n", Color.Red);
                 }
             }
             OperateResult.AppendText(">>本次下线成功 " + sucCount + " 人" + (failCount > 0 ? ",失败 " + failCount + " 人" : "") + "\n", Color.Black);
@@ -312,7 +260,7 @@ namespace UAS_MES_NEW.Query
         {
             if (UpLoadMan.Checked)
             {
-                OperateResult.AppendText(">>已切换到上线模式,输入人员编号回车上线\n", Color.Black);
+                OperateResult.AppendText(">>已切换到上线模式,输入人员工号回车上线\n", Color.Black);
                 em_code.Focus();
             }
         }
@@ -321,23 +269,19 @@ namespace UAS_MES_NEW.Query
         {
             if (DownLoadMan.Checked)
             {
-                OperateResult.AppendText(">>已切换到下线模式,输入人员编号回车下线,或勾选列表后点\"确认下线\"批量下线\n", Color.Black);
+                OperateResult.AppendText(">>已切换到下线模式,输入人员工号回车下线,或勾选列表后点\"确认下线\"批量下线\n", Color.Black);
                 em_code.Focus();
             }
         }
 
         /// <summary>
         /// 刷新DGV:只取未下线的人员,已选线别时只显示当前线别
-        /// 人员名称直接取 loadman.lm_emname(上线时已写入),不再关联 SOPEMPLOYEEDETAIL;
-        /// 兼容历史数据:lm_emname 为空时才回退到 SOPEMPLOYEEDETAIL 取名称
-        /// (SOPEMPLOYEEDETAIL 同一 sed_emcode 可能有多条,先按其聚合去重;上线时间 to_char 到秒)
+        /// 只显示工号,不关联 SOPEMPLOYEEDETAIL(上线时间 to_char 到秒)
         /// </summary>
         private void LoadGridData()
         {
-            string sql = "select lm.lm_id,lm.lm_linecode,lm.lm_emcode,lm.lm_emname,"
-                + "nvl(lm.lm_emname,se.sed_emname) emname,"
+            string sql = "select lm.lm_id,lm.lm_linecode,lm.lm_emcode,"
                 + "to_char(lm.lm_uptime,'yyyy-mm-dd hh24:mi:ss') lm_uptime,lm.lm_inman from loadman lm"
-                + " left join (select sed_emcode,max(sed_emname) sed_emname from SOPEMPLOYEEDETAIL group by sed_emcode) se on lm.lm_emcode=se.sed_emcode"
                 + " where lm.lm_downtime is null";
             if (li_code.Text != "")
                 sql += " and lm.lm_linecode='" + li_code.Text + "'";