diff --git a/Ayay.Solution.sln b/Ayay.Solution.sln index 0bedb48..e025631 100644 --- a/Ayay.Solution.sln +++ b/Ayay.Solution.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SHH.Contracts", "SHH.Contra EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SHH.NetMQ", "SHH.NetMQ\SHH.NetMQ.csproj", "{FAC8E0CD-4BB3-4752-A406-CD3D2CE5FBB4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SHH.CameraDashboard", "SHH.CameraDashboard\SHH.CameraDashboard.csproj", "{03C249D7-BCF1-404D-AD09-7AB39BA263AD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {FAC8E0CD-4BB3-4752-A406-CD3D2CE5FBB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAC8E0CD-4BB3-4752-A406-CD3D2CE5FBB4}.Release|Any CPU.ActiveCfg = Release|Any CPU {FAC8E0CD-4BB3-4752-A406-CD3D2CE5FBB4}.Release|Any CPU.Build.0 = Release|Any CPU + {03C249D7-BCF1-404D-AD09-7AB39BA263AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03C249D7-BCF1-404D-AD09-7AB39BA263AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03C249D7-BCF1-404D-AD09-7AB39BA263AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03C249D7-BCF1-404D-AD09-7AB39BA263AD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SHH.CameraDashboard/App.xaml b/SHH.CameraDashboard/App.xaml new file mode 100644 index 0000000..6998269 --- /dev/null +++ b/SHH.CameraDashboard/App.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/SHH.CameraDashboard/App.xaml.cs b/SHH.CameraDashboard/App.xaml.cs new file mode 100644 index 0000000..f60e5be --- /dev/null +++ b/SHH.CameraDashboard/App.xaml.cs @@ -0,0 +1,14 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace SHH.CameraDashboard +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + +} diff --git a/SHH.CameraDashboard/App/AppGlobalData.cs b/SHH.CameraDashboard/App/AppGlobalData.cs new file mode 100644 index 0000000..ca201f8 --- /dev/null +++ b/SHH.CameraDashboard/App/AppGlobalData.cs @@ -0,0 +1,17 @@ +namespace SHH.CameraDashboard +{ + // 2. 全局配置存储 + public static class AppGlobalData + { + public static List ActiveServerList { get; private set; } = new List(); + + public static void SaveConfig(IEnumerable nodes) + { + ActiveServerList.Clear(); + foreach (var node in nodes) + { + ActiveServerList.Add(new ServerNode { Ip = node.Ip, Port = node.Port }); + } + } + } +} \ No newline at end of file diff --git a/SHH.CameraDashboard/App/ClipboardHelper.cs b/SHH.CameraDashboard/App/ClipboardHelper.cs new file mode 100644 index 0000000..ef52861 --- /dev/null +++ b/SHH.CameraDashboard/App/ClipboardHelper.cs @@ -0,0 +1,40 @@ +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows; + +public static class ClipboardHelper +{ + /// + /// 安全复制文本,包含冲突重试机制 + /// + public static void SetText(string text) + { + if (string.IsNullOrEmpty(text)) return; + + // 最多尝试 5 次,每次间隔 100 毫秒 + for (int i = 0; i < 5; i++) + { + try + { + Clipboard.SetText(text); + return; // 复制成功,退出方法 + } + catch (COMException ex) + { + // 如果是剪贴板被占用错误,等待后重试 + if ((uint)ex.ErrorCode == 0x800401D0) + { + Thread.Sleep(100); + continue; + } + throw; // 其他 COM 错误则抛出 + } + catch (Exception) + { + if (i == 4) throw; // 最后一次尝试失败则抛出 + Thread.Sleep(100); + } + } + } +} \ No newline at end of file diff --git a/SHH.CameraDashboard/App/ThemeManager.cs b/SHH.CameraDashboard/App/ThemeManager.cs new file mode 100644 index 0000000..b0c24ef --- /dev/null +++ b/SHH.CameraDashboard/App/ThemeManager.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace SHH.CameraDashboard +{ + public enum ThemeType { Dark, Light } + + public static class ThemeManager + { + public static void ChangeTheme(ThemeType theme) + { + var appResources = Application.Current.Resources; + + // 1. 找到旧的颜色字典并移除 + // 我们通过检查 Source 路径来识别它 + ResourceDictionary oldDict = null; + foreach (var dict in appResources.MergedDictionaries) + { + // 只要路径里包含 "Colors." 说明它是我们的皮肤文件 + if (dict.Source != null && dict.Source.OriginalString.Contains("Themes/Colors.")) + { + oldDict = dict; + break; + } + } + + if (oldDict != null) + { + appResources.MergedDictionaries.Remove(oldDict); + } + + // 2. 加载新字典 + string dictName = theme switch + { + ThemeType.Light => "/Style/Themes/Colors.Light.xaml", + ThemeType.Dark => "/Style/Themes/Colors.Dark.xaml", + _ => "/Style/Themes/Colors.Dark.xaml" // 默认 + }; + + var newDict = new ResourceDictionary + { + Source = new Uri(dictName, UriKind.Relative) + }; + + // 3. 添加到集合中 (建议加在最前面,或者根据索引位置) + appResources.MergedDictionaries.Add(newDict); + } + } +} diff --git a/SHH.CameraDashboard/App/WizardControl.xaml b/SHH.CameraDashboard/App/WizardControl.xaml new file mode 100644 index 0000000..11fb734 --- /dev/null +++ b/SHH.CameraDashboard/App/WizardControl.xaml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + +