feat: HotKey and Logs optimize

master
Tongg 9 months ago
parent ce3563e2e0
commit 5e21cb8788
  1. 3
      Language/en_US.xaml
  2. 2
      Language/zh_CN.xaml
  3. 29
      Model/Attributes/LogAttribute.cs
  4. 153
      Model/Helper/ClientHotKeyManager.cs
  5. 24
      Model/Helper/ClientHotKeys.cs
  6. 2
      Model/Services/SOCClientService.cs
  7. 61
      ViewModel/BaseWindow/BaseControlVM.cs
  8. 2
      ViewModel/Grading/DiamondSelectVM.cs
  9. 10
      ViewModel/Grading/GradingLoadingVM.cs
  10. 19
      Views/Grading/GradingResult.xaml.cs
  11. 24
      Views/UserControl/Viewport3D.xaml.cs

@ -200,6 +200,9 @@
<sys:String x:Key="Recheck">P021: Diamond requires cleaning</sys:String> <sys:String x:Key="Recheck">P021: Diamond requires cleaning</sys:String>
<sys:String x:Key="NoDiamond">P011: No diamond detected</sys:String> <sys:String x:Key="NoDiamond">P011: No diamond detected</sys:String>
<sys:String x:Key="OpenOfTheHatch">Please check if the cutting tool door is closed</sys:String> <sys:String x:Key="OpenOfTheHatch">Please check if the cutting tool door is closed</sys:String>
<sys:String x:Key="DETECTING_EXCEPTION">The algorithm is running abnormally:</sys:String>
<sys:String x:Key="DETECTING_RESULT_ISNULL">The test result is empty:</sys:String>
<sys:String x:Key="ApplicationError">Application error:</sys:String> <sys:String x:Key="ApplicationError">Application error:</sys:String>

@ -202,6 +202,8 @@
<sys:String x:Key="Recheck">P021:检测到钻石需进行清洁</sys:String> <sys:String x:Key="Recheck">P021:检测到钻石需进行清洁</sys:String>
<sys:String x:Key="NoDiamond">P011:未检测到钻石</sys:String> <sys:String x:Key="NoDiamond">P011:未检测到钻石</sys:String>
<sys:String x:Key="OpenOfTheHatch">S007:请检查切工仪设备舱门是否关闭</sys:String> <sys:String x:Key="OpenOfTheHatch">S007:请检查切工仪设备舱门是否关闭</sys:String>
<sys:String x:Key="DETECTING_EXCEPTION">算法运行异常:</sys:String>
<sys:String x:Key="DETECTING_RESULT_ISNULL">检测结果为空:</sys:String>
<sys:String x:Key="ApplicationError">应用程序出现错误:</sys:String> <sys:String x:Key="ApplicationError">应用程序出现错误:</sys:String>

@ -4,6 +4,7 @@ using Rougamo;
using Rougamo.Context; using Rougamo.Context;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using SparkClient.Model.Extension;
namespace SparkClient.Model.Attributes 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) public override void OnExit(MethodContext context)
{ {
//Logger.Debug($"Exiting {context.Method.DeclaringType?.Name}.{context.Method.Name}"); //Logger.Debug($"Exiting {context.Method.DeclaringType?.Name}.{context.Method.Name}");
// 获取返回值
var returnValue = context.ReturnValue; 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}");
}
} }
} }
} }

@ -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<ClientHotKeyManager> _instance =
new Lazy<ClientHotKeyManager>(() => new ClientHotKeyManager());
public static ClientHotKeyManager Instance => _instance.Value;
private ClientHotKeyManager() { }
#endregion
#region 存储结构
private readonly ConcurrentDictionary<HotKey, HotKeyRecord> _hotKeys =
new ConcurrentDictionary<HotKey, HotKeyRecord>();
private readonly ConcurrentDictionary<HotKey, HotKeyManager> _manager =
new ConcurrentDictionary<HotKey, HotKeyManager>();
// private HotKeyManager _hotKeyManager = new HotKeyManager();
#endregion
#region 公共方法
/// <summary>
/// 注册热键
/// </summary>
/// <param name="hotKey">热键</param>
/// <param name="handler">事件</param>
/// <param name="registrant">来源类</param>
/// <exception cref="ArgumentNullException">非法参数</exception>
/// <exception cref="InvalidOperationException">重复注册</exception>
public void Register(HotKey hotKey, EventHandler<KeyPressedEventArgs> 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!");
}
}
/// <summary>
/// 释放热键
/// </summary>
/// <param name="hotKey"></param>
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 _);
}
}
/// <summary>
/// 热键是否注册
/// </summary>
/// <param name="hotKey"></param>
/// <returns></returns>
public bool ContainsHotKey(HotKey hotKey) => _hotKeys.ContainsKey(hotKey);
/// <summary>
/// 刷新热键
/// </summary>
/// <param name="hotKey"></param>
/// <param name="newHandler"></param>
/// <param name="newRegistrant"></param>
/// <exception cref="ArgumentNullException"></exception>
private void RefreshHotKey(HotKey hotKey, EventHandler<KeyPressedEventArgs> 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<KeyPressedEventArgs> Handler { get; }
public object Registrant { get; }
public HotKeyRecord(HotKey hotKey, EventHandler<KeyPressedEventArgs> handler, object registrant)
{
HotKey = hotKey;
Handler = handler;
Registrant = registrant;
}
}
#endregion
}

