NavisworksTransport/doc/working/LayerManagement_Technical_Implementation_Guide.md
2025-08-18 23:55:01 +08:00

29 KiB
Raw Blame History

分层管理功能重构技术实现指南

技术架构概览

系统组件关系图

┌─────────────────────────────────────────────────────────────┐
│                    LogisticsControlPanel                    │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────┐ │
│  │  类别设置    │ │   路径编辑   │ │   检测动画   │ │ 分层管理 │ │
│  │    Tab      │ │    Tab      │ │    Tab      │ │  Tab   │ │
│  └─────────────┘ └─────────────┘ └─────────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────┘
                                                    │
                    ┌───────────────────────────────┘
                    │
┌─────────────────────────────────────────────────────────────┐
│              ModelLayerManagementView                      │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────┐ │
│  │  楼层分析    │ │  设置层属性  │ │  分层保存    │ │选中保存 │ │
│  │   功能区     │ │   功能区     │ │   功能区     │ │ 功能区  │ │
│  └─────────────┘ └─────────────┘ └─────────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────┘
                    │
    ┌───────────────┼───────────────┐
    │               │               │
┌─────────┐ ┌──────────────┐ ┌─────────────┐
│ViewModel│ │   Service    │ │ Existing    │
│ Layer   │ │   Layer      │ │ Components  │
│         │ │              │ │             │
└─────────┘ └──────────────┘ └─────────────┘

核心技术栈

  • UI框架: WPF (XAML + C#)
  • 架构模式: MVVM (Model-View-ViewModel)
  • API集成: Navisworks 2026 Native + COM API
  • 异步处理: async/await + Task
  • 事件驱动: EventHandler + INotifyPropertyChanged

详细实现方案

1. 楼层分析功能实现

1.1 核心数据结构

/// <summary>
/// 楼层分析结果数据模型
/// </summary>
public class FloorAnalysisResult : INotifyPropertyChanged
{
    public string AttributeName { get; set; }           // 属性名称
    public int FloorCount { get; set; }                 // 检测到的楼层数
    public double QualityScore { get; set; }            // 质量评分 (0-100)
    public List<string> FloorNames { get; set; }        // 楼层名称列表
    public bool IsFeasible { get; set; }                // 是否可行
    public string RecommendationText { get; set; }      // 建议文本
    public ObservableCollection<FloorInfo> Floors { get; set; }  // 详细楼层信息
}

1.2 分析算法实现

/// <summary>
/// 执行楼层分析
/// </summary>
public async Task<FloorAnalysisResult> AnalyzeFloorsAsync()
{
    try
    {
        OnStatusChanged("正在分析模型楼层结构...");
        
        // 1. 获取可用的楼层属性
        var availableAttributes = FloorDetector.GetAvailableFloorAttributes();
        
        // 2. 为每个属性计算质量评分
        var bestAttribute = await FindBestFloorAttributeAsync(availableAttributes);
        
        // 3. 基于最佳属性检测楼层
        var detectedFloors = await FloorDetector.DetectFloorsByAttributeAsync(bestAttribute);
        
        // 4. 计算分析结果
        var result = new FloorAnalysisResult
        {
            AttributeName = bestAttribute,
            FloorCount = detectedFloors.Count,
            QualityScore = CalculateQualityScore(detectedFloors),
            FloorNames = detectedFloors.Select(f => f.FloorName).ToList(),
            IsFeasible = detectedFloors.Count >= 2 && CalculateQualityScore(detectedFloors) > 60,
            Floors = new ObservableCollection<FloorInfo>(detectedFloors)
        };
        
        result.RecommendationText = GenerateRecommendation(result);
        
        OnStatusChanged($"楼层分析完成: 检测到 {result.FloorCount} 个楼层");
        return result;
    }
    catch (Exception ex)
    {
        LogManager.Error($"楼层分析失败: {ex.Message}");
        throw;
    }
}

/// <summary>
/// 计算楼层属性质量评分
/// </summary>
private double CalculateQualityScore(List<FloorInfo> floors)
{
    if (floors == null || floors.Count == 0) return 0;
    
    double score = 0;
    
    // 1. 楼层数量评分 (30%)
    var countScore = Math.Min(floors.Count * 10, 30);
    
    // 2. 命名规范性评分 (40%)
    var namingScore = CalculateNamingQuality(floors) * 40;
    
    // 3. 高程分布评分 (30%)
    var elevationScore = CalculateElevationQuality(floors) * 30;
    
    return countScore + namingScore + elevationScore;
}

1.3 UI实现 (XAML片段)

<!-- 楼层分析功能区 -->
<GroupBox Header="楼层分析" Margin="5" Height="300">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <!-- 分析控制区 -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">
            <Button Content="开始分析" Command="{Binding AnalyzeFloorsCommand}" 
                    Padding="10,5" Margin="0,0,10,0"/>
            <TextBlock Text="{Binding AnalysisStatus}" VerticalAlignment="Center" 
                      Foreground="Blue"/>
        </StackPanel>
        
        <!-- 分析结果展示 -->
        <DataGrid Grid.Row="1" ItemsSource="{Binding AnalysisResult.Floors}" 
                  AutoGenerateColumns="False" IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="楼层名称" Binding="{Binding FloorName}" Width="120"/>
                <DataGridTextColumn Header="标高(m)" Binding="{Binding Elevation, StringFormat=F2}" Width="80"/>
                <DataGridTextColumn Header="构件数量" Binding="{Binding ItemCount}" Width="80"/>
                <DataGridCheckBoxColumn Header="有效" Binding="{Binding IsValid}" Width="60"/>
            </DataGrid.Columns>
        </DataGrid>
        
        <!-- 质量评分显示 -->
        <StackPanel Grid.Row="2" Margin="0,10,0,0">
            <TextBlock Text="{Binding AnalysisResult.QualityScore, StringFormat='质量评分: {0:F1}/100'}" 
                      FontWeight="Bold"/>
            <TextBlock Text="{Binding AnalysisResult.RecommendationText}" 
                      Foreground="DarkGreen" TextWrapping="Wrap"/>
        </StackPanel>
    </Grid>
</GroupBox>

2. 设置层属性功能实现

2.1 属性设置服务

/// <summary>
/// 层属性设置服务
/// </summary>
public class LayerAttributeService
{
    private readonly CategoryAttributeManager _attributeManager;
    
    public LayerAttributeService()
    {
        _attributeManager = new CategoryAttributeManager();
    }
    
    /// <summary>
    /// 为选中的模型项设置层属性
    /// </summary>
    public async Task<bool> SetLayerAttributeAsync(ModelItemCollection items, string layerName)
    {
        try
        {
            OnStatusChanged($"正在为 {items.Count} 个构件设置层属性...");
            
            // 使用COM API确保属性持久化
            var success = await Task.Run(() => 
            {
                return _attributeManager.SetLogisticsAttribute(items, "Layer", layerName);
            });
            
            if (success)
            {
                OnStatusChanged($"成功为 {items.Count} 个构件设置层属性: {layerName}");
                LayerAttributeChanged?.Invoke(this, new LayerAttributeChangedEventArgs(items, layerName));
            }
            
            return success;
        }
        catch (Exception ex)
        {
            LogManager.Error($"设置层属性失败: {ex.Message}");
            return false;
        }
    }
    
    /// <summary>
    /// 批量设置多个楼层的属性
    /// </summary>
    public async Task<Dictionary<string, bool>> BatchSetLayerAttributesAsync(
        Dictionary<string, ModelItemCollection> layerGroups)
    {
        var results = new Dictionary<string, bool>();
        
        foreach (var group in layerGroups)
        {
            var success = await SetLayerAttributeAsync(group.Value, group.Key);
            results[group.Key] = success;
            
            // 添加延迟避免API过载
            await Task.Delay(100);
        }
        
        return results;
    }
    
    public event EventHandler<LayerAttributeChangedEventArgs> LayerAttributeChanged;
    public event EventHandler<string> StatusChanged;
    
    private void OnStatusChanged(string status) => StatusChanged?.Invoke(this, status);
}

2.2 选择树操作界面

<!-- 设置层属性功能区 -->
<GroupBox Header="设置层属性" Margin="5" Height="350">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <!-- 操作控制区 -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">
            <Label Content="目标楼层:" VerticalAlignment="Center"/>
            <ComboBox ItemsSource="{Binding AvailableFloors}" 
                     SelectedItem="{Binding SelectedTargetFloor}"
                     Width="120" Margin="5,0"/>
            <Button Content="设置选中项" Command="{Binding SetSelectedItemsLayerCommand}" 
                    Padding="10,5" Margin="10,0"/>
        </StackPanel>
        
        <!-- 选择树视图 -->
        <TreeView Grid.Row="1" ItemsSource="{Binding ModelTreeItems}" 
                 BorderBrush="LightGray" BorderThickness="1">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding IsSelected}" 
                                 Command="{Binding DataContext.ToggleSelectionCommand, 
                                          RelativeSource={RelativeSource AncestorType=UserControl}}"
                                 CommandParameter="{Binding}"/>
                        <TextBlock Text="{Binding Name}" Margin="5,0"/>
                        <TextBlock Text="{Binding ItemCount, StringFormat='({0})'}" 
                                  Foreground="Gray" Margin="5,0"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
        
        <!-- 状态信息 -->
        <StackPanel Grid.Row="2" Margin="0,10,0,0">
            <TextBlock Text="{Binding SelectedItemsInfo}" FontWeight="Bold"/>
            <TextBlock Text="{Binding AttributeSetStatus}" Foreground="Green"/>
        </StackPanel>
    </Grid>
