MainWindow.axaml 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <Window xmlns="https://github.com/avaloniaui"
  2. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  3. xmlns:vm="using:YZWater.Core.ViewModels"
  4. xmlns:views="using:YZWater.Avalonia.Views"
  5. xmlns:conv="using:YZWater.Avalonia.Converters"
  6. xmlns:th="using:YZWater.Avalonia.Controls"
  7. x:Class="YZWater.Avalonia.Views.MainWindow"
  8. x:DataType="vm:MainViewModel"
  9. Title="{Binding Title}"
  10. Icon="/Assets/app-icon.png"
  11. WindowDecorations="None"
  12. Width="1280" Height="800"
  13. MinWidth="1024" MinHeight="700"
  14. WindowStartupLocation="CenterScreen"
  15. WindowState="Maximized"
  16. Background="{DynamicResource AppBgBrush}">
  17. <Window.DataContext>
  18. <vm:MainViewModel/>
  19. </Window.DataContext>
  20. <DockPanel>
  21. <!-- ═══ 自定义标题栏 ═══ -->
  22. <Border DockPanel.Dock="Top" Background="{DynamicResource NavBgBrush}" Height="32"
  23. PointerPressed="OnTitleBarPointerPressed" Cursor="Hand">
  24. <Grid ColumnDefinitions="Auto,*,Auto">
  25. <Image Source="/Assets/app-icon.png" Width="20" Height="20" Margin="8,0,4,0" VerticalAlignment="Center"/>
  26. <TextBlock Grid.Column="1" Text="{Binding Title}" FontSize="13" FontWeight="SemiBold"
  27. VerticalAlignment="Center" Foreground="{DynamicResource TextPrimaryBrush}"/>
  28. <StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center">
  29. <Button Content="─" Click="OnMinimizeClick" Classes="chrome-btn"/>
  30. <Button x:Name="MaximizeBtn" Content="☐" Click="OnMaximizeClick" Classes="chrome-btn"/>
  31. <Button Content="✕" Click="OnCloseClick" Classes="chrome-btn"
  32. Foreground="{DynamicResource DangerFgBrush}"/>
  33. </StackPanel>
  34. </Grid>
  35. </Border>
  36. <!-- ═══ 底部导航栏 ═══ -->
  37. <Border x:Name="NavBar" DockPanel.Dock="Bottom" Background="{DynamicResource NavBgBrush}"
  38. BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0" Padding="4,0">
  39. <Grid ColumnDefinitions="*,Auto,Auto,Auto">
  40. <!-- 导航按钮 -->
  41. <StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center" Spacing="0">
  42. <Button Command="{Binding ShowViewACommand}" Classes="nav-tab">
  43. <StackPanel Orientation="Horizontal" Spacing="6">
  44. <Border Width="3" Height="14" CornerRadius="1"
  45. Background="{Binding IsTabAActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  46. <TextBlock Text="{Binding NavProcess}" FontFamily="Consolas, monospace" FontSize="11"
  47. FontWeight="{Binding IsTabAActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  48. Foreground="{Binding IsTabAActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  49. </StackPanel>
  50. </Button>
  51. <Border Background="{DynamicResource BorderBrush}" Width="1" Height="20" VerticalAlignment="Center"/>
  52. <Button Command="{Binding ShowViewBCommand}" Classes="nav-tab">
  53. <StackPanel Orientation="Horizontal" Spacing="6">
  54. <Border Width="3" Height="14" CornerRadius="1"
  55. Background="{Binding IsTabBActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  56. <TextBlock Text="{Binding NavParams}" FontFamily="Consolas, monospace" FontSize="11"
  57. FontWeight="{Binding IsTabBActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  58. Foreground="{Binding IsTabBActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  59. </StackPanel>
  60. </Button>
  61. <Border Background="{DynamicResource BorderBrush}" Width="1" Height="20" VerticalAlignment="Center"/>
  62. <Button Command="{Binding ShowViewCCommand}" Classes="nav-tab">
  63. <StackPanel Orientation="Horizontal" Spacing="6">
  64. <Border Width="3" Height="14" CornerRadius="1"
  65. Background="{Binding IsTabCActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  66. <TextBlock Text="{Binding NavFlow}" FontFamily="Consolas, monospace" FontSize="11"
  67. FontWeight="{Binding IsTabCActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  68. Foreground="{Binding IsTabCActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  69. </StackPanel>
  70. </Button>
  71. <Border Background="{DynamicResource BorderBrush}" Width="1" Height="20" VerticalAlignment="Center"/>
  72. <Button Command="{Binding ShowViewDCommand}" Classes="nav-tab">
  73. <StackPanel Orientation="Horizontal" Spacing="6">
  74. <Border Width="3" Height="14" CornerRadius="1"
  75. Background="{Binding IsTabDActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  76. <TextBlock Text="{Binding NavAlarm}" FontFamily="Consolas, monospace" FontSize="11"
  77. FontWeight="{Binding IsTabDActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  78. Foreground="{Binding IsTabDActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  79. </StackPanel>
  80. </Button>
  81. <Border Background="{DynamicResource BorderBrush}" Width="1" Height="20" VerticalAlignment="Center"/>
  82. <Button Command="{Binding ShowViewECommand}" Classes="nav-tab">
  83. <StackPanel Orientation="Horizontal" Spacing="6">
  84. <Border Width="3" Height="14" CornerRadius="1"
  85. Background="{Binding IsTabEActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  86. <TextBlock Text="{Binding NavAbout}" FontFamily="Consolas, monospace" FontSize="11"
  87. FontWeight="{Binding IsTabEActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  88. Foreground="{Binding IsTabEActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  89. </StackPanel>
  90. </Button>
  91. <Border Background="{DynamicResource BorderBrush}" Width="1" Height="20" VerticalAlignment="Center"/>
  92. <Button Command="{Binding ShowViewFCommand}" Classes="nav-tab">
  93. <StackPanel Orientation="Horizontal" Spacing="6">
  94. <Border Width="3" Height="14" CornerRadius="1"
  95. Background="{Binding IsTabFActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  96. <TextBlock Text="{Binding NavAudit}" FontFamily="Consolas, monospace" FontSize="11"
  97. FontWeight="{Binding IsTabFActive, Converter={x:Static conv:BoolConverters.ToFontWeight}}"
  98. Foreground="{Binding IsTabFActive, Converter={x:Static conv:BoolConverters.ToBrush}}"/>
  99. </StackPanel>
  100. </Button>
  101. </StackPanel>
  102. <!-- 主题切换 -->
  103. <Button Grid.Column="1" Command="{Binding ToggleThemeCommand}" Classes="btn-toggle" Margin="8,0">
  104. <StackPanel Orientation="Horizontal" Spacing="6">
  105. <TextBlock Text="{Binding ThemeIcon}" FontSize="14" VerticalAlignment="Center"/>
  106. <TextBlock Text="THEME" FontSize="10" VerticalAlignment="Center"
  107. Foreground="{DynamicResource TextSecondaryBrush}"/>
  108. </StackPanel>
  109. </Button>
  110. <!-- 语言切换 -->
  111. <Button Grid.Column="2" Command="{Binding ToggleLanguageCommand}" Classes="btn-toggle" Margin="0,0,8,0">
  112. <StackPanel Orientation="Horizontal" Spacing="6">
  113. <TextBlock Text="{Binding LangIcon}" FontSize="12" FontWeight="Bold" VerticalAlignment="Center"/>
  114. <TextBlock Text="LANG" FontSize="10" VerticalAlignment="Center"
  115. Foreground="{DynamicResource TextSecondaryBrush}"/>
  116. </StackPanel>
  117. </Button>
  118. <!-- 用户信息 + 模式指示 -->
  119. <StackPanel Grid.Column="3" Orientation="Horizontal" Spacing="8" Margin="8,0" VerticalAlignment="Center">
  120. <Border Background="{DynamicResource CardBgBrush}" CornerRadius="4" Padding="6,2">
  121. <TextBlock Text="{Binding HubStatusText}" FontSize="10" Foreground="{DynamicResource TextSecondaryBrush}"/>
  122. </Border>
  123. <!-- 用户信息区域(认证禁用时隐藏) -->
  124. <TextBlock Text="{Binding CurrentUserName}" FontSize="12" FontWeight="Bold" VerticalAlignment="Center"
  125. IsVisible="{Binding ShowUserInfo}"/>
  126. <Border Background="{DynamicResource PrimaryBrush}" CornerRadius="4" Padding="6,2"
  127. IsVisible="{Binding ShowUserInfo}">
  128. <TextBlock Text="{Binding CurrentUserRole}" FontSize="10" Foreground="White"/>
  129. </Border>
  130. <Button Command="{Binding ToggleUserDialogCommand}" IsVisible="{Binding CanManageUsers}"
  131. Content="{Binding UserManageText}" Padding="8,4" FontSize="11" Classes="btn-primary"/>
  132. <Button Command="{Binding LogoutCommand}" Content="{Binding LogoutText}" Padding="8,4" FontSize="11" Classes="btn-danger"
  133. IsVisible="{Binding ShowUserInfo}"/>
  134. </StackPanel>
  135. </Grid>
  136. </Border>
  137. <!-- ═══ PLC 通信中断横幅(ISA-101: 断线时全局可见警告)═══
  138. 独立占一行,不再浮在内容区顶部:压在页面标题栏上会把标题一起糊掉,
  139. 而断线恰恰是最需要看清"现在在哪个页面"的时候 -->
  140. <Border DockPanel.Dock="Top" IsVisible="{Binding !IsPlcConnected}"
  141. Background="#F39C12" Padding="12,6">
  142. <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="8">
  143. <TextBlock Text="⚠" FontSize="16" VerticalAlignment="Center" Foreground="#2C3E50"/>
  144. <TextBlock Text="{Binding PlcCommInterruptedText}"
  145. FontSize="13" FontWeight="Bold" VerticalAlignment="Center" Foreground="#2C3E50"/>
  146. </StackPanel>
  147. </Border>
  148. <!-- ═══ 主内容区域 ═══ -->
  149. <Panel>
  150. <!-- 视图内容(通过 CurrentView + DataTemplate 切换) -->
  151. <ContentControl Content="{Binding CurrentView}"/>
  152. <!-- ═══ 用户管理对话框 ═══ -->
  153. <Border IsVisible="{Binding ShowUserDialog}" ZIndex="100" Background="#CC000000">
  154. <Border Background="{DynamicResource CardBgBrush}" CornerRadius="12" Padding="24"
  155. MaxWidth="600" MaxHeight="500" VerticalAlignment="Center" HorizontalAlignment="Center"
  156. BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1">
  157. <DockPanel>
  158. <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="12" Margin="0,0,0,16">
  159. <TextBlock Text="{Binding UserManageText}" FontSize="18" FontWeight="Bold"/>
  160. <Button Content="{Binding CloseText}" Command="{Binding ToggleUserDialogCommand}" HorizontalAlignment="Right" Classes="btn-danger"/>
  161. </StackPanel>
  162. <!-- 创建用户 -->
  163. <Border DockPanel.Dock="Top" Background="{DynamicResource CardBgBrush}" CornerRadius="8" Padding="12" Margin="0,0,0,12">
  164. <StackPanel Spacing="8">
  165. <TextBlock Text="{Binding CreateNewUserText}" FontWeight="Bold" FontSize="14"/>
  166. <StackPanel Orientation="Horizontal" Spacing="8">
  167. <TextBox Text="{Binding NewUserName}" PlaceholderText="{Binding UserNameLabel}" Width="120"/>
  168. <TextBox Text="{Binding NewUserPassword}" PlaceholderText="{Binding PasswordLabel}" PasswordChar="●" Width="120"/>
  169. <TextBox Text="{Binding NewUserDisplayName}" PlaceholderText="{Binding DisplayNameLabel}" Width="120"/>
  170. <ComboBox SelectedIndex="{Binding NewUserRole}" Width="100">
  171. <ComboBoxItem Content="Viewer"/>
  172. <ComboBoxItem Content="Operator"/>
  173. <ComboBoxItem Content="Engineer"/>
  174. <ComboBoxItem Content="Admin"/>
  175. </ComboBox>
  176. <Button Content="{Binding CreateText}" Command="{Binding CreateUserCommand}" Classes="btn-success"/>
  177. </StackPanel>
  178. <TextBlock Text="{Binding UserManageMessage}" Foreground="Red" FontSize="12"/>
  179. </StackPanel>
  180. </Border>
  181. <!-- 用户列表 -->
  182. <DataGrid ItemsSource="{Binding UserList}" AutoGenerateColumns="False" IsReadOnly="True"
  183. GridLinesVisibility="Horizontal" CanUserResizeColumns="True">
  184. <DataGrid.Columns>
  185. <DataGridTextColumn Header="User" Binding="{Binding UserName}" Width="100"/>
  186. <DataGridTextColumn Header="Name" Binding="{Binding DisplayName}" Width="120"/>
  187. <DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="80"/>
  188. <DataGridTextColumn Header="Status" Binding="{Binding IsActive}" Width="60"/>
  189. <DataGridTextColumn Header="Last Login" Binding="{Binding LastLoginTime, StringFormat='yyyy-MM-dd HH:mm'}" Width="140"/>
  190. <DataGridTemplateColumn Header="Action" Width="80">
  191. <DataGridTemplateColumn.CellTemplate>
  192. <DataTemplate>
  193. <Button Content="{Binding IsActive, Converter={x:Static conv:BoolConverters.ToActiveText}}"
  194. Command="{Binding $parent[DataGrid].((vm:MainViewModel)DataContext).ToggleUserActiveCommand}"
  195. CommandParameter="{Binding}"
  196. Classes="btn-toggle" Padding="6,2" FontSize="11"/>
  197. </DataTemplate>
  198. </DataGridTemplateColumn.CellTemplate>
  199. </DataGridTemplateColumn>
  200. </DataGrid.Columns>
  201. </DataGrid>
  202. </DockPanel>
  203. </Border>
  204. </Border>
  205. <!-- ═══ 退出确认对话框(破坏性操作需二次确认,防止误触 ✕ 停屏) ═══ -->
  206. <Border IsVisible="{Binding ShowExitDialog}" ZIndex="110" Background="#CC000000">
  207. <Border Background="{DynamicResource CardBgBrush}" CornerRadius="12" Padding="24"
  208. MaxWidth="420" VerticalAlignment="Center" HorizontalAlignment="Center"
  209. BorderBrush="{DynamicResource DangerFgBrush}" BorderThickness="1">
  210. <StackPanel Spacing="16">
  211. <StackPanel Orientation="Horizontal" Spacing="10">
  212. <TextBlock Text="⚠" FontSize="18" FontFamily="Segoe UI Symbol" VerticalAlignment="Center"
  213. Foreground="{DynamicResource DangerFgBrush}"/>
  214. <TextBlock Text="{Binding ExitConfirmTitleText}" FontSize="18" FontWeight="Bold"
  215. VerticalAlignment="Center"/>
  216. </StackPanel>
  217. <TextBlock Text="{Binding ExitConfirmMessageText}" FontSize="13" TextWrapping="Wrap"
  218. Foreground="{DynamicResource TextSecondaryBrush}"/>
  219. <StackPanel Orientation="Horizontal" Spacing="12" HorizontalAlignment="Right">
  220. <Button Content="{Binding CancelText}" Click="OnExitCancelClick"
  221. Classes="btn-toggle" MinWidth="88"/>
  222. <Button Content="{Binding ConfirmText}" Click="OnExitConfirmClick"
  223. Classes="btn-danger" MinWidth="88"/>
  224. </StackPanel>
  225. </StackPanel>
  226. </Border>
  227. </Border>
  228. </Panel>
  229. </DockPanel>
  230. </Window>