@ -0,0 +1,24 @@
using System.Windows.Input;
using GlobalHotKey;
namespace SparkClient.Model.Helper;
public class ClientHotKeys
{
/// <summary>
/// 快速开始检测
/// </summary>
public static readonly HotKey QuickAnewDetectHotKey = new HotKey(Key.Q, ModifierKeys.Control | ModifierKeys.Alt);
/// <summary>
/// 关闭检测结果页
/// </summary>
public static readonly HotKey CloseResultHotKey = new HotKey(Key.E, ModifierKeys.Control | ModifierKeys.Alt);
/// <summary>
/// 检测结果页 切换详细数据页和数据模型页
/// </summary>
public static readonly HotKey SwitchPagesHotKey = new HotKey(Key.D1, ModifierKeys.Control);
/// <summary>
/// 心箭图渲染
/// </summary>
public static readonly HotKey ArrowAndHeartHotKey = new HotKey(Key.D2, ModifierKeys.Control);
}

@ -68,7 +68,7 @@ namespace SparkClient.Model.Services
{ {
Logger.Info($"Request sent to URL: {url}"); Logger.Info($"Request sent to URL: {url}");
client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken); client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken);
client.Timeout = new TimeSpan(0, 0, 5);
HttpResponseMessage result = await client.GetAsync(url); HttpResponseMessage result = await client.GetAsync(url);
// 提前读取内容并存储 // 提前读取内容并存储

