diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..013007b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dotnet.preferCSharpExtension": true +} \ No newline at end of file diff --git a/Common/PLMService.cs b/Common/PLMService.cs new file mode 100644 index 0000000..fb9df7d --- /dev/null +++ b/Common/PLMService.cs @@ -0,0 +1,92 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Laservall.Solidworks.Common +{ + public class PartTypeItem + { + [JsonProperty("type_id")] + public string TypeId { get; set; } + + [JsonProperty("parent_type_id")] + public string ParentTypeId { get; set; } + + [JsonProperty("code")] + public string Code { get; set; } + + [JsonProperty("type_name")] + public string TypeName { get; set; } + + [JsonProperty("type_key")] + public string TypeKey { get; set; } + + [JsonProperty("is_child")] + public string IsChild { get; set; } + + public string DisplayText => $"{Code} - {TypeName}"; + + public override string ToString() => DisplayText; + } + + public static class PLMService + { + private const string PartTypeSearchUrl = "http://10.0.0.155:9992/api/PLM/PartType/Search"; + private static readonly HttpClient _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(30) }; + + private static List _cachedPartTypes; + private static readonly object _lock = new object(); + + public static List CachedPartTypes + { + get + { + lock (_lock) + { + return _cachedPartTypes ?? new List(); + } + } + } + + public static async Task> SearchPartTypesAsync(string code = "", string name = "") + { + try + { + var requestBody = new { code = code ?? "", name = name ?? "" }; + var json = JsonConvert.SerializeObject(requestBody); + var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json"); + + var response = await _httpClient.PostAsync(PartTypeSearchUrl, content).ConfigureAwait(false); + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + if (!response.IsSuccessStatusCode) + { + Debug.WriteLine($"PLM PartType/Search failed: {(int)response.StatusCode} {responseText}"); + return new List(); + } + + return JsonConvert.DeserializeObject>(responseText) + ?? new List(); + } + catch (Exception ex) + { + Debug.WriteLine($"PLM PartType/Search error: {ex.Message}"); + return new List(); + } + } + + public static async Task LoadAndCachePartTypesAsync() + { + var items = await SearchPartTypesAsync("", "").ConfigureAwait(false); + lock (_lock) + { + _cachedPartTypes = items; + } + Debug.WriteLine($"PLM PartTypes loaded: {items.Count} items"); + } + } +} diff --git a/Common/PropertyEditor.cs b/Common/PropertyEditor.cs index 1621384..a3716ba 100644 --- a/Common/PropertyEditor.cs +++ b/Common/PropertyEditor.cs @@ -1,10 +1,10 @@ -using HandyControl.Controls; +using HandyControl.Controls; using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; namespace Laservall.Solidworks.Common { @@ -35,7 +35,7 @@ namespace Laservall.Solidworks.Common { public override FrameworkElement CreateElement(PropertyItem propertyItem) { - var comboBox = new ComboBox(); + var comboBox = new System.Windows.Controls.ComboBox(); comboBox.IsEditable = true; var items = ComboBoxDataRegistry.GetItems(propertyItem.DisplayName); comboBox.ItemsSource = items; @@ -49,29 +49,109 @@ namespace Laservall.Solidworks.Common public override DependencyProperty GetDependencyProperty() { - return ComboBox.SelectedItemProperty; + return System.Windows.Controls.ComboBox.SelectedItemProperty; } } public class CategoryComboxPropertyEditor : PropertyEditorBase { + private static List _allPartTypes = new List(); + + public static void SetPartTypes(List items) + { + _allPartTypes = items ?? new List(); + } + public override FrameworkElement CreateElement(PropertyItem propertyItem) { - var comboBox = new ComboBox(); - comboBox.IsEditable = true; - var items = ComboBoxDataRegistry.GetItems(propertyItem.DisplayName); - comboBox.ItemsSource = items; - comboBox.SelectedItem = propertyItem.Value?.ToString(); + var comboBox = new System.Windows.Controls.ComboBox + { + IsEditable = true, + IsTextSearchEnabled = false + }; + + var allItems = _allPartTypes; + + comboBox.ItemsSource = allItems; + comboBox.DisplayMemberPath = "DisplayText"; + comboBox.SelectedValuePath = "Code"; + + var currentCode = propertyItem.Value?.ToString(); + if (!string.IsNullOrEmpty(currentCode)) + { + var match = allItems.FirstOrDefault(x => + string.Equals(x.Code, currentCode, StringComparison.OrdinalIgnoreCase)); + if (match != null) + { + comboBox.SelectedItem = match; + } + } + + bool suppressFilter = false; + comboBox.SelectionChanged += (s, e) => { - propertyItem.Value = comboBox.SelectedItem; + if (comboBox.SelectedItem is PartTypeItem selected) + { + propertyItem.Value = selected.Code; + } }; + + comboBox.Loaded += (s, e) => + { + var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox; + if (textBox == null) return; + + textBox.TextChanged += (s2, e2) => + { + if (suppressFilter) return; + + var text = textBox.Text; + if (string.IsNullOrEmpty(text)) + { + comboBox.ItemsSource = allItems; + } + else + { + var lower = text.ToLowerInvariant(); + var filtered = allItems.Where(x => + (x.Code != null && x.Code.ToLowerInvariant().Contains(lower)) || + (x.TypeName != null && x.TypeName.ToLowerInvariant().Contains(lower)) + ).ToList(); + comboBox.ItemsSource = filtered; + } + + suppressFilter = true; + comboBox.IsDropDownOpen = true; + textBox.Text = text; + textBox.CaretIndex = text.Length; + suppressFilter = false; + }; + }; + + comboBox.DropDownClosed += (s, e) => + { + if (comboBox.SelectedItem is PartTypeItem selected) + { + suppressFilter = true; + var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox; + if (textBox != null) + { + textBox.Text = selected.DisplayText; + textBox.CaretIndex = textBox.Text.Length; + } + suppressFilter = false; + + comboBox.ItemsSource = allItems; + } + }; + return comboBox; } public override DependencyProperty GetDependencyProperty() { - return ComboBox.SelectedItemProperty; + return System.Windows.Controls.ComboBox.SelectedValueProperty; } } diff --git a/Laservall.Solidworks.csproj b/Laservall.Solidworks.csproj index 696a4d6..ee059bb 100644 --- a/Laservall.Solidworks.csproj +++ b/Laservall.Solidworks.csproj @@ -89,6 +89,7 @@ + @@ -169,8 +170,8 @@ - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + 这台计算机上缺少此项目引用的 NuGet 程序包。使用"NuGet 程序包还原"可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 - \ No newline at end of file + diff --git a/Model/PartPropModel.cs b/Model/PartPropModel.cs index f396e87..6e0035a 100644 --- a/Model/PartPropModel.cs +++ b/Model/PartPropModel.cs @@ -1,4 +1,4 @@ -using HandyControl.Controls; +using HandyControl.Controls; using Laservall.Solidworks.Common; using System; using System.Collections.Generic; @@ -168,6 +168,21 @@ namespace Laservall.Solidworks.Model } } + private string _partType; + [Category("零件属性")] + [DisplayName("零件类型")] + [Editor(typeof(SearchableComboBoxPropertyEditor), typeof(SearchableComboBoxPropertyEditor))] + public string PartType + { + get => _partType; + set + { + if (_partType == value) return; + _partType = value; + OnPropertyChanged(); + } + } + private bool _purCheck; [Category("零件属性")] [DisplayName("采购检验")] @@ -211,4 +226,4 @@ namespace Laservall.Solidworks.Model } } } -} \ No newline at end of file +} diff --git a/Pane/PartPropPaneViewModel.cs b/Pane/PartPropPaneViewModel.cs index 68dd493..c3b0f4e 100644 --- a/Pane/PartPropPaneViewModel.cs +++ b/Pane/PartPropPaneViewModel.cs @@ -4,6 +4,7 @@ using Laservall.Solidworks.Model; using SolidWorks.Interop.sldworks; using System.Diagnostics; using System.Reflection; +using System.Threading.Tasks; using System.Windows.Input; using Xarial.XCad; using Xarial.XCad.Documents; @@ -37,8 +38,16 @@ namespace Laservall.Solidworks.Pane set => Set(ref _versionText, value); } + private bool _isLoadingPartTypes; + public bool IsLoadingPartTypes + { + get => _isLoadingPartTypes; + set => Set(ref _isLoadingPartTypes, value); + } + public ICommand SaveCommand { get; } public ICommand ResetCommand { get; } + public ICommand RefreshPartTypesCommand { get; } public PartPropPaneViewModel() { @@ -46,6 +55,45 @@ namespace Laservall.Solidworks.Pane SaveCommand = new RelayCommand(ExecuteSave, CanSave); ResetCommand = new RelayCommand(ExecuteReset, CanReset); + RefreshPartTypesCommand = new RelayCommand(async _ => await LoadPartTypesAsync()); + + // 异步加载零件类型数据 + Task.Run(async () => await LoadPartTypesAsync()); + } + + /// + /// 从PLM API加载零件类型数据 + /// + private async Task LoadPartTypesAsync() + { + try + { + IsLoadingPartTypes = true; + StatusText = "正在加载零件类型..."; + + // 调用PLM API获取零件类型 + var partTypes = await PartTypeService.GetAllAsync(); + + if (partTypes.Count > 0) + { + // 注册到可搜索ComboBox编辑器 + SearchableComboBoxPropertyEditor.RegisterPartTypes("零件类型", partTypes); + StatusText = $"已加载 {partTypes.Count} 个零件类型"; + } + else + { + StatusText = "未找到零件类型数据"; + } + } + catch (System.Exception ex) + { + Debug.WriteLine($"加载零件类型失败: {ex.Message}"); + StatusText = "加载零件类型失败"; + } + finally + { + IsLoadingPartTypes = false; + } } public void OnSelectionChanged(IXDocument doc, IXSelObject selObject)