</GroupBox>

3. 分层保存功能实现

3.1 简化的分层配置

/// <summary>
/// 简化的分层保存配置
/// </summary>
public class SimpleSplitConfiguration
{
    public SplitStrategy Strategy { get; set; } = SplitStrategy.ByFloor;
    public string AttributeName { get; set; } = "Layer";
    public string OutputDirectory { get; set; }
    public string FileNameTemplate { get; set; } = "{ProjectName}_{LayerName}";
    public bool EnablePreview { get; set; } = true;
    public bool GenerateReport { get; set; } = true;
    
    /// <summary>
    /// 转换为完整的ModelSplitter配置
    /// </summary>
    public SplitConfiguration ToFullConfiguration()
    {
        return new SplitConfiguration
        {
            Strategy = this.Strategy,
            AttributeName = this.AttributeName,
            OutputDirectory = this.OutputDirectory,
            FileNamePattern = this.FileNameTemplate,
            IncludeEmptyLayers = false,
            PreserveOriginalStructure = true,
            GenerateReport = this.GenerateReport,
            CreateSubDirectories = false
        };
    }
}

3.2 预览功能实现

/// <summary>
/// 生成分层保存预览
/// </summary>
public async Task<List<LayerPreviewInfo>> GenerateLayerPreviewAsync(SimpleSplitConfiguration config)
{
    try
    {
        OnStatusChanged("正在生成分层预览...");
        
        // 复用ModelSplitterManager的预览功能
        var fullConfig = config.ToFullConfiguration();
        var previewResults = await _modelSplitter.PreviewSplit(fullConfig);
        
        var previewInfos = previewResults.Select(result => new LayerPreviewInfo
        {
            LayerName = result.LayerName,
            ItemCount = result.ItemCount,
            EstimatedFileSize = EstimateFileSize(result.Items),
            OutputPath = result.OutputFilePath,
            IsValid = result.ItemCount > 0
        }).ToList();
        
        OnStatusChanged($"预览生成完成: {previewInfos.Count} 个图层");
        return previewInfos;
    }
    catch (Exception ex)
    {
        LogManager.Error($"生成预览失败: {ex.Message}");
        throw;
    }
}

/// <summary>
/// 执行分层保存
/// </summary>
public async Task<bool> ExecuteLayerSplitAsync(SimpleSplitConfiguration config, 
    IProgress<SplitProgressInfo> progress = null)
{
    try
    {
        OnStatusChanged("开始分层保存...");
        
        var fullConfig = config.ToFullConfiguration();
        
        // 设置进度回调
        if (progress != null)
        {
            _modelSplitter.ProgressChanged += (s, e) => 
            {
                progress.Report(new SplitProgressInfo
                {
                    CurrentLayer = e.UserState?.ToString(),
                    ProgressPercentage = e.ProgressPercentage,
                    StatusText = $"正在处理: {e.UserState}"
                });
            };
        }
        
        var results = await _modelSplitter.ExecuteSplitAsync(fullConfig);
        var successCount = results.Count(r => r.Success);
        
        OnStatusChanged($"分层保存完成: {successCount}/{results.Count} 个文件成功保存");
        
        return successCount == results.Count;
    }
    catch (Exception ex)
    {
        LogManager.Error($"分层保存失败: {ex.Message}");
        return false;
    }
}

3.3 分层保存UI

<!-- 分层保存功能区 -->
<GroupBox Header="分层保存" Margin="5" Height="400">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <!-- 配置区 -->
        <StackPanel Grid.Row="0" Margin="0,0,0,10">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                
                <Label Grid.Row="0" Grid.Column="0" Content="分层依据:"/>
                <ComboBox Grid.Row="0" Grid.Column="1" 
                         ItemsSource="{Binding SplitStrategies}"
                         SelectedItem="{Binding SelectedSplitStrategy}"
                         Margin="5,0"/>
                
                <Label Grid.Row="1" Grid.Column="0" Content="输出目录:"/>
                <TextBox Grid.Row="1" Grid.Column="1" 
                        Text="{Binding OutputDirectory}" Margin="5,0"/>
                <Button Grid.Row="1" Grid.Column="2" Content="浏览" 
                       Command="{Binding BrowseOutputDirectoryCommand}" Margin="5,0"/>
            </Grid>
        </StackPanel>
        
        <!-- 操作按钮 -->
        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,10">
            <Button Content="生成预览" Command="{Binding GeneratePreviewCommand}" 
                    Padding="10,5" Margin="0,0,10,0"/>
            <Button Content="开始保存" Command="{Binding StartSplitCommand}" 
                    Padding="10,5" Margin="0,0,10,0"/>
            <CheckBox Content="生成报告" IsChecked="{Binding GenerateReport}" 
                     VerticalAlignment="Center" Margin="10,0"/>
        </StackPanel>
        
        <!-- 预览列表 -->
        <DataGrid Grid.Row="2" ItemsSource="{Binding LayerPreviews}" 
                 AutoGenerateColumns="False" IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridCheckBoxColumn Header="导出" Binding="{Binding IsSelected}" Width="50"/>
                <DataGridTextColumn Header="图层名称" Binding="{Binding LayerName}" Width="150"/>
                <DataGridTextColumn Header="构件数量" Binding="{Binding ItemCount}" Width="80"/>
                <DataGridTextColumn Header="预估大小" Binding="{Binding EstimatedFileSize}" Width="80"/>
                <DataGridTextColumn Header="输出路径" Binding="{Binding OutputPath}" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>
        
        <!-- 进度显示 -->
        <StackPanel Grid.Row="3" Margin="0,10,0,0">
            <TextBlock Text="{Binding SplitStatus}" FontWeight="Bold"/>
            <ProgressBar Value="{Binding SplitProgress}" Maximum="100" Height="20" Margin="0,5"/>
        </StackPanel>
    </Grid>
</GroupBox>

4. 选中保存功能实现

4.1 选中内容保存服务

/// <summary>
/// 选中内容保存服务
/// </summary>
public class SelectionExportService
{
    /// <summary>
    /// 导出当前选中的内容
    /// </summary>
    public async Task<bool> ExportCurrentSelectionAsync(string outputPath, 
        IProgress<int> progress = null)
    {
        try
        {
            // 获取当前选择
            var selection = NavisApplication.ActiveDocument.CurrentSelection;
            if (selection.IsEmpty)
            {
                throw new InvalidOperationException("当前没有选中任何内容");
            }
            
            OnStatusChanged($"正在导出 {selection.Count} 个选中项...");
            
            // 创建临时文档
            var tempDoc = new Document();
            
            // 复制选中内容到临时文档
            await Task.Run(() =>
            {
                tempDoc.CurrentSelection.CopyFrom(selection);
                
                // 报告进度
                progress?.Report(50);
                
                // 保存文档
                tempDoc.SaveFile(outputPath);
                
                progress?.Report(100);
            });
            
            OnStatusChanged($"选中内容已成功导出到: {outputPath}");
            return true;
        }
        catch (Exception ex)
        {
            LogManager.Error($"导出选中内容失败: {ex.Message}");
            return false;
        }
    }
    
    /// <summary>
    /// 获取选中内容的统计信息
    /// </summary>
    public SelectionInfo GetSelectionInfo()
    {
        var selection = NavisApplication.ActiveDocument.CurrentSelection;
        
        return new SelectionInfo
        {
            ItemCount = selection.Count,
            IsEmpty = selection.IsEmpty,
            BoundingBox = selection.IsEmpty ? null : selection.ComputeBoundingBox(),
            Categories = GetSelectionCategories(selection)
        };
    }
    
    public event EventHandler<string> StatusChanged;
    private void OnStatusChanged(string status) => StatusChanged?.Invoke(this, status);
}

/// <summary>
/// 选中内容信息
/// </summary>
public class SelectionInfo
{
    public int ItemCount { get; set; }
    public bool IsEmpty { get; set; }
    public BoundingBox3D BoundingBox { get; set; }
    public Dictionary<string, int> Categories { get; set; }
    
    public string Summary => IsEmpty ? "未选中任何内容" : 
        $"已选中 {ItemCount} 个构件,范围: {FormatBounds()}";
        
    private string FormatBounds()
    {
        if (BoundingBox == null) return "未知";
        var size = BoundingBox.Max - BoundingBox.Min;
        return $"{size.X:F1}×{size.Y:F1}×{size.Z:F1}m";
    }
}

4.2 选中保存UI

<!-- 选中保存功能区 -->
<GroupBox Header="选中保存" Margin="5" Height="250">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <!-- 选中信息显示 -->
        <StackPanel Grid.Row="0" Margin="0,0,0,10">
            <TextBlock Text="{Binding SelectionInfo.Summary}" FontWeight="Bold"/>
            <TextBlock Text="{Binding SelectionInfo.Categories, 
                              Converter={StaticResource DictionaryToStringConverter}}" 
                      Foreground="Gray" FontSize="10"/>
        </StackPanel>
        
        <!-- 类别分布 -->
        <ListView Grid.Row="1" ItemsSource="{Binding SelectionInfo.Categories}" 
                 Visibility="{Binding SelectionInfo.IsEmpty, 
                             Converter={StaticResource BoolToVisibilityConverter}, 
                             ConverterParameter=Invert}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="类别" DisplayMemberBinding="{Binding Key}" Width="120"/>
                    <GridViewColumn Header="数量" DisplayMemberBinding="{Binding Value}" Width="60"/>
                </GridView>
            </ListView.View>
        </ListView>
        
        <!-- 导出控制 -->
        <StackPanel Grid.Row="2" Margin="0,10,0,0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                
                <Label Grid.Column="0" Content="文件名:" VerticalAlignment="Center"/>
                <TextBox Grid.Column="1" Text="{Binding ExportFileName}" Margin="5,0"/>
                <Button Grid.Column="2" Content="导出" 
                       Command="{Binding ExportSelectionCommand}" 
                       IsEnabled="{Binding SelectionInfo.IsEmpty, 
                                  Converter={StaticResource InverseBooleanConverter}}"
                       Padding="10,5" Margin="5,0"/>
            </Grid>
            <ProgressBar Value="{Binding ExportProgress}" Maximum="100" 
                        Height="15" Margin="0,5"/>
            <TextBlock Text="{Binding ExportStatus}" Foreground="Green"/>
        </StackPanel>
    </Grid>
</GroupBox>

性能优化策略

1. 内存管理优化

/// <summary>
/// 大模型处理的内存优化策略
/// </summary>
public class MemoryOptimizedProcessor
{
    private const int BATCH_SIZE = 1000;  // 批处理大小
    
    /// <summary>
    /// 分批处理大型模型
    /// </summary>
    public async Task<List<TResult>> ProcessInBatchesAsync<TSource, TResult>(
        IEnumerable<TSource> source, 
        Func<IEnumerable<TSource>, Task<IEnumerable<TResult>>> processor,
        IProgress<int> progress = null)
    {
        var results = new List<TResult>();
        var batches = source.Batch(BATCH_SIZE).ToList();
        
        for (int i = 0; i < batches.Count; i++)
        {
            var batch = batches[i];
            var batchResults = await processor(batch);
            results.AddRange(batchResults);
            
            // 强制垃圾回收
            if (i % 10 == 0)
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            
            // 报告进度
            progress?.Report((i + 1) * 100 / batches.Count);
        }
        
        return results;
    }
}

2. 异步操作取消支持

/// <summary>
/// 支持取消的异步操作基类
/// </summary>
public abstract class CancellableAsyncOperation
{
    protected CancellationTokenSource _cancellationTokenSource;
    
    public bool IsCancelled => _cancellationTokenSource?.Token.IsCancellationRequested ?? false;
    
    public void Cancel()
    {
        _cancellationTokenSource?.Cancel();
        OnStatusChanged("操作已取消");
    }
    
    protected virtual void OnStatusChanged(string status)
    {
        StatusChanged?.Invoke(this, status);
    }
    
    public event EventHandler<string> StatusChanged;
}

错误处理与日志记录

1. 统一异常处理

/// <summary>
/// 分层管理异常处理器
/// </summary>
public class LayerManagementExceptionHandler
{
    public static async Task<TResult> ExecuteWithExceptionHandlingAsync<TResult>(
        Func<Task<TResult>> operation, 
        string operationName,
        TResult defaultValue = default(TResult))
    {
        try
        {
            return await operation();
        }
        catch (UnauthorizedAccessException ex)
        {
            var message = $"{operationName}失败: 文件访问权限不足 - {ex.Message}";
            LogManager.Error(message);
            MessageBox.Show(message, "权限错误", MessageBoxButton.OK, MessageBoxImage.Warning);
            return defaultValue;
        }
        catch (OutOfMemoryException ex)
        {
            var message = $"{operationName}失败: 内存不足,请尝试分批处理 - {ex.Message}";
            LogManager.Error(message);
            MessageBox.Show(message, "内存错误", MessageBoxButton.OK, MessageBoxImage.Error);
            return defaultValue;
        }
        catch (Exception ex)
        {
            var message = $"{operationName}失败: {ex.Message}";
            LogManager.Error(message, ex);
            MessageBox.Show(message, "操作失败", MessageBoxButton.OK, MessageBoxImage.Error);
            return defaultValue;
        }
    }
}

2. 操作日志记录

/// <summary>
/// 分层管理操作日志
/// </summary>
public class LayerManagementAuditLog
{
    public static void LogLayerAnalysis(FloorAnalysisResult result)
    {
        LogManager.Info($"楼层分析完成: 属性={result.AttributeName}, " +
                       $"楼层数={result.FloorCount}, 质量评分={result.QualityScore:F1}");
    }
    
    public static void LogAttributeSetting(string layerName, int itemCount, bool success)
    {
        var status = success ? "成功" : "失败";
        LogManager.Info($"层属性设置{status}: 楼层={layerName}, 构件数={itemCount}");
    }
    
    public static void LogLayerSplit(string strategy, int layerCount, int successCount)
    {
        LogManager.Info($"分层保存完成: 策略={strategy}, " +
                       $"总层数={layerCount}, 成功={successCount}");
    }
    
    public static void LogSelectionExport(int itemCount, string outputPath, bool success)
    {
        var status = success ? "成功" : "失败";
        LogManager.Info($"选中导出{status}: 构件数={itemCount}, 路径={outputPath}");
    }
}

集成测试方案

1. 单元测试示例

[TestClass]
public class LayerManagementTests
{
    [TestMethod]
    public async Task AnalyzeFloors_WithValidModel_ReturnsValidResult()
    {
        // Arrange
        var viewModel = new ModelLayerManagementViewModel();
        
        // Act
        var result = await viewModel.AnalyzeFloorsAsync();
        
        // Assert
        Assert.IsNotNull(result);
        Assert.IsTrue(result.FloorCount > 0);
        Assert.IsTrue(result.QualityScore >= 0 && result.QualityScore <= 100);
    }
    
    [TestMethod]
    public async Task SetLayerAttribute_WithValidSelection_ReturnsTrue()
    {
        // Arrange
        var service = new LayerAttributeService();
        var mockItems = CreateMockModelItems();
        
        // Act
        var success = await service.SetLayerAttributeAsync(mockItems, "TestFloor");
        
        // Assert
        Assert.IsTrue(success);
    }
}

2. 集成测试检查清单

  • 楼层分析功能在不同模型类型下的表现
  • 属性设置在大型选择集下的性能
  • 分层保存的文件完整性验证
  • 选中导出的数据一致性检查
  • 内存使用情况监控
  • 异常恢复机制验证

文档创建时间: 2025-08-18
技术架构版本: v1.0
适用范围: NavisworksTransport分层管理功能重构