@ -5,6 +5,7 @@ using HandyControl.Controls;
using SparkClient.Model.Helper; using SparkClient.Model.Helper;
using SparkClient.Model.Services; using SparkClient.Model.Services;
using SparkClient.ViewModel.Grading; using SparkClient.ViewModel.Grading;
using SparkClient.Views.Grading;
using MessageBox = SparkClient.Views.Dialog.MessageBox; using MessageBox = SparkClient.Views.Dialog.MessageBox;
namespace SparkClient.ViewModel.BaseWindow; namespace SparkClient.ViewModel.BaseWindow;
@ -30,9 +31,6 @@ public class BaseControlVM : BaseViewModel
public ICommand NextCommand { get; } public ICommand NextCommand { get; }
/// <summary> /// <summary>
/// 构造:创建一个带有子页面的模板,并指定子窗口标题,并指定右侧按钮事件内容 /// 构造:创建一个带有子页面的模板,并指定子窗口标题,并指定右侧按钮事件内容
/// </summary> /// </summary>
@ -64,25 +62,32 @@ public class BaseControlVM : BaseViewModel
ShowFunctionButton = Visibility.Hidden; ShowFunctionButton = Visibility.Hidden;
if (vm.GetType().Equals(typeof(GradingResultVM))) if (vm.GetType().Equals(typeof(GradingResultVM)))
{ {
Application.Current.Dispatcher.Invoke(() => // Application.Current.Dispatcher.Invoke(() =>
{ // {
try // try
{ // {
HotKeyManager _hotKeyManager = new HotKeyManager(); // if (_hkmQuickAnewDetect == null)
var hotKey = new HotKey(Key.Q, ModifierKeys.Control | ModifierKeys.Alt); // {
_hotKeyManager.Register(hotKey); // _hkmQuickAnewDetect = new HotKeyManager();
_hotKeyManager.KeyPressed += OnHotKeyPressed; // _hkmQuickAnewDetect.Register(_hkQuickAnewDetect);
// _hkmQuickAnewDetect.KeyPressed += OnHotKeyPressed;
HotKeyManager _hotKeyManagerClose = new HotKeyManager(); // }
var hotKeyClose = new HotKey(Key.E, ModifierKeys.Control | ModifierKeys.Alt); //
_hotKeyManagerClose.Register(hotKeyClose); // if (_hkmCloseResult == null)
_hotKeyManagerClose.KeyPressed += OnHotKeyPressedClose; // {
} // _hkmCloseResult = new HotKeyManager();
catch (Exception ex) // _hkmCloseResult.Register(_hkCloseResult);
{ // _hkmCloseResult.KeyPressed += OnHotKeyPressedClose;
Logger.Info("设计缺陷:快捷键重复注册"); // }
} //
}); // }
// 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))) else if(vm.GetType().Equals(typeof(GradingLoadingVM)))
{ {
@ -150,6 +155,18 @@ public class BaseControlVM : BaseViewModel
WindowManager.PreviousVM(); WindowManager.PreviousVM();
WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); WindowManager.mainViewModel.Content = WindowManager.PreviousVM();
await SOCClientService.Service.OpenPump(false); 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; //bool isSaved = (Content as GradingResultVM).isSaved;
// if (isSaved) // if (isSaved)
// { // {

@ -668,7 +668,7 @@ public class DiamondSelectVM : BaseViewModel
try try
{ {
//WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); //WindowManager.mainViewModel.Content = WindowManager.PreviousVM();
Logger.Info($"检测完毕,跳转至结果页面:{param.ToSafeAbundantString()}"); Logger.Info($"检测完毕,跳转至结果页面:");
BaseControlVM vm = new BaseControlVM(new GradingResultVM(param), MultilingualHelper.getString("DetectionResult")); BaseControlVM vm = new BaseControlVM(new GradingResultVM(param), MultilingualHelper.getString("DetectionResult"));
var ct = param.measurements.VOLUME / 57; var ct = param.measurements.VOLUME / 57;
vm.WindowTitle = string.IsNullOrWhiteSpace(param.DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {param.DiamondCode}({ct.ToString("F3")}ct)"; vm.WindowTitle = string.IsNullOrWhiteSpace(param.DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {param.DiamondCode}({ct.ToString("F3")}ct)";

@ -314,7 +314,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable
{ {
bool hasErr = false; bool hasErr = false;
Logger.Info($"算法运行完毕:{detectTask.Status}"); Logger.Info($"算法运行完毕:{detectTask.Status}");
Logger.Info($"算法运行结果:{detectTask.Result.ToSafeAbundantString()}"); Logger.Info($"算法运行结果:[Status = {detectTask.Result.Status}; Message = {detectTask.Result.ErrorMsg}]");
try try
{ {
CompleteProgressQuicklyAsync(); CompleteProgressQuicklyAsync();
@ -339,6 +339,14 @@ public class GradingLoadingVM : BaseViewModel,IDisposable
new MessageBox().Show(MultilingualHelper.getString("NoDiamond")); new MessageBox().Show(MultilingualHelper.getString("NoDiamond"));
hasErr = true; hasErr = true;
return -1; 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); Progress = (100.00);

@ -5,7 +5,9 @@ using System.Windows.Forms.VisualStyles;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using GlobalHotKey;
using log4net; using log4net;
using SparkClient.Model.Helper;
using SparkClient.ViewModel.Grading; using SparkClient.ViewModel.Grading;
using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D; using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D;
@ -20,6 +22,10 @@ public partial class GradingResult
// 用于记录当前所有已存在的Popup // 用于记录当前所有已存在的Popup
private List<Popup> _allPopups = new List<Popup>(); private List<Popup> _allPopups = new List<Popup>();
//快捷键
// private HotKeyManager? _hkmSwitchPages = null;
// public static readonly HotKey _hkSwitchPages = new HotKey(Key.D1, ModifierKeys.Control);
public GradingResult() public GradingResult()
{ {
InitializeComponent(); InitializeComponent();
@ -27,6 +33,13 @@ public partial class GradingResult
// 在Window最外层捕获鼠标点击,判断是否点击在Popup之外,如果是则关闭所有Popup // 在Window最外层捕获鼠标点击,判断是否点击在Popup之外,如果是则关闭所有Popup
this.PreviewMouseLeftButtonDown += Window_PreviewMouseLeftButtonDown; this.PreviewMouseLeftButtonDown += Window_PreviewMouseLeftButtonDown;
//DataContext = new GradingResultVM(null); //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.EffectsManager = new DefaultEffectsManager();
// this.Viewport3Dx.Camera = new PerspectiveCamera() // this.Viewport3Dx.Camera = new PerspectiveCamera()
@ -46,6 +59,12 @@ public partial class GradingResult
} }
private void OnHotKeyPressed(object sender, KeyPressedEventArgs e)
{
ButtonBase_OnClick(sender, null);
}
/// <summary> /// <summary>
/// 点击模型 /// 点击模型
/// </summary> /// </summary>

@ -17,6 +17,7 @@ using SharpDX.Direct3D11;
using SharpDX.DXGI; using SharpDX.DXGI;
using MathNet.Numerics; using MathNet.Numerics;
using System.Windows.Media; using System.Windows.Media;
using GlobalHotKey;
using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.Functions;
using SparkClient.Model.Services; using SparkClient.Model.Services;
using MessageBox = SparkClient.Views.Dialog.MessageBox; using MessageBox = SparkClient.Views.Dialog.MessageBox;
@ -36,6 +37,8 @@ public partial class Viewport3D
Viewport3Dx.ShowViewCube = false; Viewport3Dx.ShowViewCube = false;
Viewport3Dx.ShowCoordinateSystem = false; Viewport3Dx.ShowCoordinateSystem = false;
ViewportManager.SetViewport3D(Viewport3Dx); ViewportManager.SetViewport3D(Viewport3Dx);
ClientHotKeyManager.Instance.Register(ClientHotKeys.ArrowAndHeartHotKey, ShowArrowAndHeart, this);
} }
/// <summary> /// <summary>
@ -280,15 +283,8 @@ public partial class Viewport3D
break; break;
case "BtnShow3DView": case "BtnShow3DView":
// ObjExporter.ExportToObj2(ViewportManager.ViewportTriangle, @"D:\id03.obj"); // 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; 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) // private void BtnDirection_OnClick(object sender, RoutedEventArgs e)
// { // {
// var directionName = ((Button)sender).Name.ToString(); // var directionName = ((Button)sender).Name.ToString();

Loading…
Cancel
Save