feat(node): refine console layout and tray status
This commit is contained in:
parent
aba93d6d0b
commit
efcf06bf24
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
- 修复国际旗舰模型输出思考过程时偶尔无法及时停止的问题;即使模型暂时没有返回新的流式片段,点击“停止”也会迅速中断当前回答。
|
||||
|
||||
- Windows Node 主窗口改为简洁的单层自适应布局:移除固定宽度与重复卡片边框,窗口缩放时内容和页签会随可用宽度调整,专业软件的状态与操作也会在窄窗口中自然换行;能力概览按软件归并,不再为同一软件或同名能力重复显示名称。Origin、ANSYS、Blender 均可手工选择位置,Origin 自动检测也会在 COM 路径无效时继续查找注册表和标准安装目录。
|
||||
- Windows Node 主窗口改为简洁的单层自适应布局:顶部只保留产品名与节点状态,移除固定宽度、重复卡片边框和说明性大标题;默认窗口适当增高,缩放时内容和页签会随可用宽度调整,专业软件的状态与操作也会在窄窗口中自然换行。可用软件按名称归并,不再重复显示同一软件或能力;托盘右键菜单中的长状态也会自动截断,不再把菜单横向撑宽。Origin、ANSYS、Blender 均可手工选择位置,Origin 自动检测也会在 COM 路径无效时继续查找注册表和标准安装目录。
|
||||
|
||||
- Windows Node 从托盘退出时会保护已有任务:可以停止接单并等待任务完成后退出,也可以经二次确认取消任务并终止对应的软件进程,不再直接关闭节点而留下状态不明的任务。
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
- **08-21 / Unreleased / Blender 多视图与剖切 v2**:以 `blender.scene.author@v2` 直接替换 v1,目标节点为 Blender 5.2 LTS;`rotary_kiln` 一次建模后可连续渲染等轴测、侧视、窑头、窑尾、纵向剖切和横截面,完整工程保持未剖切状态;固定等轴测预览外,其他选定 PNG 可动态自动回传,GLB 排除仅供剖切渲染的辅助几何。专业软件提交工具改为区分缺失参数与合法空数组,允许 Blender 这类无输入、无额外导出请求的纯生成任务进入合同校验;90 项 Blender/合同/Job/Node/预览专项 unittest、.NET build、独立 adapter 打包和 Blender 3.6.12 兼容烟测通过,全量 698 项仍仅 3 个既有数据库集成模块因显式测试库缺少 `users` 表未通过(另跳过 4 项),目标节点 5.2 真机验收待部署后执行,未连接或迁移生产数据库。
|
||||
|
||||
- **08-21 / Unreleased / Windows Node 软件地址选择、Origin 检测与自适应界面**:专业软件保留一层带边界的独立配置行和通栏只读地址框,Origin、ANSYS、Blender 均可手选位置。Origin 自动检测由单一 COM 路径扩展为 COM、卸载注册表和标准目录回退,手选的 `Origin*.exe` 同时用于 Worker 版本识别,COM 执行健康仍由 probe 独立校验。主窗口移除固定宽度居中容器和普通内容卡片边框,改为单层全宽页面;页签使用 WinForms 内置 `FillToRight` 模式跟随窗口调整,避免手工尺寸回调递归触发布局栈溢出;软件状态与操作分行并允许按钮自然换行,能力概览按软件与能力名称归并旧、新 adapter 的重复文案。Windows Node 23 项源码 unittest、.NET build、启动烟测与 diff 检查通过,无 DB、schema、HTTP API、依赖或运行方式变化。
|
||||
- **08-21 / Unreleased / Windows Node 软件地址选择、Origin 检测与自适应界面**:专业软件保留一层带边界的独立配置行和通栏只读地址框,Origin、ANSYS、Blender 均可手选位置。Origin 自动检测由单一 COM 路径扩展为 COM、卸载注册表和标准目录回退,手选的 `Origin*.exe` 同时用于 Worker 版本识别,COM 执行健康仍由 probe 独立校验。主窗口移除固定宽度居中容器、普通内容卡片边框和重复说明标题,顶部压缩为产品名与状态单行,默认高度增至 1050;页签使用 WinForms 内置 `FillToRight` 模式跟随窗口调整,软件状态与操作分行并允许按钮自然换行,可用软件按名称归并旧、新 adapter 的重复文案。托盘右键状态规范为单行并在 24 字符处省略,完整信息继续在主窗口显示,托盘悬浮保留较长摘要。Windows Node 23 项源码 unittest、.NET build、启动烟测与 diff 检查通过,无 DB、schema、HTTP API、依赖或运行方式变化。
|
||||
|
||||
- **08-20 / Unreleased / Windows Node 专业软件独立配置与 runtime 安装**:主窗口新增 Origin、ANSYS Mechanical 2024 R2、Blender 软件卡,分别显示应用位置来源和受管 runtime 状态;三种软件均可由 UI 选择自定义位置,清除后按各自的环境变量、COM、卸载注册表、PATH 或标准目录自动检测。每个软件可单独创建或更新隔离的 Python 3.12 runtime,安装只使用内置 runtime 定义与固定 requirements,拒绝活动任务期间替换,并先在临时目录完成后再切换;配置后的路径由 Host 作为固定子进程环境传给 Worker,任务请求仍不能提供路径或命令。移除重复承担软件安装和开机启动的统一 BAT,发布包直接运行 EXE,当前账号的开机启动也完全由 UI 管理;全新节点默认使用可写的 `%LocalAppData%` 数据根目录,已有 `%ProgramData%` 节点原位兼容。
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ class WindowsNodeSourceTests(unittest.TestCase):
|
|||
|
||||
def test_configuration_window_is_resizable_and_dpi_safe(self) -> None:
|
||||
form = (PROJECT / "ConfigurationForm.cs").read_text(encoding="utf-8")
|
||||
self.assertIn("ClientSize = new Size(1080, 720)", form)
|
||||
self.assertIn("ClientSize = new Size(1080, 1050)", form)
|
||||
self.assertIn("MinimumSize = new Size(760, 560)", form)
|
||||
self.assertIn("FormBorderStyle.Sizable", form)
|
||||
self.assertIn("AutoScaleMode.Dpi", form)
|
||||
|
|
@ -210,7 +210,10 @@ class WindowsNodeSourceTests(unittest.TestCase):
|
|||
self.assertIn("Appearance = TabAppearance.FlatButtons", form)
|
||||
self.assertNotIn("protected override void OnResize", form)
|
||||
self.assertIn("tab.Controls.Add(content)", form)
|
||||
self.assertIn("CreateSubsectionTitle(\"能力概览\")", form)
|
||||
self.assertIn("CreateSectionTitle(\"节点信息\")", form)
|
||||
self.assertIn("CreateSubsectionTitle(\"可用软件\")", form)
|
||||
self.assertIn("heading.Controls.Add(state, 1, 0)", form)
|
||||
self.assertNotIn("headingHint", form)
|
||||
self.assertIn("panel.SetColumnSpan(path, 2)", form)
|
||||
self.assertIn("panel.SetColumnSpan(status, 2)", form)
|
||||
self.assertIn("panel.SetColumnSpan(actions, 2)", form)
|
||||
|
|
@ -235,6 +238,8 @@ class WindowsNodeSourceTests(unittest.TestCase):
|
|||
|
||||
tray = (PROJECT / "TrayApplicationContext.cs").read_text(encoding="utf-8")
|
||||
self.assertIn("form.ReconnectRequested += RestartConnection", tray)
|
||||
self.assertIn("statusItem.Text = CompactMenuText(status.Message, 24)", tray)
|
||||
self.assertIn('singleLine[..(length - 1)] + "…"', tray)
|
||||
|
||||
def test_tray_exit_waits_for_or_cancels_active_jobs(self) -> None:
|
||||
tray = (PROJECT / "TrayApplicationContext.cs").read_text(encoding="utf-8")
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ internal sealed class ConfigurationForm : Form
|
|||
adapters = NodeAdapterRegistry.CreateDefault(jobInbox);
|
||||
Text = "zcbot Windows Node";
|
||||
AutoScaleMode = AutoScaleMode.Dpi;
|
||||
ClientSize = new Size(1080, 720);
|
||||
ClientSize = new Size(1080, 1050);
|
||||
MinimumSize = new Size(760, 560);
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Font = new Font("Microsoft YaHei UI", 9);
|
||||
|
|
@ -109,19 +109,20 @@ internal sealed class ConfigurationForm : Form
|
|||
{
|
||||
AutoSize = true,
|
||||
Dock = DockStyle.Top,
|
||||
ColumnCount = 1,
|
||||
ColumnCount = 2,
|
||||
Margin = new Padding(2, 0, 2, 14),
|
||||
};
|
||||
heading.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
|
||||
heading.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
|
||||
heading.Controls.Add(new Label
|
||||
{
|
||||
Text = "zcbot Windows Node",
|
||||
AutoSize = true,
|
||||
Font = new Font("Microsoft YaHei UI", 18, FontStyle.Bold),
|
||||
Anchor = AnchorStyles.Left,
|
||||
Font = new Font("Microsoft YaHei UI", 16, FontStyle.Bold),
|
||||
ForeColor = Color.FromArgb(15, 23, 42),
|
||||
});
|
||||
var headingHint = CreateHint("连接本机科研软件与 zcbot,安全执行受控任务");
|
||||
headingHint.Font = new Font("Microsoft YaHei UI", 10);
|
||||
heading.Controls.Add(headingHint);
|
||||
}, 0, 0);
|
||||
heading.Controls.Add(state, 1, 0);
|
||||
page.Controls.Add(heading);
|
||||
|
||||
var tabs = new NavigationTabControl
|
||||
|
|
@ -139,22 +140,11 @@ internal sealed class ConfigurationForm : Form
|
|||
page.Controls.Add(tabs, 0, 1);
|
||||
|
||||
var statusCard = CreateSection();
|
||||
var statusHeader = new TableLayoutPanel
|
||||
{
|
||||
AutoSize = true,
|
||||
Dock = DockStyle.Top,
|
||||
ColumnCount = 2,
|
||||
Margin = new Padding(0, 0, 0, 8),
|
||||
};
|
||||
statusHeader.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
|
||||
statusHeader.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
|
||||
statusHeader.Controls.Add(CreateSectionTitle("节点状态"), 0, 0);
|
||||
statusHeader.Controls.Add(state, 1, 0);
|
||||
statusCard.Controls.Add(statusHeader);
|
||||
statusCard.Controls.Add(CreateSectionTitle("节点信息"));
|
||||
statusCard.Controls.Add(detail);
|
||||
statusCard.Controls.Add(identity);
|
||||
statusCard.Controls.Add(CreateDivider());
|
||||
statusCard.Controls.Add(CreateSubsectionTitle("能力概览"));
|
||||
statusCard.Controls.Add(CreateSubsectionTitle("可用软件"));
|
||||
statusCard.Controls.Add(capabilitySummary);
|
||||
var resetActions = CreateActions();
|
||||
resetActions.Controls.Add(reconnect);
|
||||
|
|
@ -1356,9 +1346,7 @@ internal sealed class ConfigurationForm : Form
|
|||
{
|
||||
var selected = eventArgs.Index == SelectedIndex;
|
||||
var bounds = eventArgs.Bounds;
|
||||
using var background = new SolidBrush(selected
|
||||
? Color.White
|
||||
: Color.FromArgb(241, 245, 249));
|
||||
using var background = new SolidBrush(Color.White);
|
||||
eventArgs.Graphics.FillRectangle(background, bounds);
|
||||
TextRenderer.DrawText(
|
||||
eventArgs.Graphics,
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ internal sealed class TrayApplicationContext : ApplicationContext
|
|||
{
|
||||
current = status;
|
||||
form.ApplyStatus(status, config);
|
||||
statusItem.Text = status.Message;
|
||||
statusItem.Text = CompactMenuText(status.Message, 24);
|
||||
tray.Text = Limit($"zcbot Windows Node - {status.Message}", 63);
|
||||
var oldIcon = tray.Icon;
|
||||
tray.Icon = TrayIconFactory.Create(status.State);
|
||||
|
|
@ -279,4 +279,12 @@ internal sealed class TrayApplicationContext : ApplicationContext
|
|||
|
||||
private static string Limit(string value, int length) =>
|
||||
value.Length <= length ? value : value[..length];
|
||||
|
||||
private static string CompactMenuText(string value, int length)
|
||||
{
|
||||
var singleLine = value.Replace('\r', ' ').Replace('\n', ' ').Trim();
|
||||
return singleLine.Length <= length
|
||||
? singleLine
|
||||
: singleLine[..(length - 1)] + "…";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue