Explorar o código

优化控件,人员上线功能优化

callm hai 3 semanas
pai
achega
5cafd8288a

+ 14 - 2
UAS_MES_YDCY/.workbuddy/memory/2026-09-18.md

@@ -12,8 +12,20 @@
   - 人员编号:`SnCollectionBox em_code`,KeyDown Enter 分支执行(项目统一扫码范式)。
   - RadioButton 上线(默认)/下线,CheckedChanged 切换模式提示。
 - 业务规则:
-  - 上线:**先校验人员编号存在于 `SOPEMPLOYEEDETAIL`(`sed_emcode`),不存在则提示"人员编号不存在"并拒绝**;再查 `lm_emcode + lm_downtime is null`,已存在则提示其所在线别并拒绝(一人只能同时一条线);通过后 insert(lm_id=loadman_seq.nextval, lm_uptime=sysdate, lm_inman=User.UserName)。`SOPEMPLOYEEDETAIL` 是用户提供的表(项目内无既有引用),下线不做人存在性校验。
+  - 上线:**必须选择线别**;**先校验人员编号存在于 `SOPEMPLOYEEDETAIL`(`sed_emcode`),不存在则提示"人员编号不存在"并拒绝**;再查 `lm_emcode + lm_downtime is null`,已存在则提示其所在线别并拒绝(一人只能同时一条线);通过后 insert(lm_id=loadman_seq.nextval, lm_uptime=sysdate, lm_inman=User.UserName)。`SOPEMPLOYEEDETAIL` 是用户提供的表(项目内无既有引用),下线不做人存在性校验。
+  - 下线:**不需要选择线别**("线别必选"校验只在上线分支内),按人员编号直接下掉其唯一在线记录;线别下拉仅影响 DGV 过滤显示。
   - 下线:按人员编号(不限线别,一人最多一条在线记录)`update loadman set lm_downtime=sysdate`;无在线记录则提示。
-  - DGV:`from loadman lm left join SOPEMPLOYEEDETAIL se on lm.lm_emcode=se.sed_emcode`,取 `sed_emname` 作为「人员名称」列;`where lm.lm_downtime is null [and lm.lm_linecode=当前线别] order by lm.lm_uptime desc`;线别 DbChange、上线/下线成功后均调用 LoadGridData 刷新。
+  - DGV:`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`——**SOPEMPLOYEEDETAIL 同一 sed_emcode 会有多条记录,必须先子查询聚合去重再 join,否则 DGV 出重复行**;时间列 `to_char(lm_uptime,'yyyy-mm-dd hh24:mi:ss')` 显示到秒;`where lm.lm_downtime is null [and lm.lm_linecode=当前线别] order by lm.lm_uptime desc`;线别 DbChange、上线/下线成功后均调用 LoadGridData 刷新。
 - **发现的模板 bug**:Query_LoadMake 里 `li_code.DbChange` 与 `ma_code.DbChange` 共用一个 handler 且固定读 `ma_code.ReturnData`——线别触发时读到的是工单数据。新代码 handler 改读对应控件(`li_code.ReturnData`)。
 - 菜单:需在 `CS$SYSNAVATION` 插 `sn_classname='Query.Query_LoadMan'`,`CS$USERGROUPPOWER` 授权;代码侧无需改动。
+
+## 修复共享控件 SearchTextBox 内部布局(CustomControl/TextBoxWithIcon)
+
+- 问题:控件被拉高(如 Query_LoadMan/Query_LoadMake 里的 282x46)后,内部单行 TextBox 高度锁死为字体高、`Dock=Left` 把 Top 锁在 0,放大镜图标 16px 顶对齐 → 内容挤在上半部、下方大片留白;原 `SizeChanged` 只调宽度不管垂直位置。
+- 修复(向后兼容,25+ 界面共用):
+  - `TextBox` 去掉 `Dock=Left`(否则 Dock 布局会覆盖 Top 调整);
+  - `Search_Icon` 加 `SizeMode=CenterImage` + `BackColor=Transparent`(`Dock=Right` 撑满高度后图标垂直居中,`ClickPicBox : PictureBox` 支持 SizeMode);
+  - 宽度调整与垂直居中统一抽成 `AdjustLayout()`:`TextBox.Width = Width - 图标宽 - 3`,`Top = (Height - TextBox.Height)/2`(负值取 0);`Load`(字体应用后高度才确定)和 `SizeChanged` 都调用。
+- 默认小尺寸(204x21)用法行为几乎不变;只有拉高后的界面观感变化(内容居中)。
+- `MaCodeSearchTextBox` 内部是同样的结构(同样的 Dock + 只调宽度问题),独立控件未修改,待确认是否同修。
+- **Query_LoadMan 首行对齐二次修正**:两个输入框白框高度不一致的根源是字体——SearchTextBox 内部 TextBox 继承控件 Font(原 9F,框高约 22px),SnCollectionBox 是 14F 单行框(约 30px)。把 `li_code.Font` 改为 14F 后两者框高一致;首行全部按中心线 y=50 重排(label top=34、li_code top=27[控件高46]、em_code top=35[单行约30]、RadioButton top=34[高32])。经验:**SearchTextBox 拉高使用时,Font 要和相邻输入框一致,否则内部白框高度不同**。

+ 3 - 2
UAS_MES_YDCY/CustomControl/TextBoxWithIcon/SearchTextBox.Designer.cs

@@ -36,12 +36,14 @@
             // Search_Icon
             // 
             this.Search_Icon.AllPower = null;
+            this.Search_Icon.BackColor = System.Drawing.Color.Transparent;
             this.Search_Icon.Cursor = System.Windows.Forms.Cursors.Hand;
             this.Search_Icon.Dock = System.Windows.Forms.DockStyle.Right;
             this.Search_Icon.Image = global::UAS_MES_NEW.Properties.Resources.search_16px_1202802_easyicon_net;
             this.Search_Icon.Location = new System.Drawing.Point(183, 0);
             this.Search_Icon.Name = "Search_Icon";
             this.Search_Icon.Power = "";
+            this.Search_Icon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
             this.Search_Icon.Size = new System.Drawing.Size(21, 21);
             this.Search_Icon.TabIndex = 1;
             this.Search_Icon.TabStop = false;
@@ -51,12 +53,11 @@
             // 
             this.TextBox.AllPower = null;
             this.TextBox.BackColor = System.Drawing.Color.White;
-            this.TextBox.Dock = System.Windows.Forms.DockStyle.Left;
             this.TextBox.ID = null;
             this.TextBox.Location = new System.Drawing.Point(0, 0);
             this.TextBox.Name = "TextBox";
             this.TextBox.Power = null;
-            this.TextBox.Size = new System.Drawing.Size(178, 35);
+            this.TextBox.Size = new System.Drawing.Size(178, 21);
             this.TextBox.Str = null;
             this.TextBox.Str1 = null;
             this.TextBox.Str2 = null;

+ 13 - 0
UAS_MES_YDCY/CustomControl/TextBoxWithIcon/SearchTextBox.cs

@@ -314,11 +314,24 @@ namespace UAS_MES_NEW.CustomControl.TextBoxWithIcon
                 TextBox.BackColor = System.Drawing.Color.White;
             TextBox.Enabled = TextBoxEnable1;
             Search_Icon.Power = this.Power;
+            //字体应用后文本框实际高度才确定,加载时先做一次布局
+            AdjustLayout();
         }
 
         private void SearchTextBox_SizeChanged(object sender, EventArgs e)
+        {
+            AdjustLayout();
+        }
+
+        /// <summary>
+        /// 调整内部布局:文本框宽度留出放大镜位置;单行文本框高度由字体决定,
+        /// 控件被拉高时把文本框与放大镜垂直居中,避免下方留白
+        /// </summary>
+        private void AdjustLayout()
         {
             TextBox.Width = this.Width - Search_Icon.Width - 3;
+            int top = (this.Height - TextBox.Height) / 2;
+            TextBox.Top = top > 0 ? top : 0;
         }
 
         public void GetData()

+ 7 - 7
UAS_MES_YDCY/FunctionCode/Query/Query_LoadMan.Designer.cs

@@ -49,7 +49,7 @@ namespace UAS_MES_NEW.Query
             //
             this.linecode_label.AutoSize = true;
             this.linecode_label.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.linecode_label.Location = new System.Drawing.Point(24, 38);
+            this.linecode_label.Location = new System.Drawing.Point(24, 34);
             this.linecode_label.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
             this.linecode_label.Name = "linecode_label";
             this.linecode_label.Size = new System.Drawing.Size(64, 31);
@@ -62,9 +62,9 @@ namespace UAS_MES_NEW.Query
             this.li_code.Caller = null;
             this.li_code.Condition = null;
             this.li_code.DBTitle = "";
-            this.li_code.Font = new System.Drawing.Font("微软雅黑", 9F);
+            this.li_code.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.li_code.FormName = null;
-            this.li_code.Location = new System.Drawing.Point(96, 31);
+            this.li_code.Location = new System.Drawing.Point(96, 27);
             this.li_code.Margin = new System.Windows.Forms.Padding(6);
             this.li_code.Name = "li_code";
             this.li_code.Power = "";
@@ -80,7 +80,7 @@ namespace UAS_MES_NEW.Query
             //
             this.emcode_label.AutoSize = true;
             this.emcode_label.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.emcode_label.Location = new System.Drawing.Point(408, 38);
+            this.emcode_label.Location = new System.Drawing.Point(408, 34);
             this.emcode_label.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
             this.emcode_label.Name = "emcode_label";
             this.emcode_label.Size = new System.Drawing.Size(94, 31);
@@ -93,7 +93,7 @@ namespace UAS_MES_NEW.Query
             this.em_code.BackColor = System.Drawing.Color.White;
             this.em_code.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
             this.em_code.ID = null;
-            this.em_code.Location = new System.Drawing.Point(532, 34);
+            this.em_code.Location = new System.Drawing.Point(532, 35);
             this.em_code.Margin = new System.Windows.Forms.Padding(4);
             this.em_code.Name = "em_code";
             this.em_code.Power = null;
@@ -106,7 +106,7 @@ namespace UAS_MES_NEW.Query
             this.UpLoadMan.AutoSize = true;
             this.UpLoadMan.Checked = true;
             this.UpLoadMan.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.UpLoadMan.Location = new System.Drawing.Point(800, 38);
+            this.UpLoadMan.Location = new System.Drawing.Point(800, 34);
             this.UpLoadMan.Margin = new System.Windows.Forms.Padding(4);
             this.UpLoadMan.Name = "UpLoadMan";
             this.UpLoadMan.Size = new System.Drawing.Size(76, 32);
@@ -120,7 +120,7 @@ namespace UAS_MES_NEW.Query
             //
             this.DownLoadMan.AutoSize = true;
             this.DownLoadMan.Font = new System.Drawing.Font("微软雅黑", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.DownLoadMan.Location = new System.Drawing.Point(912, 38);
+            this.DownLoadMan.Location = new System.Drawing.Point(912, 34);
             this.DownLoadMan.Margin = new System.Windows.Forms.Padding(4);
             this.DownLoadMan.Name = "DownLoadMan";
             this.DownLoadMan.Size = new System.Drawing.Size(76, 32);

+ 11 - 8
UAS_MES_YDCY/FunctionCode/Query/Query_LoadMan.cs

@@ -61,13 +61,7 @@ namespace UAS_MES_NEW.Query
                 return;
             string linecode = li_code.Text.Trim();
             string emcode = em_code.Text.Trim();
-            //限制一:线别必选
-            if (linecode == "")
-            {
-                OperateResult.AppendText("<<请先选择线别\n", Color.Red, li_code);
-                return;
-            }
-            //限制二:人员编号不能为空
+            //限制:人员编号不能为空
             if (emcode == "")
             {
                 OperateResult.AppendText("<<人员编号不能为空\n", Color.Red, em_code);
@@ -75,6 +69,12 @@ namespace UAS_MES_NEW.Query
             }
             if (UpLoadMan.Checked)
             {
+                //上线:必须选择线别
+                if (linecode == "")
+                {
+                    OperateResult.AppendText("<<请先选择线别\n", Color.Red, li_code);
+                    return;
+                }
                 //上线:先校验人员编号存在于 SOPEMPLOYEEDETAIL
                 if (!dh.CheckExist("SOPEMPLOYEEDETAIL", "sed_emcode='" + emcode + "'"))
                 {
@@ -136,10 +136,13 @@ namespace UAS_MES_NEW.Query
 
         /// <summary>
         /// 刷新DGV:只取未下线的人员,已选线别时只显示当前线别;按 lm_emcode 关联 SOPEMPLOYEEDETAIL 取人员名称
+        /// (SOPEMPLOYEEDETAIL 同一 sed_emcode 可能有多条,先按其聚合去重再关联;上线时间 to_char 到秒)
         /// </summary>
         private void LoadGridData()
         {
-            string sql = "select lm.lm_id,lm.lm_linecode,lm.lm_emcode,se.sed_emname,lm.lm_uptime,lm.lm_inman from loadman lm left join SOPEMPLOYEEDETAIL se on lm.lm_emcode=se.sed_emcode where lm.lm_downtime is null";
+            string sql = "select lm.lm_id,lm.lm_linecode,lm.lm_emcode,se.sed_emname,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 + "'";
             sql += " order by lm.lm_uptime desc";

+ 3 - 3
UAS_MES_YDCY/UAS_MES_YDCY.csproj

@@ -2201,6 +2201,9 @@
     <EmbeddedResource Include="FunctionCode\Query\Query_ExeProgress.resx">
       <DependentUpon>Query_ExeProgress.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="FunctionCode\Query\Query_LoadMan.resx">
+      <DependentUpon>Query_LoadMan.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="FunctionCode\Query\Query_MakeInf.resx">
       <DependentUpon>Query_MakeInf.cs</DependentUpon>
       <SubType>Designer</SubType>
@@ -2220,9 +2223,6 @@
     <EmbeddedResource Include="FunctionCode\Query\Query_LoadMake.resx">
       <DependentUpon>Query_LoadMake.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="FunctionCode\Query\Query_LoadMan.resx">
-      <DependentUpon>Query_LoadMan.cs</DependentUpon>
-    </EmbeddedResource>
     <EmbeddedResource Include="FunctionCode\Query\Query_RFIDPrint.resx">
       <DependentUpon>Query_RFIDPrint.cs</DependentUpon>
     </EmbeddedResource>