diff --git a/Language/en_US.xaml b/Language/en_US.xaml index a06848e..fbd1a3f 100644 --- a/Language/en_US.xaml +++ b/Language/en_US.xaml @@ -200,6 +200,9 @@ P021: Diamond requires cleaning P011: No diamond detected Please check if the cutting tool door is closed + The algorithm is running abnormally: + The test result is empty: + Application error: diff --git a/Language/zh_CN.xaml b/Language/zh_CN.xaml index 390a981..bcb4969 100644 --- a/Language/zh_CN.xaml +++ b/Language/zh_CN.xaml @@ -201,7 +201,9 @@ P004:JSON解析失败 P021:检测到钻石需进行清洁 P011:未检测到钻石 - S007:请检查切工仪设备舱门是否关闭 + S007:请检查切工仪设备舱门是否关闭 + 算法运行异常: + 检测结果为空: 应用程序出现错误: diff --git a/Model/Attributes/LogAttribute.cs b/Model/Attributes/LogAttribute.cs index 15690f3..db47fe7 100644 --- a/Model/Attributes/LogAttribute.cs +++ b/Model/Attributes/LogAttribute.cs @@ -4,6 +4,7 @@ using Rougamo; using Rougamo.Context; using System.Reflection; using System.Text; +using SparkClient.Model.Extension; namespace SparkClient.Model.Attributes { @@ -28,17 +29,37 @@ namespace SparkClient.Model.Attributes } // 记录日志 - Logger.Debug($"Entering {context.Method.DeclaringType?.Name}.{context.Method.Name} with parameters: {parameterLog}"); + //Logger.Debug($"Entering {context.Method.DeclaringType?.Name}.{context.Method.Name} with parameters: {parameterLog}"); } public override void OnExit(MethodContext context) { //Logger.Debug($"Exiting {context.Method.DeclaringType?.Name}.{context.Method.Name}"); - // 获取返回值 var returnValue = context.ReturnValue; + // 获取返回值 + if (context.Exception != null) + { + var parameters = context.Method.GetParameters(); + var arguments = context.Arguments; - // 记录日志 - Logger.Debug($"Exiting {context.Method.DeclaringType?.Name}.{context.Method.Name} with return value: {returnValue}"); + // 构建参数字符串 + var parameterLog = new StringBuilder(); + for (int i = 0; i < parameters.Length; i++) + { + parameterLog.Append($"{parameters[i].Name} = {arguments[i].ToSafeAbundantString()}, "); + } + + Logger.Error($"[METS]=============Method Exception Termination[MsgStart]============="); + Logger.Error($"Method: {context.Method.DeclaringType?.Name}.{context.Method.Name}"); + Logger.Error($"Method Parameters: {parameterLog.ToString()}"); + Logger.Error($"Exception: {context.Exception.Message} \r\n{context.Exception.StackTrace}"); + Logger.Error($"[METE]=============Method Exception Termination[MsgEnd]==============="); + } + else + { + // 记录日志 + //Logger.Debug($"[MethodExiting] Exiting {context.Method.DeclaringType?.Name}.{context.Method.Name} with return value: {returnValue}"); + } } } } diff --git a/Model/Helper/ClientHotKeyManager.cs b/Model/Helper/ClientHotKeyManager.cs new file mode 100644 index 0000000..80e6596 --- /dev/null +++ b/Model/Helper/ClientHotKeyManager.cs @@ -0,0 +1,153 @@ +using System.Collections.Concurrent; +using System.Diagnostics; +using EnumsNET; +using GlobalHotKey; +using log4net; +using SparkClient.Model.Extension; + +namespace SparkClient.Model.Helper; + +public sealed class ClientHotKeyManager +{ + private static readonly ILog Logger = LogManager.GetLogger(typeof(ClientHotKeyManager)); + #region 单例模式 + private static readonly Lazy _instance = + new Lazy(() => new ClientHotKeyManager()); + public static ClientHotKeyManager Instance => _instance.Value; + private ClientHotKeyManager() { } + #endregion + + #region 存储结构 + private readonly ConcurrentDictionary _hotKeys = + new ConcurrentDictionary(); + private readonly ConcurrentDictionary _manager = + new ConcurrentDictionary(); + // private HotKeyManager _hotKeyManager = new HotKeyManager(); + #endregion + + #region 公共方法 + /// + /// 注册热键 + /// + /// 热键 + /// 事件 + /// 来源类 + /// 非法参数 + /// 重复注册 + public void Register(HotKey hotKey, EventHandler handler, object registrant = null) + { + if (hotKey == null) throw new ArgumentNullException(nameof(hotKey)); + if (handler == null) throw new ArgumentNullException(nameof(handler)); + Logger.Info($"快捷键注册: [ Key = {hotKey.Key.GetName()}, Modifiers = {hotKey.Modifiers.ToSafeAbundantString()}, Handler = {handler.Method.Name}, From = {registrant.GetType().Name}]"); + var record = new HotKeyRecord(hotKey, handler, registrant ?? GetDefaultRegistrant()); + + if (_hotKeys.TryAdd(hotKey, record)) + { + HotKeyManager _hotKeyManager = new HotKeyManager(); + _hotKeyManager.Register(hotKey); + _hotKeyManager.KeyPressed += handler; + _manager.TryAdd(hotKey, _hotKeyManager); + } + else + { + throw new InvalidOperationException($"HotKey {hotKey} already registered!"); + } + } + + /// + /// 释放热键 + /// + /// + public void Unregister(HotKey hotKey) + { + if (_hotKeys.TryRemove(hotKey, out var record)) + { + Logger.Info($"快捷键释放: {hotKey.ToSafeAbundantString()}"); + HotKeyManager _hotKeyManager = _manager.ContainsKey(hotKey)? _manager[hotKey]: new HotKeyManager(); + _hotKeyManager.Unregister(hotKey); + _hotKeyManager.KeyPressed -= record.Handler; + _manager.TryRemove(hotKey, out _); + } + } + /// + /// 热键是否注册 + /// + /// + /// + public bool ContainsHotKey(HotKey hotKey) => _hotKeys.ContainsKey(hotKey); + + /// + /// 刷新热键 + /// + /// + /// + /// + /// + private void RefreshHotKey(HotKey hotKey, EventHandler newHandler, object newRegistrant = null) + { + if (hotKey == null || newHandler == null) throw new ArgumentNullException(); + + var registrant = newRegistrant ?? GetDefaultRegistrant(); + + if (!_manager.ContainsKey(hotKey)) + { + HotKeyManager managerTemp = new HotKeyManager(); + managerTemp.Register(hotKey); + managerTemp.KeyPressed += newHandler; + _manager.TryAdd(hotKey, managerTemp); + } + HotKeyManager _hotKeyManager = _manager.ContainsKey(hotKey)? _manager[hotKey]: null; + _hotKeys.AddOrUpdate( + hotKey, + key => + { + _hotKeyManager.Register(key); + _hotKeyManager.KeyPressed += newHandler; + return new HotKeyRecord(hotKey, newHandler,newRegistrant); + }, + (key, existingRecord) => + { + _hotKeyManager.KeyPressed -= existingRecord.Handler; + _hotKeyManager.KeyPressed += newHandler; + return new HotKeyRecord(hotKey, newHandler,newRegistrant); + }); + } + #endregion + + #region 调试支持 + [Conditional("DEBUG")] + public void PrintDebugInfo() + { + foreach (var kvp in _hotKeys) + { + Debug.WriteLine($"HotKey: {kvp.Key} | Registrant: {kvp.Value.Registrant}"); + } + } + #endregion + + #region 辅助方法 + private object GetDefaultRegistrant() + { + // 获取调用堆栈中的注册者信息(例如:类名+方法名) + var stackTrace = new StackTrace(skipFrames: 2); + var frame = stackTrace.GetFrame(0); + return $"{frame.GetMethod().DeclaringType?.Name}.{frame.GetMethod().Name}"; + } + #endregion + + #region 内部记录类 + private class HotKeyRecord + { + public HotKey HotKey { get; } + public EventHandler Handler { get; } + public object Registrant { get; } + + public HotKeyRecord(HotKey hotKey, EventHandler handler, object registrant) + { + HotKey = hotKey; + Handler = handler; + Registrant = registrant; + } + } + #endregion +} \ No newline at end of file diff --git a/Model/Helper/ClientHotKeys.cs b/Model/Helper/ClientHotKeys.cs new file mode 100644 index 0000000..0a08787 --- /dev/null +++ b/Model/Helper/ClientHotKeys.cs @@ -0,0 +1,24 @@ +using System.Windows.Input; +using GlobalHotKey; + +namespace SparkClient.Model.Helper; + +public class ClientHotKeys +{ + /// + /// 快速开始检测 + /// + public static readonly HotKey QuickAnewDetectHotKey = new HotKey(Key.Q, ModifierKeys.Control | ModifierKeys.Alt); + /// + /// 关闭检测结果页 + /// + public static readonly HotKey CloseResultHotKey = new HotKey(Key.E, ModifierKeys.Control | ModifierKeys.Alt); + /// + /// 检测结果页 切换详细数据页和数据模型页 + /// + public static readonly HotKey SwitchPagesHotKey = new HotKey(Key.D1, ModifierKeys.Control); + /// + /// 心箭图渲染 + /// + public static readonly HotKey ArrowAndHeartHotKey = new HotKey(Key.D2, ModifierKeys.Control); +} \ No newline at end of file diff --git a/Model/Services/SOCClientService.cs b/Model/Services/SOCClientService.cs index e0fbe0d..6ec502e 100644 --- a/Model/Services/SOCClientService.cs +++ b/Model/Services/SOCClientService.cs @@ -68,7 +68,7 @@ namespace SparkClient.Model.Services { Logger.Info($"Request sent to URL: {url}"); client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken); - + client.Timeout = new TimeSpan(0, 0, 5); HttpResponseMessage result = await client.GetAsync(url); // 提前读取内容并存储 diff --git a/ViewModel/BaseWindow/BaseControlVM.cs b/ViewModel/BaseWindow/BaseControlVM.cs index 38218b3..be313e1 100644 --- a/ViewModel/BaseWindow/BaseControlVM.cs +++ b/ViewModel/BaseWindow/BaseControlVM.cs @@ -5,6 +5,7 @@ using HandyControl.Controls; using SparkClient.Model.Helper; using SparkClient.Model.Services; using SparkClient.ViewModel.Grading; +using SparkClient.Views.Grading; using MessageBox = SparkClient.Views.Dialog.MessageBox; namespace SparkClient.ViewModel.BaseWindow; @@ -30,9 +31,6 @@ public class BaseControlVM : BaseViewModel public ICommand NextCommand { get; } - - - /// /// 构造:创建一个带有子页面的模板,并指定子窗口标题,并指定右侧按钮事件内容 /// @@ -64,25 +62,32 @@ public class BaseControlVM : BaseViewModel ShowFunctionButton = Visibility.Hidden; if (vm.GetType().Equals(typeof(GradingResultVM))) { - Application.Current.Dispatcher.Invoke(() => - { - try - { - HotKeyManager _hotKeyManager = new HotKeyManager(); - var hotKey = new HotKey(Key.Q, ModifierKeys.Control | ModifierKeys.Alt); - _hotKeyManager.Register(hotKey); - _hotKeyManager.KeyPressed += OnHotKeyPressed; - - HotKeyManager _hotKeyManagerClose = new HotKeyManager(); - var hotKeyClose = new HotKey(Key.E, ModifierKeys.Control | ModifierKeys.Alt); - _hotKeyManagerClose.Register(hotKeyClose); - _hotKeyManagerClose.KeyPressed += OnHotKeyPressedClose; - } - catch (Exception ex) - { - Logger.Info("设计缺陷:快捷键重复注册"); - } - }); + // Application.Current.Dispatcher.Invoke(() => + // { + // try + // { + // if (_hkmQuickAnewDetect == null) + // { + // _hkmQuickAnewDetect = new HotKeyManager(); + // _hkmQuickAnewDetect.Register(_hkQuickAnewDetect); + // _hkmQuickAnewDetect.KeyPressed += OnHotKeyPressed; + // } + // + // if (_hkmCloseResult == null) + // { + // _hkmCloseResult = new HotKeyManager(); + // _hkmCloseResult.Register(_hkCloseResult); + // _hkmCloseResult.KeyPressed += OnHotKeyPressedClose; + // } + // + // } + // catch (Exception ex) + // { + // Logger.Info($"快捷键注册失败,静默处理:{ex.Message}"); + // } + // }); + ClientHotKeyManager.Instance.Register(ClientHotKeys.QuickAnewDetectHotKey, OnHotKeyPressed, this); + ClientHotKeyManager.Instance.Register(ClientHotKeys.CloseResultHotKey, OnHotKeyPressedClose, this); } else if(vm.GetType().Equals(typeof(GradingLoadingVM))) { @@ -150,6 +155,18 @@ public class BaseControlVM : BaseViewModel WindowManager.PreviousVM(); WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); await SOCClientService.Service.OpenPump(false); + + try + { + ClientHotKeyManager.Instance.Unregister(ClientHotKeys.QuickAnewDetectHotKey); + ClientHotKeyManager.Instance.Unregister(ClientHotKeys.CloseResultHotKey); + ClientHotKeyManager.Instance.Unregister(ClientHotKeys.SwitchPagesHotKey); + ClientHotKeyManager.Instance.Unregister(ClientHotKeys.ArrowAndHeartHotKey); + } + catch (Exception ex) + { + Logger.Info($"快捷键释放失败,静默处理:{ex.Message}"); + } //bool isSaved = (Content as GradingResultVM).isSaved; // if (isSaved) // { diff --git a/ViewModel/Grading/DiamondSelectVM.cs b/ViewModel/Grading/DiamondSelectVM.cs index fe4f4fb..b2f1388 100644 --- a/ViewModel/Grading/DiamondSelectVM.cs +++ b/ViewModel/Grading/DiamondSelectVM.cs @@ -668,7 +668,7 @@ public class DiamondSelectVM : BaseViewModel try { //WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); - Logger.Info($"检测完毕,跳转至结果页面:{param.ToSafeAbundantString()}"); + Logger.Info($"检测完毕,跳转至结果页面:"); BaseControlVM vm = new BaseControlVM(new GradingResultVM(param), MultilingualHelper.getString("DetectionResult")); var ct = param.measurements.VOLUME / 57; vm.WindowTitle = string.IsNullOrWhiteSpace(param.DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {param.DiamondCode}({ct.ToString("F3")}ct)"; diff --git a/ViewModel/Grading/GradingLoadingVM.cs b/ViewModel/Grading/GradingLoadingVM.cs index 8777520..d04cc24 100644 --- a/ViewModel/Grading/GradingLoadingVM.cs +++ b/ViewModel/Grading/GradingLoadingVM.cs @@ -314,7 +314,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable { bool hasErr = false; Logger.Info($"算法运行完毕:{detectTask.Status}"); - Logger.Info($"算法运行结果:{detectTask.Result.ToSafeAbundantString()}"); + Logger.Info($"算法运行结果:[Status = {detectTask.Result.Status}; Message = {detectTask.Result.ErrorMsg}]"); try { CompleteProgressQuicklyAsync(); @@ -339,6 +339,14 @@ public class GradingLoadingVM : BaseViewModel,IDisposable new MessageBox().Show(MultilingualHelper.getString("NoDiamond")); hasErr = true; return -1; + case "DETECTING_EXCEPTION": + new MessageBox().Show(MultilingualHelper.getString("DETECTING_EXCEPTION") + detectTask.Result.ErrorMsg); + hasErr = true; + return -1; + case "DETECTING_RESULT_ISNULL": + new MessageBox().Show(MultilingualHelper.getString("DETECTING_RESULT_ISNULL") + detectTask.Result.ErrorMsg); + hasErr = true; + return -1; } Progress = (100.00); diff --git a/Views/Grading/GradingResult.xaml.cs b/Views/Grading/GradingResult.xaml.cs index 84dc182..92b4be6 100644 --- a/Views/Grading/GradingResult.xaml.cs +++ b/Views/Grading/GradingResult.xaml.cs @@ -5,7 +5,9 @@ using System.Windows.Forms.VisualStyles; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; +using GlobalHotKey; using log4net; +using SparkClient.Model.Helper; using SparkClient.ViewModel.Grading; using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D; @@ -20,6 +22,10 @@ public partial class GradingResult // 用于记录当前所有已存在的Popup private List _allPopups = new List(); + + //快捷键 + // private HotKeyManager? _hkmSwitchPages = null; + // public static readonly HotKey _hkSwitchPages = new HotKey(Key.D1, ModifierKeys.Control); public GradingResult() { InitializeComponent(); @@ -27,6 +33,13 @@ public partial class GradingResult // 在Window最外层捕获鼠标点击,判断是否点击在Popup之外,如果是则关闭所有Popup this.PreviewMouseLeftButtonDown += Window_PreviewMouseLeftButtonDown; //DataContext = new GradingResultVM(null); + ClientHotKeyManager.Instance.Register(ClientHotKeys.SwitchPagesHotKey, OnHotKeyPressed, this); + // if (_hkmSwitchPages == null) + // { + // _hkmSwitchPages = new HotKeyManager(); + // _hkmSwitchPages.Register(_hkSwitchPages); + // _hkmSwitchPages.KeyPressed += OnHotKeyPressed; + // } // this.Viewport3Dx.EffectsManager = new DefaultEffectsManager(); // this.Viewport3Dx.Camera = new PerspectiveCamera() @@ -44,7 +57,13 @@ public partial class GradingResult // triangles.AddRange(entities); // }; } + + + private void OnHotKeyPressed(object sender, KeyPressedEventArgs e) + { + ButtonBase_OnClick(sender, null); + } /// /// 点击模型 diff --git a/Views/UserControl/Viewport3D.xaml.cs b/Views/UserControl/Viewport3D.xaml.cs index 628345c..baa61cc 100644 --- a/Views/UserControl/Viewport3D.xaml.cs +++ b/Views/UserControl/Viewport3D.xaml.cs @@ -17,6 +17,7 @@ using SharpDX.Direct3D11; using SharpDX.DXGI; using MathNet.Numerics; using System.Windows.Media; +using GlobalHotKey; using NPOI.SS.Formula.Functions; using SparkClient.Model.Services; using MessageBox = SparkClient.Views.Dialog.MessageBox; @@ -36,6 +37,8 @@ public partial class Viewport3D Viewport3Dx.ShowViewCube = false; Viewport3Dx.ShowCoordinateSystem = false; ViewportManager.SetViewport3D(Viewport3Dx); + + ClientHotKeyManager.Instance.Register(ClientHotKeys.ArrowAndHeartHotKey, ShowArrowAndHeart, this); } /// @@ -280,15 +283,8 @@ public partial class Viewport3D break; case "BtnShow3DView": // ObjExporter.ExportToObj2(ViewportManager.ViewportTriangle, @"D:\id03.obj"); - try - { - RayHelper.GenerateRender(ViewportManager.ViewportTriangle.First().TriangleCode, "123"); - } - catch (Exception ex) - { - new MessageBox().Show(ex.Message); - } + ShowArrowAndHeart(sender, null); break; } @@ -356,6 +352,18 @@ public partial class Viewport3D } + private void ShowArrowAndHeart(object sender, KeyPressedEventArgs e) + { + try + { + RayHelper.GenerateRender(ViewportManager.ViewportTriangle.First().TriangleCode, "123"); + } + catch (Exception ex) + { + new MessageBox().Show(ex.Message); + } + } + // private void BtnDirection_OnClick(object sender, RoutedEventArgs e) // { // var directionName = ((Button)sender).Name.ToString();