diff --git a/Sln.Wcs.UI/App.axaml b/Sln.Wcs.UI/App.axaml
index 783f573..ce86296 100644
--- a/Sln.Wcs.UI/App.axaml
+++ b/Sln.Wcs.UI/App.axaml
@@ -7,7 +7,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #2E5A7A
+ #1E3A5A
+ #3E6A9A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #8FA0B0
+ #6F8292
+ #AFBECC
+
+
+
+
+
+
diff --git a/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml b/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml
index 5b8ce7e..4978734 100644
--- a/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml
+++ b/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml
@@ -13,16 +13,16 @@
SystemDecorations="Full"
CanResize="False">
-
+
+ Background="{DynamicResource CardBgBrush}" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,0,0,1">
-
-
+
+
@@ -33,29 +33,17 @@
+ Background="{DynamicResource PageBgBrush}" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0">
+ Background="{DynamicResource PrimaryBtnBrush}" Foreground="White"
+ CornerRadius="4" />
diff --git a/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml.cs b/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml.cs
index c023b6c..4495595 100644
--- a/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml.cs
+++ b/Sln.Wcs.UI/Views/Base/EntityEditWindow.axaml.cs
@@ -5,6 +5,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
+using Avalonia.Styling;
using Sln.Wcs.UI.ViewModels.Base;
namespace Sln.Wcs.UI.Views.Base;
@@ -31,12 +32,21 @@ public partial class EntityEditWindow : Window
return _tcs.Task;
}
+ private static bool IsDark =>
+ Application.Current!.ActualThemeVariant == ThemeVariant.Dark;
+
private void BuildForm(List fields)
{
FormPanel.Children.Clear();
if (_entity is null) return;
var type = _entity.GetType();
+ var labelFg = Brush.Parse(IsDark ? "#8B9BB5" : "#656D76");
+ var checkFg = Brush.Parse(IsDark ? "#BCC8D6" : "#1F2328");
+ var tbBg = Brush.Parse(IsDark ? "#0A0E14" : "#F0F2F5");
+ var tbFg = Brush.Parse(IsDark ? "#DDE4F0" : "#1F2328");
+ var tbBorder = Brush.Parse(IsDark ? "#1A2F4A" : "#D0D7DE");
+
foreach (var field in fields)
{
var prop = type.GetProperty(field.PropertyName);
@@ -58,7 +68,7 @@ public partial class EntityEditWindow : Window
{
Text = field.DisplayName,
FontSize = 12,
- Foreground = Brush.Parse("#7B8FA8"),
+ Foreground = labelFg,
VerticalAlignment = VerticalAlignment.Center,
};
row.Children.Add(label);
@@ -71,7 +81,7 @@ public partial class EntityEditWindow : Window
{
IsChecked = value is int iv ? iv == 1 : (value as bool? ?? false),
IsEnabled = !field.IsReadOnly,
- Foreground = Brush.Parse("#BCC8D6"),
+ Foreground = checkFg,
VerticalAlignment = VerticalAlignment.Center,
};
cb.IsCheckedChanged += (_, _) =>
@@ -85,9 +95,9 @@ public partial class EntityEditWindow : Window
Text = value?.ToString() ?? "",
IsReadOnly = field.IsReadOnly,
Watermark = field.DisplayName,
- Background = Brush.Parse("#0A0E14"),
- Foreground = Brush.Parse("#DDE4F0"),
- BorderBrush = Brush.Parse("#1A2F4A"),
+ Background = tbBg,
+ Foreground = tbFg,
+ BorderBrush = tbBorder,
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(3),
Padding = new Thickness(8, 5),
diff --git a/Sln.Wcs.UI/Views/Base/LocationInfoListView.axaml b/Sln.Wcs.UI/Views/Base/LocationInfoListView.axaml
index ba10bed..91fa5ec 100644
--- a/Sln.Wcs.UI/Views/Base/LocationInfoListView.axaml
+++ b/Sln.Wcs.UI/Views/Base/LocationInfoListView.axaml
@@ -3,45 +3,45 @@
x:Class="Sln.Wcs.UI.Views.Base.LocationInfoListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Base/MaterialInfoListView.axaml b/Sln.Wcs.UI/Views/Base/MaterialInfoListView.axaml
index 03df5ed..8634a97 100644
--- a/Sln.Wcs.UI/Views/Base/MaterialInfoListView.axaml
+++ b/Sln.Wcs.UI/Views/Base/MaterialInfoListView.axaml
@@ -3,37 +3,37 @@
x:Class="Sln.Wcs.UI.Views.Base.MaterialInfoListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Base/StoreInfoListView.axaml b/Sln.Wcs.UI/Views/Base/StoreInfoListView.axaml
index 9e65c5f..027aae3 100644
--- a/Sln.Wcs.UI/Views/Base/StoreInfoListView.axaml
+++ b/Sln.Wcs.UI/Views/Base/StoreInfoListView.axaml
@@ -3,31 +3,31 @@
x:Class="Sln.Wcs.UI.Views.Base.StoreInfoListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Device/DeviceHostListView.axaml b/Sln.Wcs.UI/Views/Device/DeviceHostListView.axaml
index 8270255..f29d67c 100644
--- a/Sln.Wcs.UI/Views/Device/DeviceHostListView.axaml
+++ b/Sln.Wcs.UI/Views/Device/DeviceHostListView.axaml
@@ -4,41 +4,41 @@
-
-
+ Background="{DynamicResource CardBgBrush}" Foreground="{DynamicResource PrimaryTextBrush}" BorderBrush="{DynamicResource BorderBrush}" />
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ Background="{DynamicResource InfoBtnBrush}" Foreground="White" FontSize="11" Padding="8,3" />
+ Background="{DynamicResource DangerBtnBrush}" Foreground="White" FontSize="11" Padding="8,3" />
diff --git a/Sln.Wcs.UI/Views/Device/DeviceInfoListView.axaml b/Sln.Wcs.UI/Views/Device/DeviceInfoListView.axaml
index 793fabb..d7769be 100644
--- a/Sln.Wcs.UI/Views/Device/DeviceInfoListView.axaml
+++ b/Sln.Wcs.UI/Views/Device/DeviceInfoListView.axaml
@@ -3,40 +3,45 @@
x:Class="Sln.Wcs.UI.Views.Device.DeviceInfoListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -44,59 +49,53 @@
-
+
-
-
-
+
-
-
+
-
-
-
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Device/DeviceParamListView.axaml b/Sln.Wcs.UI/Views/Device/DeviceParamListView.axaml
index 667828f..9288d0d 100644
--- a/Sln.Wcs.UI/Views/Device/DeviceParamListView.axaml
+++ b/Sln.Wcs.UI/Views/Device/DeviceParamListView.axaml
@@ -3,41 +3,41 @@
x:Class="Sln.Wcs.UI.Views.Device.DeviceParamListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/HomePageView.axaml b/Sln.Wcs.UI/Views/HomePageView.axaml
index 529697e..985b2fa 100644
--- a/Sln.Wcs.UI/Views/HomePageView.axaml
+++ b/Sln.Wcs.UI/Views/HomePageView.axaml
@@ -5,198 +5,168 @@
-
-
-
-
-
-
-
+
-
+
+ FontSize="12" Foreground="{DynamicResource SecondaryTextBrush}" TextWrapping="Wrap" LineHeight="20" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
-
+
+ FontSize="12" Foreground="{DynamicResource SecondaryTextBrush}" TextWrapping="Wrap" />
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
-
+
+ FontSize="12" Foreground="{DynamicResource SecondaryTextBrush}" TextWrapping="Wrap" />
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
+
-
+
-
+
+ FontSize="13" FontWeight="SemiBold" Foreground="{DynamicResource AccentTextBrush}" HorizontalAlignment="Center" />
-
+
-
-
+
+
-
+
@@ -207,19 +177,19 @@
-
+
-
+
-
-
+
+
-
+
+ FontSize="11" Foreground="{DynamicResource MutedTextBrush}" TextWrapping="Wrap" LineHeight="18" />
diff --git a/Sln.Wcs.UI/Views/MainWindow.axaml b/Sln.Wcs.UI/Views/MainWindow.axaml
index b768072..d39b492 100644
--- a/Sln.Wcs.UI/Views/MainWindow.axaml
+++ b/Sln.Wcs.UI/Views/MainWindow.axaml
@@ -7,60 +7,69 @@
Width="1280" Height="780"
MinWidth="1000" MinHeight="600"
WindowStartupLocation="CenterScreen"
- Background="#0A0E14"
- Foreground="#BCC8D6">
+ Background="{DynamicResource PageBgBrush}"
+ Foreground="{DynamicResource PrimaryTextBrush}">
-
+
-
-
-
+
+
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
@@ -69,49 +78,49 @@
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/MainWindow.axaml.cs b/Sln.Wcs.UI/Views/MainWindow.axaml.cs
index e68cc20..5794752 100644
--- a/Sln.Wcs.UI/Views/MainWindow.axaml.cs
+++ b/Sln.Wcs.UI/Views/MainWindow.axaml.cs
@@ -9,6 +9,7 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
+using Avalonia.Styling;
using Sln.Wcs.UI.ViewModels;
namespace Sln.Wcs.UI.Views;
@@ -24,6 +25,7 @@ public partial class MainWindow : Window
private long _prevBytesSent;
private long _prevBytesReceived;
private DateTime _prevNetCheck;
+ private bool _isDarkTheme = true;
public MainWindow(NavigationViewModel navigationVm)
{
@@ -55,10 +57,27 @@ public partial class MainWindow : Window
(_prevBytesSent, _prevBytesReceived) = GetNetworkBytes();
_prevNetCheck = DateTime.UtcNow;
+ // 主题切换
+ ThemeToggleBorder.PointerPressed += (_, _) => ToggleTheme();
+
// 退出按钮
LogoutBtn.Click += (_, _) => Close();
}
+ private void ToggleTheme()
+ {
+ _isDarkTheme = !_isDarkTheme;
+ var app = Application.Current!;
+ app.RequestedThemeVariant = _isDarkTheme ? ThemeVariant.Dark : ThemeVariant.Light;
+
+ ThemeIcon.Text = _isDarkTheme ? "\U0001F319" : "☀️";
+ ThemeLabel.Text = _isDarkTheme ? "深色" : "浅色";
+
+ // 关闭所有弹出菜单后重建
+ CloseAllPopups();
+ BuildMenu();
+ }
+
private void RefreshSystemStatus()
{
// CPU usage
@@ -135,13 +154,20 @@ public partial class MainWindow : Window
private void BuildMenu()
{
MenuContainer.Children.Clear();
+ // Use explicit colors per theme — code-behind FindResource doesn't resolve ThemeDictionaries reliably
+ var menuFg = Brush.Parse(_isDarkTheme ? "#8B9BB5" : "#656D76");
+ var menuHoverBg = Brush.Parse(_isDarkTheme ? "#1B3A5C" : "#BBDEFB");
+ var menuHoverFg = Brush.Parse(_isDarkTheme ? "#4FC3F7" : "#0969DA");
+ var popupBg = Brush.Parse(_isDarkTheme ? "#0F1620" : "#FAFBFC");
+ var popupBorder = Brush.Parse(_isDarkTheme ? "#1A2F4A" : "#D0D7DE");
+
foreach (var item in _navVm.TopMenuItems)
{
var btn = new Button
{
Content = item.Label,
Background = Brushes.Transparent,
- Foreground = Brush.Parse("#8B9BB5"),
+ Foreground = menuFg,
FontSize = 13,
Padding = new Thickness(14, 12),
Cursor = new Cursor(StandardCursorType.Hand),
@@ -162,10 +188,10 @@ public partial class MainWindow : Window
IsLightDismissEnabled = false,
};
- var popupBorder = new Border
+ var popupBorderControl = new Border
{
- Background = Brush.Parse("#0F1620"),
- BorderBrush = Brush.Parse("#1A2F4A"),
+ Background = popupBg,
+ BorderBrush = popupBorder,
BorderThickness = new Thickness(1),
CornerRadius = new CornerRadius(4),
MinWidth = 160,
@@ -178,7 +204,7 @@ public partial class MainWindow : Window
{
Content = sub.Label,
Background = Brushes.Transparent,
- Foreground = Brush.Parse("#8B9BB5"),
+ Foreground = menuFg,
FontSize = 12,
HorizontalAlignment = HorizontalAlignment.Stretch,
HorizontalContentAlignment = HorizontalAlignment.Left,
@@ -192,28 +218,28 @@ public partial class MainWindow : Window
sub.Action();
};
subBtn.PointerEntered += (_, _) =>
- subBtn.Background = Brush.Parse("#1B3A5C");
+ subBtn.Background = menuHoverBg;
subBtn.PointerExited += (_, _) =>
subBtn.Background = Brushes.Transparent;
stack.Children.Add(subBtn);
}
- popupBorder.Child = stack;
- popup.Child = popupBorder;
+ popupBorderControl.Child = stack;
+ popup.Child = popupBorderControl;
// Hover 展开,离开按钮或 popup 时关闭
var closeTimer = new System.Timers.Timer(200) { AutoReset = false };
bool mouseInPopup = false;
bool mouseInButton = false;
- popupBorder.PointerEntered += (_, _) => { mouseInPopup = true; closeTimer.Stop(); };
- popupBorder.PointerExited += (_, _) => { mouseInPopup = false; TryClose(); };
+ popupBorderControl.PointerEntered += (_, _) => { mouseInPopup = true; closeTimer.Stop(); };
+ popupBorderControl.PointerExited += (_, _) => { mouseInPopup = false; TryClose(); };
btn.PointerEntered += (_, _) =>
{
mouseInButton = true;
closeTimer.Stop();
- btn.Background = Brush.Parse("#1B3A5C");
- btn.Foreground = Brush.Parse("#4FC3F7");
+ btn.Background = menuHoverBg;
+ btn.Foreground = menuHoverFg;
CloseAllPopups();
popup.Open();
};
@@ -242,7 +268,7 @@ public partial class MainWindow : Window
popup.Closed += (_, _) =>
{
btn.Background = Brushes.Transparent;
- btn.Foreground = Brush.Parse("#8B9BB5");
+ btn.Foreground = menuFg;
};
_openPopups.Add(popup);
}
@@ -250,13 +276,13 @@ public partial class MainWindow : Window
{
btn.PointerEntered += (_, _) =>
{
- btn.Background = Brush.Parse("#1B3A5C");
- btn.Foreground = Brush.Parse("#4FC3F7");
+ btn.Background = menuHoverBg;
+ btn.Foreground = menuHoverFg;
};
btn.PointerExited += (_, _) =>
{
btn.Background = Brushes.Transparent;
- btn.Foreground = Brush.Parse("#8B9BB5");
+ btn.Foreground = menuFg;
};
}
diff --git a/Sln.Wcs.UI/Views/Path/PathDetailsListView.axaml b/Sln.Wcs.UI/Views/Path/PathDetailsListView.axaml
index 3ed2e1a..1d26482 100644
--- a/Sln.Wcs.UI/Views/Path/PathDetailsListView.axaml
+++ b/Sln.Wcs.UI/Views/Path/PathDetailsListView.axaml
@@ -3,35 +3,35 @@
x:Class="Sln.Wcs.UI.Views.Path.PathDetailsListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Path/PathInfoListView.axaml b/Sln.Wcs.UI/Views/Path/PathInfoListView.axaml
index 23c2878..c3eb655 100644
--- a/Sln.Wcs.UI/Views/Path/PathInfoListView.axaml
+++ b/Sln.Wcs.UI/Views/Path/PathInfoListView.axaml
@@ -3,38 +3,43 @@
x:Class="Sln.Wcs.UI.Views.Path.PathInfoListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -45,48 +50,48 @@
-
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/SystemMonitorView.axaml b/Sln.Wcs.UI/Views/SystemMonitorView.axaml
index fe474f2..8fc12be 100644
--- a/Sln.Wcs.UI/Views/SystemMonitorView.axaml
+++ b/Sln.Wcs.UI/Views/SystemMonitorView.axaml
@@ -6,31 +6,31 @@
-
+
-
+
+ Background="{DynamicResource PrimaryBgBrush}" Foreground="{DynamicResource SecondaryTextBrush}" Padding="12,5" FontSize="12" Margin="0,0,6,0" />
+ Background="{DynamicResource PrimaryBgBrush}" Foreground="{DynamicResource SecondaryTextBrush}" Padding="12,5" FontSize="12" />
-
+
-
+
diff --git a/Sln.Wcs.UI/Views/Task/TaskDetailListView.axaml b/Sln.Wcs.UI/Views/Task/TaskDetailListView.axaml
index 5043480..f7f42af 100644
--- a/Sln.Wcs.UI/Views/Task/TaskDetailListView.axaml
+++ b/Sln.Wcs.UI/Views/Task/TaskDetailListView.axaml
@@ -3,47 +3,47 @@
x:Class="Sln.Wcs.UI.Views.Task.TaskDetailListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Sln.Wcs.UI/Views/Task/TaskQueueListView.axaml b/Sln.Wcs.UI/Views/Task/TaskQueueListView.axaml
index 0b16b75..647711d 100644
--- a/Sln.Wcs.UI/Views/Task/TaskQueueListView.axaml
+++ b/Sln.Wcs.UI/Views/Task/TaskQueueListView.axaml
@@ -3,46 +3,51 @@
x:Class="Sln.Wcs.UI.Views.Task.TaskQueueListView">
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -53,50 +58,50 @@
-
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+