274 lines
9.8 KiB
C#
274 lines
9.8 KiB
C#
|
|
using Laservall.Solidworks.Extension;
|
||
|
|
using Laservall.Solidworks.Model;
|
||
|
|
using Laservall.Solidworks.Windows;
|
||
|
|
using SolidWorks.Interop.sldworks;
|
||
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.IO;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Threading;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
|
||
|
|
namespace Laservall.Solidworks.Server
|
||
|
|
{
|
||
|
|
internal sealed class SolidWorksBomDataProvider : IBomDataProvider
|
||
|
|
{
|
||
|
|
private readonly StaThreadMarshaller _marshaller;
|
||
|
|
|
||
|
|
private static readonly HashSet<string> StaticColumnProps = new HashSet<string>
|
||
|
|
{
|
||
|
|
"零件名称", "材质", "属性", "材料"
|
||
|
|
};
|
||
|
|
|
||
|
|
public SolidWorksBomDataProvider(StaThreadMarshaller marshaller)
|
||
|
|
{
|
||
|
|
_marshaller = marshaller ?? throw new ArgumentNullException(nameof(marshaller));
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task<BomLoadResult> LoadBomAsync(IProgress<BomLoadProgress> progress, CancellationToken ct)
|
||
|
|
{
|
||
|
|
return await _marshaller.InvokeAsync(async () =>
|
||
|
|
{
|
||
|
|
ModelDoc2 model = SWUtils.SwApp.ActiveDoc as ModelDoc2;
|
||
|
|
if (model == null)
|
||
|
|
{
|
||
|
|
return new BomLoadResult
|
||
|
|
{
|
||
|
|
Items = new List<BomItemModel>(),
|
||
|
|
DynamicKeys = new List<string>(),
|
||
|
|
Settings = BomSettings.Load()
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
Configuration config = model.ConfigurationManager.ActiveConfiguration;
|
||
|
|
|
||
|
|
var rootTree = new SwAssDocTreeModel
|
||
|
|
{
|
||
|
|
drawingNo = Path.GetFileNameWithoutExtension(model.GetPathName()),
|
||
|
|
docPath = model.GetPathName(),
|
||
|
|
configName = config?.Name ?? "",
|
||
|
|
children = new List<SwAssDocTreeModel>(),
|
||
|
|
isAss = true,
|
||
|
|
quantity = 1,
|
||
|
|
props = SWUtils.GetConfig3(model.GetPathName())
|
||
|
|
};
|
||
|
|
|
||
|
|
Component2 rootComponent = config?.GetRootComponent3(true) as Component2;
|
||
|
|
int totalCount = GetTotalComponentCount(model);
|
||
|
|
|
||
|
|
if (HasLightweightComponents(model))
|
||
|
|
{
|
||
|
|
ResolvingProgressWindow.RunWithProgress(() =>
|
||
|
|
{
|
||
|
|
SWUtils.SetAllPartResolved(model.GetPathName());
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (rootComponent != null)
|
||
|
|
{
|
||
|
|
IProgress<SwTreeLoadProgress> swProgress = null;
|
||
|
|
if (progress != null)
|
||
|
|
{
|
||
|
|
swProgress = new Progress<SwTreeLoadProgress>(p =>
|
||
|
|
{
|
||
|
|
progress.Report(new BomLoadProgress
|
||
|
|
{
|
||
|
|
Processed = p.Processed,
|
||
|
|
Total = p.Total,
|
||
|
|
CurrentName = p.CurrentName
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
var parts = await SWUtils.GetSwAssDocTreeChildrenAsync(
|
||
|
|
rootComponent, true, true, totalCount, swProgress);
|
||
|
|
rootTree.children.AddRange(parts);
|
||
|
|
}
|
||
|
|
|
||
|
|
var allItems = SWUtils.FlattenBomTree(rootTree);
|
||
|
|
var propKeys = SWUtils.CollectAllPropertyKeys(allItems);
|
||
|
|
|
||
|
|
var dynamicKeys = propKeys
|
||
|
|
.Where(k => !StaticColumnProps.Contains(k))
|
||
|
|
.OrderBy(k => k)
|
||
|
|
.ToList();
|
||
|
|
|
||
|
|
var settings = BomSettings.Load();
|
||
|
|
settings.MergeDynamicKeys(dynamicKeys);
|
||
|
|
|
||
|
|
var userAddedKeys = settings.Columns
|
||
|
|
.Where(c => c.IsUserAdded && !dynamicKeys.Contains(c.Name))
|
||
|
|
.Select(c => c.Name)
|
||
|
|
.ToList();
|
||
|
|
dynamicKeys.AddRange(userAddedKeys);
|
||
|
|
|
||
|
|
EnsurePropsKeys(allItems, dynamicKeys);
|
||
|
|
|
||
|
|
return new BomLoadResult
|
||
|
|
{
|
||
|
|
Items = allItems,
|
||
|
|
DynamicKeys = dynamicKeys,
|
||
|
|
Settings = settings
|
||
|
|
};
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
public SaveResult SaveChanges(List<ChangeItem> changes)
|
||
|
|
{
|
||
|
|
if (changes == null || changes.Count == 0)
|
||
|
|
{
|
||
|
|
return new SaveResult { Success = true, SavedCount = 0 };
|
||
|
|
}
|
||
|
|
|
||
|
|
return _marshaller.Invoke(() =>
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var grouped = changes
|
||
|
|
.Where(c => !string.IsNullOrEmpty(c.DocPath) && !string.IsNullOrEmpty(c.Key))
|
||
|
|
.GroupBy(c => c.DocPath);
|
||
|
|
|
||
|
|
int savedCount = 0;
|
||
|
|
foreach (var group in grouped)
|
||
|
|
{
|
||
|
|
ModelDoc2 doc = SWUtils.OpenDocSilently(group.Key);
|
||
|
|
if (doc == null) continue;
|
||
|
|
|
||
|
|
Configuration activeConfig = doc.ConfigurationManager?.ActiveConfiguration;
|
||
|
|
CustomPropertyManager configPropMgr = activeConfig?.CustomPropertyManager;
|
||
|
|
|
||
|
|
CustomPropertyManager filePropMgr = null;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
filePropMgr = doc.Extension?.get_CustomPropertyManager("");
|
||
|
|
}
|
||
|
|
catch { }
|
||
|
|
|
||
|
|
foreach (var change in group)
|
||
|
|
{
|
||
|
|
bool writtenToConfig = false;
|
||
|
|
if (configPropMgr != null)
|
||
|
|
{
|
||
|
|
var configNames = configPropMgr.GetNames() as string[];
|
||
|
|
if (configNames != null && configNames.Contains(change.Key))
|
||
|
|
{
|
||
|
|
configPropMgr.Set2(change.Key, change.Value ?? "");
|
||
|
|
writtenToConfig = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!writtenToConfig && filePropMgr != null)
|
||
|
|
{
|
||
|
|
filePropMgr.Set2(change.Key, change.Value ?? "");
|
||
|
|
}
|
||
|
|
else if (!writtenToConfig && configPropMgr != null)
|
||
|
|
{
|
||
|
|
configPropMgr.Set2(change.Key, change.Value ?? "");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
doc.Save3(0, 0, 0);
|
||
|
|
savedCount++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return new SaveResult { Success = true, SavedCount = savedCount };
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
return new SaveResult { Success = false, Error = ex.Message };
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
public BomSettings GetSettings()
|
||
|
|
{
|
||
|
|
return BomSettings.Load();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SaveSettings(BomSettings settings)
|
||
|
|
{
|
||
|
|
settings?.Save();
|
||
|
|
}
|
||
|
|
|
||
|
|
public List<BomItemModel> GetFlatBomItems(List<BomItemModel> allItems)
|
||
|
|
{
|
||
|
|
return allItems
|
||
|
|
.Where(i => !i.IsAssembly)
|
||
|
|
.GroupBy(i => i.DrawingNo ?? "")
|
||
|
|
.Select(g =>
|
||
|
|
{
|
||
|
|
var first = g.First();
|
||
|
|
return new BomItemModel
|
||
|
|
{
|
||
|
|
Level = 0,
|
||
|
|
LevelDisplay = "",
|
||
|
|
DrawingNo = first.DrawingNo,
|
||
|
|
ConfigName = first.ConfigName,
|
||
|
|
PartName = first.PartName,
|
||
|
|
MaterialProp = first.MaterialProp,
|
||
|
|
Material = first.Material,
|
||
|
|
Classification = first.Classification,
|
||
|
|
Quantity = g.Sum(x => x.Quantity),
|
||
|
|
IsAssembly = false,
|
||
|
|
IsOutSourcing = first.IsOutSourcing,
|
||
|
|
DocPath = first.DocPath,
|
||
|
|
Props = first.Props,
|
||
|
|
HasChildren = false,
|
||
|
|
IsExpanded = false,
|
||
|
|
IsVisible = true
|
||
|
|
};
|
||
|
|
})
|
||
|
|
.ToList();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void EnsurePropsKeys(List<BomItemModel> items, List<string> keys)
|
||
|
|
{
|
||
|
|
foreach (var item in items)
|
||
|
|
{
|
||
|
|
if (item.Props == null)
|
||
|
|
{
|
||
|
|
item.Props = new Dictionary<string, string>();
|
||
|
|
}
|
||
|
|
foreach (var key in keys)
|
||
|
|
{
|
||
|
|
if (!item.Props.ContainsKey(key))
|
||
|
|
{
|
||
|
|
item.Props[key] = "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int GetTotalComponentCount(ModelDoc2 model)
|
||
|
|
{
|
||
|
|
AssemblyDoc assembly = model as AssemblyDoc;
|
||
|
|
if (assembly == null)
|
||
|
|
{
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
object[] components = assembly.GetComponents(false) as object[];
|
||
|
|
return Math.Max((components?.Length ?? 0) + 1, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool HasLightweightComponents(ModelDoc2 model)
|
||
|
|
{
|
||
|
|
AssemblyDoc assembly = model as AssemblyDoc;
|
||
|
|
if (assembly == null) return false;
|
||
|
|
|
||
|
|
object[] components = assembly.GetComponents(false) as object[];
|
||
|
|
if (components == null) return false;
|
||
|
|
|
||
|
|
foreach (object obj in components)
|
||
|
|
{
|
||
|
|
Component2 comp = obj as Component2;
|
||
|
|
if (comp == null) continue;
|
||
|
|
int state = comp.GetSuppression();
|
||
|
|
// swComponentLightweight = 4, swComponentFullyLightweight = 8
|
||
|
|
if (state == 4 || state == 8) return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|