Files
Axi_Omron/src/AxiOmron.PcbCheck/Views/Pages/SystemSettingsPage.xaml
yunxiao.zhu 8f74e07c66 feat(*): 添加管理员解锁与 SFTP 探活能力
* 新增管理员解锁弹窗、手动操作权限控制与倒计时状态
* 支持系统设置页测试 SFTP 连接,并在启动时执行探活
* 补充设计时服务、全局异常兜底与相关单元测试
2026-04-17 14:12:10 +08:00

110 lines
12 KiB
XML

<Page x:Class="AxiOmron.PcbCheck.Views.Pages.SystemSettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hc="https://handyorg.github.io/handycontrol"
mc:Ignorable="d"
d:DesignWidth="1400"
d:DesignHeight="860"
Title="SystemSettingsPage"
d:DataContext="{Binding Source={StaticResource DesignTimeLocator}, Path=SystemSettingViewModel}"
DataContext="{Binding Source={StaticResource Locator}, Path=SystemSettingViewModel}">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl Grid.Row="0" Style="{StaticResource TabControlInLine}">
<TabItem Header="PLC">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="16">
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="PLC 主机" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.Host, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="端口" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.Port, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="从站号" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.UnitId, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="轮询周期(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.PollIntervalMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="连接超时(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.ConnectTimeoutMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="心跳周期(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.HeartbeatIntervalMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="放行脉冲(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.ReleasePulseMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="放行应答超时(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Plc.ReleaseAckTimeoutMs, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="扫码枪">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="16">
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="串口号" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.PortName, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="波特率" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.BaudRate, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="数据位" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.DataBits, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="校验位" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.Parity, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="停止位" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.StopBits, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="超时(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.ReadTimeoutMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="触发命令" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.TriggerCommand, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="返回结束符" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Scanner.ResponseTerminator, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="SFTP">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="16">
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="主机" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.Host, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="端口" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.Port, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="用户名" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.Username, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="密码" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.Password, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="私钥路径" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.PrivateKeyPath, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="根目录" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.RootPath, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="文件名模板" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.FileNamePattern, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="重试间隔(秒)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.RetryIntervalSeconds, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="最大重试次数" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Sftp.MaxRetryCount, UpdateSourceTrigger=PropertyChanged}" />
<StackPanel Orientation="Horizontal" Margin="0,12,0,0">
<Button Style="{StaticResource ButtonDefault}"
Padding="18,8"
MinHeight="36"
Content="测试连接"
Command="{Binding TestSftpConnectionCommand}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="安灯 &amp; 流程">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Margin="16">
<CheckBox Content="启用安灯接口" IsChecked="{Binding EditableConfig.Andon.Enable}" Margin="0,6,0,0" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="安灯 URL" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.Url, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="请求方法" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.Method, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="超时(ms)" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.TimeoutMs, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="安灯主题" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.AndonTheme, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="设备 EID" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.Eid, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="来源标记" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.FromSign, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Style="{StaticResource TextBoxExtend}" hc:InfoElement.Title="服务 ID" hc:InfoElement.TitlePlacement="Left" Margin="0,6,0,0" Text="{Binding EditableConfig.Andon.ServiceId, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Content="扫码失败时报警" IsChecked="{Binding EditableConfig.Andon.EnableScanFailAlarm}" Margin="0,6,0,0" />
<CheckBox Content="文件未找到时报警" IsChecked="{Binding EditableConfig.Andon.EnableFileNotFoundAlarm}" Margin="0,6,0,0" />
<CheckBox Content="要求 PLC Ready" IsChecked="{Binding EditableConfig.Workflow.RequirePlcReady}" Margin="0,6,0,0" />
<CheckBox Content="要求 AutoMode &amp; StationEnable" IsChecked="{Binding EditableConfig.Workflow.RequireAutoMode}" Margin="0,6,0,0" />
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
<Grid Grid.Row="1" Margin="0,16,0,0" MinHeight="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Vertical" VerticalAlignment="Center">
<TextBlock Text="{Binding StatusMessage}" FontWeight="SemiBold" />
<TextBlock Margin="0,4,0,0" Foreground="#A33A00" Text="保存后需重启应用生效。" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<Button Style="{StaticResource ButtonDefault}" Margin="0,0,8,0" Padding="18,8" MinHeight="36" Content="重新加载" Command="{Binding ReloadCommand}" />
<Button Style="{StaticResource ButtonPrimary}" Padding="18,8" MinHeight="36" Content="保存配置" Command="{Binding SaveCommand}" />
</StackPanel>
</Grid>
</Grid>
</Page>