diff --git a/App.config b/App.config index ae9b93b..4ba9578 100644 --- a/App.config +++ b/App.config @@ -2,24 +2,20 @@ - + - - - - - + - + diff --git a/Language/zh_CN.xaml b/Language/zh_CN.xaml index 4c77196..54fb6a7 100644 --- a/Language/zh_CN.xaml +++ b/Language/zh_CN.xaml @@ -155,6 +155,7 @@ 保存失败 选择路径 重置网格线 + 切工仪旋转至此面 星辉钻石检测系统 diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 2a56d19..51e5b0e 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -11,6 +11,7 @@ using HandyControl.Tools; using log4net; using log4net.Config; using SparkClient.Model.Helper; +using SparkClient.Model.Services; using SparkClient.ViewModel; using SparkClient.ViewModel.BaseWindow; using SparkClient.Views.BaseWindow; @@ -142,7 +143,7 @@ public partial class MainWindow } - private void MainWindow_OnClosing(object? sender, CancelEventArgs e) + private async void MainWindow_OnClosing(object? sender, CancelEventArgs e) { var message = MultilingualHelper.getString("ExitAsk"); var title = MultilingualHelper.getString("ExitAskTitle"); @@ -152,6 +153,7 @@ public partial class MainWindow if (result == MessageBoxResult.OK) { + await SOCClientService.Service.OpenPump(false); DataBaseHelper.CloseConnection(); // this.Close(); Environment.Exit(0); diff --git a/Model/Entity/ApiEntity/AlgorithmResultEntity.cs b/Model/Entity/ApiEntity/AlgorithmResultEntity.cs index 86855ce..0de7f97 100644 --- a/Model/Entity/ApiEntity/AlgorithmResultEntity.cs +++ b/Model/Entity/ApiEntity/AlgorithmResultEntity.cs @@ -39,6 +39,10 @@ namespace SparkClient.Model.Entity.ApiEntity /// 面的类型。 /// public int facet_type { get; set; } + /// + /// 旋转角度 + /// + public double theta { get; set; } } /// @@ -330,6 +334,10 @@ namespace SparkClient.Model.Entity.ApiEntity /// 扭曲度详细信息。 /// public TwistDetail TWIST_DETAIL { get; set; } + + public StarAngleDetail STAR_ANGLE_DETAIL { get; set; } + public UpperHalfAngleDetail UPPER_HALF_ANGLE_DETAIL { get; set; } + public LowerHalfAngleDetail LOWER_HALF_ANGLE_DETAIL { get; set; } } /// @@ -865,4 +873,50 @@ namespace SparkClient.Model.Entity.ApiEntity public double TWIST_8 { get; set; } } + public class StarAngleDetail { + public double STAR_ANGLE_1 { get; set; } + public double STAR_ANGLE_2 { get; set; } + public double STAR_ANGLE_3 { get; set; } + public double STAR_ANGLE_4 { get; set; } + public double STAR_ANGLE_5 { get; set; } + public double STAR_ANGLE_6 { get; set; } + public double STAR_ANGLE_7 { get; set; } + public double STAR_ANGLE_8 { get; set; } + } + public class UpperHalfAngleDetail { + public double UPPER_HALF_ANGLE_1 { get; set; } + public double UPPER_HALF_ANGLE_2 { get; set; } + public double UPPER_HALF_ANGLE_3 { get; set; } + public double UPPER_HALF_ANGLE_4 { get; set; } + public double UPPER_HALF_ANGLE_5 { get; set; } + public double UPPER_HALF_ANGLE_6 { get; set; } + public double UPPER_HALF_ANGLE_7 { get; set; } + public double UPPER_HALF_ANGLE_8 { get; set; } + public double UPPER_HALF_ANGLE_9 { get; set; } + public double UPPER_HALF_ANGLE_10 { get; set; } + public double UPPER_HALF_ANGLE_11 { get; set; } + public double UPPER_HALF_ANGLE_12 { get; set; } + public double UPPER_HALF_ANGLE_13 { get; set; } + public double UPPER_HALF_ANGLE_14 { get; set; } + public double UPPER_HALF_ANGLE_15 { get; set; } + public double UPPER_HALF_ANGLE_16 { get; set; } + } + public class LowerHalfAngleDetail { + public double LOWER_HALF_ANGLE_1 { get; set; } + public double LOWER_HALF_ANGLE_2 { get; set; } + public double LOWER_HALF_ANGLE_3 { get; set; } + public double LOWER_HALF_ANGLE_4 { get; set; } + public double LOWER_HALF_ANGLE_5 { get; set; } + public double LOWER_HALF_ANGLE_6 { get; set; } + public double LOWER_HALF_ANGLE_7 { get; set; } + public double LOWER_HALF_ANGLE_8 { get; set; } + public double LOWER_HALF_ANGLE_9 { get; set; } + public double LOWER_HALF_ANGLE_10 { get; set; } + public double LOWER_HALF_ANGLE_11 { get; set; } + public double LOWER_HALF_ANGLE_12 { get; set; } + public double LOWER_HALF_ANGLE_13 { get; set; } + public double LOWER_HALF_ANGLE_14 { get; set; } + public double LOWER_HALF_ANGLE_15 { get; set; } + public double LOWER_HALF_ANGLE_16 { get; set; } + } } diff --git a/Model/Entity/ApiEntity/StatusCodes.cs b/Model/Entity/ApiEntity/StatusCodes.cs index 97948d8..799c661 100644 --- a/Model/Entity/ApiEntity/StatusCodes.cs +++ b/Model/Entity/ApiEntity/StatusCodes.cs @@ -32,6 +32,12 @@ namespace SparkClient.Model.Common // 切工仪舱门未关闭 public const string OpenOfTheHatch = "S007"; + + /// + /// 输出参数错误或者未定义 + /// + public const string OutputParameterNotProvidedOrIncorrect = "S008"; + public const string PreviousTaskIncomplete = "S009"; // 未找到切工仪 public const string DeviceNotFound = "P001"; diff --git a/Model/Services/SOCClientService.cs b/Model/Services/SOCClientService.cs index 3d0de64..cecc375 100644 --- a/Model/Services/SOCClientService.cs +++ b/Model/Services/SOCClientService.cs @@ -21,7 +21,7 @@ namespace SparkClient.Model.Services public class SOCClientService { // Log地址 - private const string LogFilePath = @"..\..\..\Resource\Document\log.txt"; + private static readonly ILog Logger = LogManager.GetLogger(typeof(SOCClientService)); @@ -35,10 +35,23 @@ namespace SparkClient.Model.Services /// private readonly string _authToken; + private static SOCClientService _service; + + public static SOCClientService Service { + get + { + if (_service == null) + _service = new SOCClientService(); + return _service; + } + + } + + private bool GenImage; /// /// 构造函数,初始化基础URL和认证令牌。 /// - public SOCClientService() + private SOCClientService() { _baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; _authToken = "your_basic_auth_token"; @@ -53,8 +66,36 @@ namespace SparkClient.Model.Services { using (var client = new HttpClient()) { + Logger.Info($"Request sent to URL: {url}"); + client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken); + + HttpResponseMessage result = await client.GetAsync(url); + + // 提前读取内容并存储 + string responseBody = await result.Content.ReadAsStringAsync(); + int statusCode = (int)result.StatusCode; + // 记录日志 + Logger.Info($"Response: Status={statusCode}, Body={responseBody}"); + var tempEntity = JsonConvert.DeserializeObject(responseBody); + if (StatusCodes.PreviousTaskIncomplete.Equals(tempEntity.Status)) + { + Logger.Info($"S009 请求重试"); + await Task.Delay(50); + return await SendGetRequestAsync(url); + } + result.Content = new StringContent(responseBody); + return result; + } + } + private async Task SendGetRequestImageAsync(string url) + { + using (var client = new HttpClient()) + { + Logger.Info($"Request sent to URL: {url}"); client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken); + return await client.GetAsync(url); + } } @@ -66,6 +107,7 @@ namespace SparkClient.Model.Services { try { + GenImage = true; // 光照度和半圆 int lightLevel = 0; string halfCircle = string.Empty; @@ -77,6 +119,7 @@ namespace SparkClient.Model.Services { throw new Exception("No data found for the specified keys."); } + foreach (DataRow row in table.Rows) { string key = row["Key"].ToString() ?? string.Empty; @@ -91,14 +134,14 @@ namespace SparkClient.Model.Services halfCircle = value; // 半圆 } } - + string url = $"{_baseUrl}/collect_images?light_level={lightLevel}&half_circle={halfCircle}"; - + var response = await SendGetRequestAsync(url); if (!response.IsSuccessStatusCode) { - return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List()}; + return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() }; } var jsonResponse = await response.Content.ReadAsStringAsync(); @@ -106,10 +149,12 @@ namespace SparkClient.Model.Services if (result == null) { - return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List()}; + return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() }; } - return new SocResultEntity { Status = result.Status, Images = new List() , DeviceId = result.device_id}; - + + return new SocResultEntity + { Status = result.Status, Images = new List(), DeviceId = result.device_id }; + } catch (Exception ex) { @@ -118,7 +163,12 @@ namespace SparkClient.Model.Services Logger.Warn($"Error in DoSoc: {ex.Message}"); // 或者使用日志框架记录日志 // logger.LogError(ex, "Error in DoSoc method."); - return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() , DeviceId = ""}; + return new SocResultEntity + { Status = StatusCodes.DeviceNotFound, Images = new List(), DeviceId = "" }; + } + finally + { + GenImage = false; } } @@ -137,7 +187,7 @@ namespace SparkClient.Model.Services string url = $"{_baseUrl}/retrieve_image/{imageIndex}"; try { - var response = await SendGetRequestAsync(url); + var response = await SendGetRequestImageAsync(url); int status = (int)response.StatusCode; switch (status) @@ -201,11 +251,12 @@ namespace SparkClient.Model.Services try { var response = await SendGetRequestAsync(url); - + Logger.Debug($" CollectStatusAsync url :{ url} "); if (response.IsSuccessStatusCode) { var jsonResponse = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject(jsonResponse); + Logger.Debug($" CollectStatusAsync result :{ result} "); return result.Status; } @@ -244,6 +295,7 @@ namespace SparkClient.Model.Services // 启动任务接口 SocResultEntity entity = await CollectImagesAsync(); // 成功 + Logger.Debug($"entity :{entity.Status} {entity.ToString()} "); if (entity.Status != StatusCodes.Success) { // 启动任务失败 @@ -257,11 +309,13 @@ namespace SparkClient.Model.Services // 成功 if (acquisitionStatus != StatusCodes.Success) { + Logger.Debug($"acquisitionStatus != StatusCodes.Success : {acquisitionStatus}"); // 采集状态失败 return new SocResultEntity { Status = acquisitionStatus, Images = new List() }; } if (imageNames.Count == 0) { + Logger.Debug("imageNames.Count == 0"); // 图片文件读取失败 return new SocResultEntity { Status = StatusCodes.ImageFileReadFailure, Images = new List() }; } @@ -298,6 +352,67 @@ namespace SparkClient.Model.Services } } + public async Task CutRevolve(double angle) + { + // await OpenPump(true); + int param = (int)angle * 100; + string url = $"{_baseUrl}/rotate_to?angle={param}"; + // if(GenImage) return StatusCodes.DeviceNotFound; + GenImage = true; + try + { + var response = await SendGetRequestAsync(url); + Logger.Debug(url); + if (response.IsSuccessStatusCode) + { + var jsonResponse = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject(jsonResponse); + Logger.Debug(result); + return result.Status; + } + + return StatusCodes.DeviceNotFound; + } + catch (Exception e) + { + string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] 发生异常: {e.Message}{Environment.NewLine}"; + Logger.Error(logMessage); + return StatusCodes.DeviceNotFound; + } + finally + { + GenImage = false; + // await OpenPump(true); + } + } + + public async Task OpenPump(bool isOpen) + { + // if(GenImage) return StatusCodes.DeviceNotFound; + int param = isOpen ? 1 : 0 ; + string url = $"{_baseUrl}/set_pump?on={param}"; + Logger.Debug(url); + try + { + var response = await SendGetRequestAsync(url); + + if (response.IsSuccessStatusCode) + { + var jsonResponse = await response.Content.ReadAsStringAsync(); + var result = JsonConvert.DeserializeObject(jsonResponse); + Logger.Debug(result.Status); + return result.Status; + } + + return StatusCodes.DeviceNotFound; + } + catch (Exception e) + { + string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] 发生异常: {e.Message}{Environment.NewLine}"; + Logger.Error(logMessage); + return StatusCodes.DeviceNotFound; + } + } } diff --git a/SparkClient.csproj b/SparkClient.csproj index 1319731..21de682 100644 --- a/SparkClient.csproj +++ b/SparkClient.csproj @@ -258,6 +258,11 @@ Wpf Designer + + MSBuild:Compile + Wpf + Designer + diff --git a/ViewModel/BaseWindow/BaseControlVM.cs b/ViewModel/BaseWindow/BaseControlVM.cs index e40d751..56b8bd4 100644 --- a/ViewModel/BaseWindow/BaseControlVM.cs +++ b/ViewModel/BaseWindow/BaseControlVM.cs @@ -3,6 +3,7 @@ using System.Windows.Input; using GlobalHotKey; using HandyControl.Controls; using SparkClient.Model.Helper; +using SparkClient.Model.Services; using SparkClient.ViewModel.Grading; using MessageBox = SparkClient.Views.Dialog.MessageBox; namespace SparkClient.ViewModel.BaseWindow; @@ -142,27 +143,31 @@ public class BaseControlVM : BaseViewModel /// 关闭并退回至上一个页面 /// /// - public void CloseVM(object parameter) + public async void CloseVM(object parameter) { if(Content is GradingResultVM) { - bool isSaved = (Content as GradingResultVM).isSaved; - if (isSaved) - { - WindowManager.PreviousVM(); - WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); - } - else { - // 部署改造:2 - WindowManager.PreviousVM(); - WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); - // MessageBox message = new MessageBox(); - // MessageBoxResult result = message.ShowAsk(MultilingualHelper.getString("DiamodResultCloseConfirm")); - // if (MessageBoxResult.OK.Equals(result)) - // { - // WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); - // } - } + WindowManager.PreviousVM(); + WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); + await SOCClientService.Service.OpenPump(false); + //bool isSaved = (Content as GradingResultVM).isSaved; + // if (isSaved) + // { + // + // } + // else { + // // 部署改造:2 + // WindowManager.PreviousVM(); + // WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); + // var _socClientService = new SOCClientService(); + // _socClientService.OpenPump(false); + // // MessageBox message = new MessageBox(); + // // MessageBoxResult result = message.ShowAsk(MultilingualHelper.getString("DiamodResultCloseConfirm")); + // // if (MessageBoxResult.OK.Equals(result)) + // // { + // // WindowManager.mainViewModel.Content = WindowManager.PreviousVM(); + // // } + // } } else { diff --git a/ViewModel/Grading/DiamondSelectVM.cs b/ViewModel/Grading/DiamondSelectVM.cs index 1a9d020..e91f229 100644 --- a/ViewModel/Grading/DiamondSelectVM.cs +++ b/ViewModel/Grading/DiamondSelectVM.cs @@ -207,6 +207,7 @@ public class DiamondSelectVM : BaseViewModel else { //正常模式 + var loadingView = new GradingLoadingVM(param.ToString(), DiamondCode); BaseControlVM vm = new BaseControlVM(loadingView, MultilingualHelper.getString("wait")); vm.WindowTitle = string.IsNullOrWhiteSpace(DiamondCode) ? vm.WindowTitle : $"{vm.WindowTitle} - {DiamondCode}"; diff --git a/ViewModel/Grading/GradingLoadingVM.cs b/ViewModel/Grading/GradingLoadingVM.cs index 040a908..389288c 100644 --- a/ViewModel/Grading/GradingLoadingVM.cs +++ b/ViewModel/Grading/GradingLoadingVM.cs @@ -24,7 +24,6 @@ namespace SparkClient.ViewModel.Grading; public class GradingLoadingVM : BaseViewModel,IDisposable { private double _progress; - private SOCClientService _socClientService; public AlgorithmResultEntity Parameter; /// /// 进度 @@ -134,12 +133,13 @@ public class GradingLoadingVM : BaseViewModel,IDisposable /// /// 开始检测 /// + //[Log] public async Task Start(int type = 0) { try { - + var progress = RunProgressAsync(_progressCts.Token); if (type == 11) @@ -166,10 +166,19 @@ public class GradingLoadingVM : BaseViewModel,IDisposable } } - if(type == 0){ - _socClientService = new SOCClientService(); - var processImage = _socClientService.ProcessImageCollectionAsync(); + if(type == 0) + { + + await SOCClientService.Service.OpenPump(true); + // if (!StatusCodes.Success.Equals(openpupmStatus)) + // { + // new MessageBox().Show("气泵开启失败!"); + // return -1; + // } + + var processImage = SOCClientService.Service.ProcessImageCollectionAsync(); //通知页面可以播放图片 + await processImage; if (!("ok".Equals(processImage.Result.Status) || "S000".Equals(processImage.Result.Status))) @@ -182,14 +191,28 @@ public class GradingLoadingVM : BaseViewModel,IDisposable LoadImages(processImage.Result.Images); } + string strImageModeImagePath = string.Empty; if (type == 1) { - List mnFiles = new List(); - for (int i = 0; i < 100; i++) + ImageSelect jsonImport = new ImageSelect(); + bool? a = jsonImport.ShowDialog(); + if (a ?? false) { - mnFiles.Add($"{i}.bmp"); + strImageModeImagePath = jsonImport.FilePath.Text; + string name = jsonImport.FileName.Text; + List mnFiles = new List(); + for (int i = 0; i < 100; i++) + { + mnFiles.Add(name.Replace("%d", i.ToString())); + } + LoadImages(mnFiles); } - LoadImages(mnFiles); + else + { + return -1; + } + + } ImageIsEnable = true; @@ -207,11 +230,18 @@ public class GradingLoadingVM : BaseViewModel,IDisposable var _algorithmConfigVM = new AlgorithmConfigVM(); _algorithmConfigVM.InitAlgorithmData(null); string algo_config = _algorithmConfigVM.AlgorithmConfigJson; - - + + string imageFileBasePath = string.Empty; //图片根目录 - string? image_file_base_path = ConfigurationManager.AppSettings["ImageFileBasePath"]; - if (string.IsNullOrEmpty(image_file_base_path)) + if (type == 1) + { + imageFileBasePath = strImageModeImagePath; + } + else + { + imageFileBasePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; + } + if (string.IsNullOrEmpty(imageFileBasePath)) { throw new InvalidOperationException("ImageFileBasePath is not configured in AppSettings."); } @@ -226,7 +256,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable JObject jsonData = new JObject( new JProperty("shape", _diamnondType.Split(" ")[0]), new JProperty("shape_mode", _diamnondType.Split(" ")[1]), - new JProperty("image_file_base_path", image_file_base_path), + new JProperty("image_file_base_path", imageFileBasePath), new JProperty("image_files", ImagePaths), new JProperty("half_circle", half_circle), new JProperty("algorithm_log_path", algorithm_log_path), @@ -285,6 +315,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable Progress = (100.00); string strParam = JsonConvert.SerializeObject(detectTask.Result); + //Logger.Info("序列化字符串:" + strParam); AlgorithmResultEntity parameter = JsonConvert.DeserializeObject(strParam); if (parameter == null && _isCancel == false) { @@ -319,6 +350,12 @@ public class GradingLoadingVM : BaseViewModel,IDisposable Parameter = parameter; if (_isCancel == true) return -100; + + if (parameter.status == StatusCodes.Recheck) + { + new MessageBox().Show(MultilingualHelper.getString("Recheck")); + } + return 0; } @@ -357,7 +394,7 @@ public class GradingLoadingVM : BaseViewModel,IDisposable { current = Math.Min(current + 1, 100); UpdateProgress(current); - await Task.Delay(stepTime); + await Task.Delay(stepTime/2); } } private void UpdateProgress(int value) diff --git a/ViewModel/Grading/GradingResultVM.cs b/ViewModel/Grading/GradingResultVM.cs index d11c16f..bd9d067 100644 --- a/ViewModel/Grading/GradingResultVM.cs +++ b/ViewModel/Grading/GradingResultVM.cs @@ -37,6 +37,7 @@ using SparkClient.Model.Attributes; using SparkClient.Model.Common; using PaperSize = System.Drawing.Printing.PaperSize; using SharpDX.Direct2D1.Effects; +using Exception = System.Exception; namespace SparkClient.ViewModel.Grading; @@ -1963,17 +1964,17 @@ public class GradingResultVM : BaseViewModel [Log] private void ExecuteThermalPrint(object parameter) { - MessageBox messageBox = new MessageBox(); - MessageBoxResult boxResult = messageBox.ShowAsk(MultilingualHelper.getString("YesOrNo")); - if (boxResult != MessageBoxResult.OK) - { - return; - } - - string tempFilePath = string.Empty; Microsoft.Office.Interop.Excel.Application excelApp = null; + string tempFilePath = string.Empty; try { + MessageBox messageBox = new MessageBox(); + MessageBoxResult boxResult = messageBox.ShowAsk(MultilingualHelper.getString("YesOrNo")); + if (boxResult != MessageBoxResult.OK) + { + return; + } + // 步骤2:加载模板并填充数据 tempFilePath = GenerateTempExcelFile(); @@ -1983,11 +1984,21 @@ public class GradingResultVM : BaseViewModel excelApp.DisplayAlerts = false; // 禁用警告提示 Microsoft.Office.Interop.Excel.Workbook workbook = excelApp.Workbooks.Open(tempFilePath); - + + string printName = ConfigurationHelper.ReadConfigValue("PrintName"); + string? targetPrinter = System.Drawing.Printing.PrinterSettings.InstalledPrinters + .Cast() + .FirstOrDefault(p => p.Contains(printName)); + if (targetPrinter == null) + { + throw new Exception($"未找到打印机{printName}"); + } + // 打印配置 workbook.PrintOut( Copies: 1, - Preview: false // 禁用打印预览 + Preview: false, + ActivePrinter: targetPrinter ); // 关闭工作簿(不保存修改) @@ -2312,86 +2323,94 @@ public class GradingResultVM : BaseViewModel private string GenerateTempExcelFile() { - string TemplatePath = @"Resource\ResultReport.xlsx"; - using (FileStream templateStream = new FileStream(TemplatePath, FileMode.Open, FileAccess.Read)) + try { - IWorkbook workbook = new XSSFWorkbook(templateStream); - ISheet sheet = workbook.GetSheetAt(0); - - //Row 1 - SetCellValue(sheet, "A1", $"{MultilingualHelper.getString("Organization")}:{Standard}"); - SetCellValue(sheet, "B1", $"{MultilingualHelper.getString("DiamondResultShape")}:{Shape}"); - SetCellValue(sheet, "C1", $"{MultilingualHelper.getString("Code")}:{DiamondCode}"); - SetCellValue(sheet, "E1", $"{MultilingualHelper.getString("Wight")}:{Wight}ct."); - //Row 2 - SetCellValue(sheet, "A2", $"{MultilingualHelper.getString("Parameters")}"); - SetCellValue(sheet, "B2", $"{MultilingualHelper.getString("DiamondResultGridAvgValue")}"); - SetCellValue(sheet, "C2", $"{MultilingualHelper.getString("Interval")}(Min~Max)"); - SetCellValue(sheet, "D2", $"{MultilingualHelper.getString("DiamondResultGridCutLevel")}"); - SetCellValue(sheet, "E2", $"{MultilingualHelper.getString("DiamondResultSymmetryGrade")}"); - //Row 3 - var row3 = getSelectData("DIAMETER"); - SetCellValue(sheet, "A3", $"{GetName("DIAMETER")}(mm)"); - SetCellValue(sheet, "B3", $"{row3.Avg}"); - SetCellValue(sheet, "C3", $"({row3.Min}~{row3.Max})"); - SetCellValue(sheet, "D3", "--"); - SetCellValue(sheet, "E3", $"{row3.SymLevel}"); - //Row 4 - var row4 = getSelectData("TOTAL_DEPTH"); - SetCellValue(sheet, "A4", $"{GetName("TOTAL_DEPTH")}(%)"); - SetCellValue(sheet, "B4", $"{row4.Avg}"); - SetCellValue(sheet, "C4", "--"); - SetCellValue(sheet, "D4", $"{row4.CutLevel}"); - SetCellValue(sheet, "E4", "--"); - // Row 5 - var row5 = getSelectData("TABLE"); - SetCellValue(sheet, "A5", $"{GetName("TABLE")}(%)"); - SetCellValue(sheet, "B5", $"{row5.Avg}"); - SetCellValue(sheet, "C5", $"({row5.Min}~{row5.Max})"); - SetCellValue(sheet, "D5", $"{row5.CutLevel}"); - SetCellValue(sheet, "E5", "--"); - var row6 = getSelectData("CROWN_ANGLE"); - SetCellValue(sheet, "A6", $"{GetName("CROWN_ANGLE")}(°)"); - SetCellValue(sheet, "B6", $"{row6.Avg}"); - SetCellValue(sheet, "C6", $"({row6.Min}~{row6.Max})"); - SetCellValue(sheet, "D6", $"{row6.CutLevel}"); - SetCellValue(sheet, "E6", $"{row6.SymLevel}"); - var row7 = getSelectData("CROWN_HEIGHT"); - SetCellValue(sheet, "A7", $"{GetName("CROWN_HEIGHT")}(%)"); - SetCellValue(sheet, "B7", $"{row7.Avg}"); - SetCellValue(sheet, "C7", $"({row7.Min}~{row7.Max})"); - SetCellValue(sheet, "D7", $"{row7.CutLevel}"); - SetCellValue(sheet, "E7", $"{row7.SymLevel}"); - var row8 = getSelectData("GIRDLE"); - SetCellValue(sheet, "A8", $"{GetName("GIRDLE")}(%)"); - SetCellValue(sheet, "B8", $"{row8.Avg}"); - SetCellValue(sheet, "C8", $"({row8.Min}~{row8.Max})"); - SetCellValue(sheet, "D8", $"{row8.CutLevel}"); - SetCellValue(sheet, "E8", $"{row8.SymLevel}"); - var row9 = getSelectData("PAV_DEPTH"); - SetCellValue(sheet, "A9", $"{GetName("PAV_DEPTH")}(%)"); - SetCellValue(sheet, "B9", $"{row9.Avg}"); - SetCellValue(sheet, "C9", $"({row9.Min}~{row9.Max})"); - SetCellValue(sheet, "D9", $"{row9.CutLevel}"); - SetCellValue(sheet, "E9", $"{row9.SymLevel}"); - //row 10 - //Row 11 - SetCellValue(sheet, "A11", $"{MultilingualHelper.getString("CuttingGrade")}"); - SetCellValue(sheet, "B11", $"{CutLevelTotal}"); - //Row 12 - SetCellValue(sheet, "A12", $"{MultilingualHelper.getString("SymmetryLevel")}"); - SetCellValue(sheet, "B12", $"{SymLevelTotal}"); - SetCellValue(sheet, "C12", $"{MultilingualHelper.getString("DateOfIssue")}: {DateTime.Now:yyyy/M/d}"); - // 生成临时文件路径 - string tempFile = Path.Combine( - Path.GetTempPath(), - $"DiamondReport_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); - - using (FileStream fs = new FileStream(tempFile, FileMode.Create)) + string TemplatePath = @"Resource\ResultReport.xlsx"; + using (FileStream templateStream = new FileStream(TemplatePath, FileMode.Open, FileAccess.Read)) { - workbook.Write(fs); + IWorkbook workbook = new XSSFWorkbook(templateStream); + ISheet sheet = workbook.GetSheetAt(0); + + //Row 1 + SetCellValue(sheet, "A1", $"{MultilingualHelper.getString("Organization")}:{Standard}"); + SetCellValue(sheet, "B1", $"{MultilingualHelper.getString("DiamondResultShape")}:{Shape}"); + SetCellValue(sheet, "C1", $"{MultilingualHelper.getString("Code")}:{DiamondCode}"); + SetCellValue(sheet, "E1", $"{MultilingualHelper.getString("Wight")}:{Wight}ct."); + //Row 2 + SetCellValue(sheet, "A2", $"{MultilingualHelper.getString("Parameters")}"); + SetCellValue(sheet, "B2", $"{MultilingualHelper.getString("DiamondResultGridAvgValue")}"); + SetCellValue(sheet, "C2", $"{MultilingualHelper.getString("Interval")}(Min~Max)"); + SetCellValue(sheet, "D2", $"{MultilingualHelper.getString("DiamondResultGridCutLevel")}"); + SetCellValue(sheet, "E2", $"{MultilingualHelper.getString("DiamondResultSymmetryGrade")}"); + //Row 3 + var row3 = getSelectData("DIAMETER"); + SetCellValue(sheet, "A3", $"{GetName("DIAMETER")}(mm)"); + SetCellValue(sheet, "B3", $"{row3.Avg}"); + SetCellValue(sheet, "C3", $"({row3.Min}~{row3.Max})"); + SetCellValue(sheet, "D3", "--"); + SetCellValue(sheet, "E3", $"{row3.SymLevel}"); + //Row 4 + var row4 = getSelectData("TOTAL_DEPTH"); + SetCellValue(sheet, "A4", $"{GetName("TOTAL_DEPTH")}(%)"); + SetCellValue(sheet, "B4", $"{row4.Avg}"); + SetCellValue(sheet, "C4", "--"); + SetCellValue(sheet, "D4", $"{row4.CutLevel}"); + SetCellValue(sheet, "E4", "--"); + // Row 5 + var row5 = getSelectData("TABLE"); + SetCellValue(sheet, "A5", $"{GetName("TABLE")}(%)"); + SetCellValue(sheet, "B5", $"{row5.Avg}"); + SetCellValue(sheet, "C5", $"({row5.Min}~{row5.Max})"); + SetCellValue(sheet, "D5", $"{row5.CutLevel}"); + SetCellValue(sheet, "E5", "--"); + var row6 = getSelectData("CROWN_ANGLE"); + SetCellValue(sheet, "A6", $"{GetName("CROWN_ANGLE")}(°)"); + SetCellValue(sheet, "B6", $"{row6.Avg}"); + SetCellValue(sheet, "C6", $"({row6.Min}~{row6.Max})"); + SetCellValue(sheet, "D6", $"{row6.CutLevel}"); + SetCellValue(sheet, "E6", $"{row6.SymLevel}"); + var row7 = getSelectData("CROWN_HEIGHT"); + SetCellValue(sheet, "A7", $"{GetName("CROWN_HEIGHT")}(%)"); + SetCellValue(sheet, "B7", $"{row7.Avg}"); + SetCellValue(sheet, "C7", $"({row7.Min}~{row7.Max})"); + SetCellValue(sheet, "D7", $"{row7.CutLevel}"); + SetCellValue(sheet, "E7", $"{row7.SymLevel}"); + var row8 = getSelectData("GIRDLE"); + SetCellValue(sheet, "A8", $"{GetName("GIRDLE")}(%)"); + SetCellValue(sheet, "B8", $"{row8.Avg}"); + SetCellValue(sheet, "C8", $"({row8.Min}~{row8.Max})"); + SetCellValue(sheet, "D8", $"{row8.CutLevel}"); + SetCellValue(sheet, "E8", $"{row8.SymLevel}"); + var row9 = getSelectData("PAV_DEPTH"); + SetCellValue(sheet, "A9", $"{GetName("PAV_DEPTH")}(%)"); + SetCellValue(sheet, "B9", $"{row9.Avg}"); + SetCellValue(sheet, "C9", $"({row9.Min}~{row9.Max})"); + SetCellValue(sheet, "D9", $"{row9.CutLevel}"); + SetCellValue(sheet, "E9", $"{row9.SymLevel}"); + //row 10 + //Row 11 + SetCellValue(sheet, "A11", $"{MultilingualHelper.getString("CuttingGrade")}"); + SetCellValue(sheet, "B11", $"{CutLevelTotal}"); + //Row 12 + SetCellValue(sheet, "A12", $"{MultilingualHelper.getString("SymmetryLevel")}"); + SetCellValue(sheet, "B12", $"{SymLevelTotal}"); + SetCellValue(sheet, "C12", $"{MultilingualHelper.getString("DateOfIssue")}: {DateTime.Now:yyyy/M/d}"); + // 生成临时文件路径 + string tempFile = Path.Combine( + Path.GetTempPath(), + $"DiamondReport_{DateTime.Now:yyyyMMddHHmmss}.xlsx"); + + using (FileStream fs = new FileStream(tempFile, FileMode.Create)) + { + workbook.Write(fs); + } + + return tempFile; } - return tempFile; + } + catch (Exception e) + { + throw e; } } diff --git a/Views/Dialog/ImageSelect.xaml b/Views/Dialog/ImageSelect.xaml new file mode 100644 index 0000000..ac7fb67 --- /dev/null +++ b/Views/Dialog/ImageSelect.xaml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public PlaneType PlaneType { get; set; } - - + + public Double Theta { get; set; } } \ No newline at end of file diff --git a/Views/UserControl/ViewportData/Helper/CommonHelper.cs b/Views/UserControl/ViewportData/Helper/CommonHelper.cs index ea78d0e..7b52e3b 100644 --- a/Views/UserControl/ViewportData/Helper/CommonHelper.cs +++ b/Views/UserControl/ViewportData/Helper/CommonHelper.cs @@ -46,7 +46,7 @@ public class CommonHelper // 提取 PlaneCode 和 PlaneType string planeCode = jsonObject.facet_id ?? (string)jsonObject.facet_id; PlaneType planeType = (PlaneType)(int)jsonObject.facet_type; - + double theta = jsonObject.theta ?? (double)jsonObject.theta; // 生成 TriangleCode var triangleCode = GenerateTriangleCode(point1, point2, point3); @@ -58,7 +58,8 @@ public class CommonHelper Point3 = point3, TriangleCode = triangleCode, PlaneCode = planeCode, - PlaneType = planeType + PlaneType = planeType, + Theta = theta }; } diff --git a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs index 01de774..b614d76 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs @@ -521,16 +521,6 @@ public class ViewportHelperPro if (selFacetType == PlaneType.Girdle && string.IsNullOrWhiteSpace(valKey)) { Logger.Info($"【面文本生成】 命中面{selFacetType},是腰"); - // if (ViewportManager.MainModelGirdleMaxLines != null || ViewportManager.MainModelGirdleMinLines != null || - // ViewportManager.MainModelGirdleAvgLines != null) - // { - // result.Add(DisplayLineModel3D(new List>(){ViewportManager.MainModelGirdleMaxLines}, new Color4(1f, 0, 0, 1f) )); - // result.Add(DisplayLineModel3D(new List>(){ViewportManager.MainModelGirdleMinLines}, new Color4(0f, 1f, 0, 1f) )); - // result.Add(DisplayLineModel3D(new List>(){ViewportManager.MainModelGirdleAvgLines}, new Color4(1f, 0.5f, 0, 1f) )); - // result.Add(DisplayText3D($"{CalculateLength(ViewportManager.MainModelGirdleMaxLines)}mm", ViewportManager.MainModelGirdleMaxLines.Item1, textColor)); - // result.Add(DisplayText3D($"{CalculateLength(ViewportManager.MainModelGirdleMinLines)}mm", ViewportManager.MainModelGirdleMinLines.Item1, textColor)); - // result.Add(DisplayText3D($"{CalculateLength(ViewportManager.MainModelGirdleAvgLines)}mm", ViewportManager.MainModelGirdleAvgLines.Item1, textColor)); - // } List facetTypeAll = ViewportManager.ViewportTriangle.FindAll(e => e.PlaneType == selFacetType); var groupedDic = facetTypeAll.GroupBy(entity => entity.PlaneCode) @@ -615,27 +605,7 @@ public class ViewportHelperPro Logger.Info($"【面文本生成】 {valueFloat} -- {valueIndex}"); var facetTextPoint = GetOffsetCenter(facetPoints, ViewportManager.CenterVector); result.Add(DisplayText3D($"{valueFloat}", facetTextPoint)); - // foreach (var kv in groupedDic) - // { - // var value = kv.Value; - // var key = kv.Key; - // var facetIndex = -1; - // int.TryParse(key.Split("_")[1], out facetIndex); - // List facetPoints = new List(); - // value.ForEach(e => { facetPoints.Add(e.Point1); facetPoints.Add(e.Point2); facetPoints.Add(e.Point3); }); - // - // int linePointType = facetIndex % 4; - // /*** - // * 0 1 2 3 - // * 4 5 6 7 - // * 面index+1 % 4 = 0 - // * 面id-loop4 = 0 - 高亮左边的竖线 - 波峰 - - // * 面id-loop4 = 1 - 高亮右边的竖线 - 波谷 - // * 面id-loop4 = 2 - 高亮左边的竖线 - 波谷 - // * 面id-loop4 = 3 - 高亮右边的竖线 - 波峰 - // */ - // - // } + } else if (selFacetType == PlaneType.Girdle && !string.IsNullOrWhiteSpace(valKey)) { Logger.Info($"【面文本生成】 命中面{selFacetType},是腰,显示值{valKey}"); @@ -697,8 +667,8 @@ public class ViewportHelperPro return result; } result.Add(DisplayLineModel3D(new List>() { showLine }, new Color4(1f, 0, 0, 1f), 2f)); - var valueFloat = ValueFormat(paramValue.ToString(), valKey); - result.Add(DisplayText3D($" {resIndex} \r\n {valueFloat}", facetTextPoint)); + var valueFloat = ValueFormat(paramValue.ToString(), valKey, true); + result.Add(DisplayText3D($"{valueFloat} \r\n {resIndex}", facetTextPoint)); } } @@ -712,6 +682,36 @@ public class ViewportHelperPro .ToDictionary(group => group.Key, group => group.ToList()); Logger.Info($"【面文本生成】 同类面{groupedDic.Count}个"); var valueIndex = 1; + //台面显示 + if (selFacetType == PlaneType.TableFacet) + { + List tablePointList = new List(); + foreach (var entity in groupedDic["11_0"]) + { + tablePointList.Add(entity.Point1); + tablePointList.Add(entity.Point2); + tablePointList.Add(entity.Point3); + } + HashSet tablePointSet = new HashSet(tablePointList); + tablePointList = VectorClockwiseSort(tablePointSet.ToList()); + + List> line = new List>(); + for (int i = 0; i < tablePointList.Count / 2; i++) + { + line.Add(new Tuple(tablePointList[i], tablePointList[i+tablePointList.Count / 2])); + } + string param = "TABLE"; + var detail = ViewportManager.DiamondData[$"{param}_DETAIL"]; + for (int i = 0; i < line.Count; i++) + { + Vector3 point = line[i].Item2; + var valueFloat = ValueFormat(detail[$"{param}_{i+1}"].ToString(), param, true); + result.Add(DisplayText3D($"{valueFloat}", new Vector3(point.X, point.Y - 0.4f, point.Z))); + } + result.Add( DisplayLineModel3D(line, new Color4(1f, 0, 0, 1f), 0.7f)); + + } + foreach (var kv in groupedDic) { var value = kv.Value; @@ -734,7 +734,7 @@ public class ViewportHelperPro Logger.Info($"【面文本生成】 {param} Key不存在"); continue; } - var valueFloat = ValueFormat(paramValue.ToString(), param); + var valueFloat = ValueFormat(paramValue.ToString(), param, true); Logger.Info($"【面文本生成】 {valueFloat} -- {facetIndex}"); var facetTextPoint = GetOffsetCenter(facetPoints, ViewportManager.CenterVector); result.Add(DisplayText3D($"{valueFloat}", facetTextPoint)); @@ -758,10 +758,10 @@ public class ViewportHelperPro } Logger.Info($"【面文本生成】 {param}_DETAIL.{param}_{valueIndex} ==={paramValue}"); - var valueFloat = ValueFormat(paramValue.ToString(), param); + var valueFloat = ValueFormat(paramValue.ToString(), param, true); Logger.Info($"【面文本生成】 {valueFloat} -- {valueIndex}"); var facetTextPoint = GetOffsetCenter(facetPoints, ViewportManager.CenterVector); - result.Add(DisplayText3D($" {facetIndex} \r\n {valueFloat}", new Vector3(facetTextPoint.X, facetTextPoint.Y + 0.1f, facetTextPoint.Z))); + result.Add(DisplayText3D($"{valueFloat} \r\n {facetIndex}", new Vector3(facetTextPoint.X, facetTextPoint.Y + 0.1f, facetTextPoint.Z))); } else if (ViewportManager.DiamondData.Count > 1 && facetIndex != -1) { @@ -782,53 +782,12 @@ public class ViewportHelperPro } Logger.Info($"【面文本生成】 {param}_DETAIL.{param}_{facetIndex} ==={paramValue}"); - var valueFloat = ValueFormat(paramValue.ToString(), param); + var valueFloat = ValueFormat(paramValue.ToString(), param, true); Logger.Info($"【面文本生成】 {valueFloat} -- {facetIndex}"); var facetTextPoint = GetOffsetCenter(facetPoints, ViewportManager.CenterVector); - result.Add(DisplayText3D($" {facetIndex} \r\n {valueFloat}", facetTextPoint)); + result.Add(DisplayText3D($"{valueFloat} \r\n {facetIndex}", facetTextPoint)); } } - - /*** - * 思路: - * 1、以面分组,1组为台面、底面,8组、16组、64组、other - * 2、每组数据区别 - * 1组:取第一个数据 - * 8组:按索引0-7 -> 1-8 - * 16组:1-2、3-4、5-6、7-8、9-10、11-12、13-14、15-0共享数据 - * 64组:这组特殊理论上是腰,按照else里的东西来 - * 3、这个方法是主动点击,被动触发理论上通用 - * 4、主动触发:循环遍历面组,根据面类型获取算法存储的数据,在Manager里制定面-参数的一对多关系,主动触发时,取参数的首位为默认 - * 5、被动触发:根据结果页传入的参数编号,找到对应的面,循环遍历面组,根据面类型获取算法存储的数据,根据被动传入参数找到值 - * 6、 ①组面可能由至少两个三角形组成,计算出三角形拼接出的多边形的中心作为文字显示的中心 - * ②在从算法结果数据对应好面组的索引,做成值-组面id的文本,计算出这个文本的大小 - * ③在拼接的图片中心,平行于平面,向中心点外偏移“文本大小高度+0.1"个单位 显示文本 - */ - - // var selFaceVector = entities - // .SelectMany(entity => new[] { entity.Point1, entity.Point2, entity.Point3 }) - // .Distinct() - // .ToList(); - // var uniqueLines = new HashSet(); - // var sortedVectors = VectorClockwiseSort(selFaceVector); - // for (int i = 0; i < sortedVectors.Count; i++) - // { - // var current = sortedVectors[i]; - // var next = sortedVectors[(i + 1) % sortedVectors.Count]; - // - // double length = (next - current).Length(); - // string lineKey = $"{length:F2}"; - // if (showAll == false) - // { - // if (uniqueLines.Contains(lineKey)) continue; - // uniqueLines.Add(lineKey); - // } - // var midPoint = (current + next) / 2; - // var text = $"{length:F2}mm"; - // var textY = midPoint.Y > ViewportManager.CenterVector.Y ? midPoint.Y + 0.3f : midPoint.Y - 0.3f; - // var lengthTextModel = DisplayText3D(text, new Vector3(midPoint.X, textY, midPoint.Z),next - current, textColor); - // result.Add(lengthTextModel); - // } } @@ -2103,6 +2062,9 @@ public class ViewportHelperPro v = Math.Floor(v * 10) / 10; return hasUnit ? $"{v.ToString("F1")}mm" : v.ToString("F1"); case "PAV_ANGLE": + case "STAR_ANGLE": + case "UPPER_HALF_ANGLE": + case "LOWER_HALF_ANGLE": case "TWIST": v = Math.Floor(v * 10) / 10; return hasUnit ? $"{v.ToString("F1")}°" : v.ToString("F1"); @@ -2113,7 +2075,7 @@ public class ViewportHelperPro // case "CROWN HEIGHT": // case "PAV DEPTH": v *= 100; - return hasUnit ? $"{(Math.Round(v / 0.5) * 0.5).ToString("F1")}%" : (Math.Round(v / 0.5) * 0.5).ToString("F1"); + return hasUnit ? $"{v.ToString("F1")}%" : v.ToString("F1"); default: v = Math.Floor(v * 1000) / 1000; return hasUnit ? $"{(v*100).ToString("F1")}%" : (v*100).ToString("F1"); diff --git a/Views/UserControl/ViewportData/Helper/ViewportManager.cs b/Views/UserControl/ViewportData/Helper/ViewportManager.cs index e6de322..c9b27ba 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportManager.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportManager.cs @@ -148,6 +148,20 @@ public class ViewportManager public static bool DoubleClickSelectShowPlaneType = true; //选中三角形代码 public static string ChooseTriangleCode = string.Empty; + + private static bool _HasTriangleSelect; + public static bool HasTriangleSelect + { + get { return _HasTriangleSelect; } + + set + { + _HasTriangleSelect = value; + if(_viewport3D != null) + _viewport3D.ViewportCutXuanZ.IsEnabled = value; + } + } + //通过选中添加的元素 public static List ChooseAddModels = new List(); /// @@ -158,6 +172,7 @@ public class ViewportManager if (string.IsNullOrWhiteSpace(ChooseTriangleCode)) { ClearDicModels(); + HasTriangleSelect = false; return; } @@ -169,6 +184,7 @@ public class ViewportManager // if (DoubleClickSelectShowBorderAngle) models.Add(SelShowType.BorderAngle); if (DoubleClickSelectShowPlaneType) models.Add(SelShowType.IsTypePanel); ChooseAddModels.AddRange(ViewportHelperPro.GentrateChosenView(ChooseTriangleCode, valType, models.ToArray())); + HasTriangleSelect = true; ChooseAddModels.ForEach(e => { if (e != null) _viewport.Items.Add(e); @@ -184,6 +200,7 @@ public class ViewportManager _viewport.Items.Remove(item); } ChooseAddModels.Clear(); + HasTriangleSelect = false; } public static void InitMeshLines() { @@ -248,10 +265,11 @@ public class ViewportManager { { PlaneType.UpperMainFacet,"CROWN_ANGLE"}, { PlaneType.PavilionMainFacet, "PAV_ANGLE"}, - { PlaneType.StarFacet, "STAR"}, + { PlaneType.StarFacet, "STAR_ANGLE"}, { PlaneType.TableFacet, "TABLE"}, { PlaneType.Culet, "COC"}, - { PlaneType.LowerGirdleFact, "LOWER_HALVES_RATIO"}, + { PlaneType.LowerGirdleFact, "LOWER_HALF_ANGLE"}, + { PlaneType.UpperGirdleFacet, "UPPER_HALF_ANGLE"}, }; // 数据 -> 面 public static Dictionary DicValueParamToFacet = new Dictionary()