744 lines
24 KiB
C#
744 lines
24 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
|
||
namespace NavisworksTransport.Core.SystemManagement
|
||
{
|
||
#region 事件参数定义
|
||
|
||
/// <summary>
|
||
/// 系统状态变更事件参数
|
||
/// </summary>
|
||
public class SystemStatusChangedEventArgs : EventArgs
|
||
{
|
||
public string Status { get; set; }
|
||
public string StatusColor { get; set; }
|
||
public DateTime Timestamp { get; set; }
|
||
public string Details { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 性能警告事件参数
|
||
/// </summary>
|
||
public class PerformanceAlertEventArgs : EventArgs
|
||
{
|
||
public PerformanceAlertType AlertType { get; set; }
|
||
public string Message { get; set; }
|
||
public DateTime Timestamp { get; set; }
|
||
public double Value { get; set; }
|
||
public double Threshold { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 配置变更事件参数
|
||
/// </summary>
|
||
public class ConfigurationChangedEventArgs : EventArgs
|
||
{
|
||
public string ConfigKey { get; set; }
|
||
public object OldValue { get; set; }
|
||
public object NewValue { get; set; }
|
||
public string ProfileName { get; set; }
|
||
public DateTime Timestamp { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 性能警告类型枚举
|
||
/// </summary>
|
||
public enum PerformanceAlertType
|
||
{
|
||
MemoryHigh,
|
||
CpuHigh,
|
||
ThreadCountHigh,
|
||
ResponseTimeLow
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 数据模型
|
||
|
||
/// <summary>
|
||
/// 日志状态数据模型
|
||
/// </summary>
|
||
public class LogStatus
|
||
{
|
||
public string Message { get; set; }
|
||
public int EntryCount { get; set; }
|
||
public string FilePath { get; set; }
|
||
public DateTime LastUpdate { get; set; }
|
||
public long FileSizeBytes { get; set; }
|
||
public string CurrentLevel { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 性能数据模型
|
||
/// </summary>
|
||
public class PerformanceData
|
||
{
|
||
public double CpuUsage { get; set; }
|
||
public long MemoryUsageMB { get; set; }
|
||
public int ThreadCount { get; set; }
|
||
public TimeSpan RunningTime { get; set; }
|
||
public int HandleCount { get; set; }
|
||
public double ResponseTimeMs { get; set; }
|
||
public DateTime Timestamp { get; set; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 配置档案数据模型
|
||
/// </summary>
|
||
public class ConfigProfile
|
||
{
|
||
public string Name { get; set; }
|
||
public Dictionary<string, object> Settings { get; set; }
|
||
public DateTime CreatedAt { get; set; }
|
||
public DateTime LastModified { get; set; }
|
||
public bool IsDefault { get; set; }
|
||
public string Description { get; set; }
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 系统日志管理器实现
|
||
|
||
/// <summary>
|
||
/// 默认系统日志管理器实现
|
||
/// </summary>
|
||
public class DefaultSystemLogManager : ISystemLogManager
|
||
{
|
||
private readonly string _logDirectory;
|
||
private readonly string _logFilePath;
|
||
private string _currentLogLevel = "Info";
|
||
|
||
public DefaultSystemLogManager()
|
||
{
|
||
_logDirectory = Path.Combine(Environment.CurrentDirectory, "Logs");
|
||
_logFilePath = Path.Combine(_logDirectory, "NavisworksTransport.log");
|
||
|
||
// 确保日志目录存在
|
||
if (!Directory.Exists(_logDirectory))
|
||
{
|
||
Directory.CreateDirectory(_logDirectory);
|
||
}
|
||
}
|
||
|
||
public async Task OpenLogViewerAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
// 检查是否存在自定义日志查看器
|
||
var logViewerPath = Path.Combine(Environment.CurrentDirectory, "tools", "LogViewer.exe");
|
||
|
||
if (File.Exists(logViewerPath))
|
||
{
|
||
// 使用自定义日志查看器
|
||
Process.Start(logViewerPath, $"\"{_logFilePath}\"");
|
||
}
|
||
else if (File.Exists(_logFilePath))
|
||
{
|
||
// 使用默认文本编辑器打开
|
||
Process.Start("notepad.exe", _logFilePath);
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("日志文件不存在", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"打开日志查看器失败: {ex.Message}", ex);
|
||
MessageBox.Show($"打开日志查看器失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
});
|
||
}
|
||
|
||
public async Task ClearLogsAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
if (File.Exists(_logFilePath))
|
||
{
|
||
// 备份当前日志文件
|
||
var backupPath = Path.Combine(_logDirectory, $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.log");
|
||
File.Move(_logFilePath, backupPath);
|
||
|
||
LogManager.Info("日志已清空,备份文件已创建");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"清空日志失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
});
|
||
}
|
||
|
||
public async Task<string> ExportLogsAsync()
|
||
{
|
||
return await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
var exportDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "NavisworksTransport_Logs");
|
||
if (!Directory.Exists(exportDirectory))
|
||
{
|
||
Directory.CreateDirectory(exportDirectory);
|
||
}
|
||
|
||
var exportFileName = $"NavisworksTransport_Log_{DateTime.Now:yyyyMMdd_HHmmss}.zip";
|
||
var exportPath = Path.Combine(exportDirectory, exportFileName);
|
||
|
||
// 这里可以使用System.IO.Compression.ZipFile来创建压缩包
|
||
// 包含主日志文件和任何相关的日志文件
|
||
if (File.Exists(_logFilePath))
|
||
{
|
||
var singleLogExportPath = Path.Combine(exportDirectory, $"NavisworksTransport_Log_{DateTime.Now:yyyyMMdd_HHmmss}.log");
|
||
File.Copy(_logFilePath, singleLogExportPath);
|
||
return singleLogExportPath;
|
||
}
|
||
|
||
return exportPath;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"导出日志失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
});
|
||
}
|
||
|
||
public async Task<LogStatus> GetLogStatusAsync()
|
||
{
|
||
return await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
var status = new LogStatus
|
||
{
|
||
FilePath = _logFilePath,
|
||
CurrentLevel = _currentLogLevel,
|
||
LastUpdate = DateTime.Now
|
||
};
|
||
|
||
if (File.Exists(_logFilePath))
|
||
{
|
||
var fileInfo = new FileInfo(_logFilePath);
|
||
status.FileSizeBytes = fileInfo.Length;
|
||
status.LastUpdate = fileInfo.LastWriteTime;
|
||
|
||
// 估算日志条目数量(简单实现)
|
||
var lines = File.ReadAllLines(_logFilePath);
|
||
status.EntryCount = lines.Length;
|
||
status.Message = $"日志文件正常,共 {status.EntryCount} 条记录";
|
||
}
|
||
else
|
||
{
|
||
status.EntryCount = 0;
|
||
status.FileSizeBytes = 0;
|
||
status.Message = "日志文件不存在";
|
||
}
|
||
|
||
return status;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"获取日志状态失败: {ex.Message}", ex);
|
||
return new LogStatus
|
||
{
|
||
Message = $"获取日志状态失败: {ex.Message}",
|
||
EntryCount = 0,
|
||
FilePath = _logFilePath,
|
||
CurrentLevel = _currentLogLevel
|
||
};
|
||
}
|
||
});
|
||
}
|
||
|
||
public void SetLogLevel(string level)
|
||
{
|
||
try
|
||
{
|
||
_currentLogLevel = level;
|
||
// 这里需要与实际的日志系统集成
|
||
LogManager.SetLogLevel(level);
|
||
LogManager.Info($"日志级别已设置为: {level}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"设置日志级别失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
// 清理资源
|
||
LogManager.Info("SystemLogManager已清理");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 系统配置管理器实现
|
||
|
||
/// <summary>
|
||
/// 默认系统配置管理器实现
|
||
/// </summary>
|
||
public class DefaultSystemConfigManager : ISystemConfigManager
|
||
{
|
||
private readonly string _configDirectory;
|
||
private readonly string _configFilePath;
|
||
private Dictionary<string, object> _currentSettings;
|
||
private ConfigProfile _currentProfile;
|
||
|
||
public event EventHandler<ConfigurationChangedEventArgs> ConfigurationChanged;
|
||
|
||
public DefaultSystemConfigManager()
|
||
{
|
||
_configDirectory = Path.Combine(Environment.CurrentDirectory, "Config");
|
||
_configFilePath = Path.Combine(_configDirectory, "settings.json");
|
||
_currentSettings = new Dictionary<string, object>();
|
||
|
||
// 确保配置目录存在
|
||
if (!Directory.Exists(_configDirectory))
|
||
{
|
||
Directory.CreateDirectory(_configDirectory);
|
||
}
|
||
|
||
// 加载默认配置
|
||
LoadDefaultSettings();
|
||
}
|
||
|
||
private void LoadDefaultSettings()
|
||
{
|
||
_currentSettings = new Dictionary<string, object>
|
||
{
|
||
{ "AutoSaveEnabled", true },
|
||
{ "AutoSaveInterval", 300 },
|
||
{ "DebugModeEnabled", false },
|
||
{ "LogLevel", "Info" },
|
||
{ "WorkingDirectory", Environment.CurrentDirectory },
|
||
{ "MaxMemoryUsageMB", 1024 },
|
||
{ "PerformanceMonitoringEnabled", true }
|
||
};
|
||
|
||
_currentProfile = new ConfigProfile
|
||
{
|
||
Name = "默认配置",
|
||
Settings = new Dictionary<string, object>(_currentSettings),
|
||
CreatedAt = DateTime.Now,
|
||
LastModified = DateTime.Now,
|
||
IsDefault = true,
|
||
Description = "系统默认配置档案"
|
||
};
|
||
}
|
||
|
||
public void SetAutoSaveEnabled(bool enabled)
|
||
{
|
||
SetSetting("AutoSaveEnabled", enabled);
|
||
}
|
||
|
||
public void SetDebugMode(bool enabled)
|
||
{
|
||
SetSetting("DebugModeEnabled", enabled);
|
||
}
|
||
|
||
public void SetAutoSaveInterval(int seconds)
|
||
{
|
||
SetSetting("AutoSaveInterval", seconds);
|
||
}
|
||
|
||
private void SetSetting(string key, object value)
|
||
{
|
||
try
|
||
{
|
||
var oldValue = _currentSettings.ContainsKey(key) ? _currentSettings[key] : null;
|
||
_currentSettings[key] = value;
|
||
|
||
// 触发配置变更事件
|
||
ConfigurationChanged?.Invoke(this, new ConfigurationChangedEventArgs
|
||
{
|
||
ConfigKey = key,
|
||
OldValue = oldValue,
|
||
NewValue = value,
|
||
ProfileName = _currentProfile?.Name,
|
||
Timestamp = DateTime.Now
|
||
});
|
||
|
||
LogManager.Info($"配置项已更新: {key} = {value}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"设置配置项失败 {key}: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
public async Task SaveConfigAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
// 这里应该实现JSON序列化保存
|
||
// var json = JsonConvert.SerializeObject(_currentSettings, Formatting.Indented);
|
||
// File.WriteAllText(_configFilePath, json);
|
||
|
||
LogManager.Info("配置已保存到文件");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"保存配置失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
});
|
||
}
|
||
|
||
public async Task LoadConfigAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
if (File.Exists(_configFilePath))
|
||
{
|
||
// var json = File.ReadAllText(_configFilePath);
|
||
// _currentSettings = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
|
||
LogManager.Info("配置已从文件加载");
|
||
}
|
||
else
|
||
{
|
||
LoadDefaultSettings();
|
||
LogManager.Info("使用默认配置");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"加载配置失败: {ex.Message}", ex);
|
||
LoadDefaultSettings();
|
||
}
|
||
});
|
||
}
|
||
|
||
public T GetSetting<T>(string key, T defaultValue = default(T))
|
||
{
|
||
try
|
||
{
|
||
if (_currentSettings.ContainsKey(key))
|
||
{
|
||
return (T)Convert.ChangeType(_currentSettings[key], typeof(T));
|
||
}
|
||
return defaultValue;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"获取配置项失败 {key}: {ex.Message}", ex);
|
||
return defaultValue;
|
||
}
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
// 自动保存配置
|
||
SaveConfigAsync().Wait(5000); // 等待最多5秒
|
||
LogManager.Info("SystemConfigManager已清理");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"SystemConfigManager清理失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 性能监控器实现
|
||
|
||
/// <summary>
|
||
/// 默认性能监控器实现
|
||
/// </summary>
|
||
public class DefaultPerformanceMonitor : IPerformanceMonitor
|
||
{
|
||
private readonly Process _currentProcess;
|
||
private bool _isMonitoring;
|
||
private readonly List<PerformanceData> _performanceHistory;
|
||
private readonly object _lockObject = new object();
|
||
|
||
public event EventHandler<PerformanceAlertEventArgs> PerformanceAlert;
|
||
|
||
public DefaultPerformanceMonitor()
|
||
{
|
||
_currentProcess = Process.GetCurrentProcess();
|
||
_performanceHistory = new List<PerformanceData>();
|
||
_isMonitoring = false;
|
||
}
|
||
|
||
public async Task<PerformanceData> GetCurrentPerformanceAsync()
|
||
{
|
||
return await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
_currentProcess.Refresh();
|
||
|
||
var performanceData = new PerformanceData
|
||
{
|
||
MemoryUsageMB = _currentProcess.WorkingSet64 / (1024 * 1024),
|
||
ThreadCount = _currentProcess.Threads.Count,
|
||
HandleCount = _currentProcess.HandleCount,
|
||
RunningTime = DateTime.Now - _currentProcess.StartTime,
|
||
Timestamp = DateTime.Now,
|
||
CpuUsage = GetCpuUsage(), // 需要实现CPU使用率获取
|
||
ResponseTimeMs = GetResponseTime() // 需要实现响应时间测量
|
||
};
|
||
|
||
// 检查性能阈值
|
||
CheckPerformanceThresholds(performanceData);
|
||
|
||
lock (_lockObject)
|
||
{
|
||
_performanceHistory.Add(performanceData);
|
||
|
||
// 保持历史记录在合理范围内(最多保留1000条记录)
|
||
if (_performanceHistory.Count > 1000)
|
||
{
|
||
_performanceHistory.RemoveAt(0);
|
||
}
|
||
}
|
||
|
||
return performanceData;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"获取性能数据失败: {ex.Message}", ex);
|
||
throw;
|
||
}
|
||
});
|
||
}
|
||
|
||
private double GetCpuUsage()
|
||
{
|
||
// 简单实现,实际应该使用PerformanceCounter或更准确的方法
|
||
try
|
||
{
|
||
return _currentProcess.TotalProcessorTime.TotalMilliseconds / Environment.TickCount * 100;
|
||
}
|
||
catch
|
||
{
|
||
return 0.0;
|
||
}
|
||
}
|
||
|
||
private double GetResponseTime()
|
||
{
|
||
// 这里应该实现响应时间测量逻辑
|
||
// 可以通过测试关键操作的执行时间来获得
|
||
return 50.0; // 模拟值
|
||
}
|
||
|
||
private void CheckPerformanceThresholds(PerformanceData data)
|
||
{
|
||
// 内存使用率检查(超过512MB警告)
|
||
if (data.MemoryUsageMB > 512)
|
||
{
|
||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||
{
|
||
AlertType = PerformanceAlertType.MemoryHigh,
|
||
Message = $"内存使用量较高: {data.MemoryUsageMB}MB",
|
||
Value = data.MemoryUsageMB,
|
||
Threshold = 512,
|
||
Timestamp = DateTime.Now
|
||
});
|
||
}
|
||
|
||
// 线程数量检查(超过50个线程警告)
|
||
if (data.ThreadCount > 50)
|
||
{
|
||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||
{
|
||
AlertType = PerformanceAlertType.ThreadCountHigh,
|
||
Message = $"线程数量较多: {data.ThreadCount}个",
|
||
Value = data.ThreadCount,
|
||
Threshold = 50,
|
||
Timestamp = DateTime.Now
|
||
});
|
||
}
|
||
|
||
// CPU使用率检查(超过80%警告)
|
||
if (data.CpuUsage > 80)
|
||
{
|
||
PerformanceAlert?.Invoke(this, new PerformanceAlertEventArgs
|
||
{
|
||
AlertType = PerformanceAlertType.CpuHigh,
|
||
Message = $"CPU使用率较高: {data.CpuUsage:F1}%",
|
||
Value = data.CpuUsage,
|
||
Threshold = 80,
|
||
Timestamp = DateTime.Now
|
||
});
|
||
}
|
||
}
|
||
|
||
public async Task StartMonitoringAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
_isMonitoring = true;
|
||
LogManager.Info("性能监控已启动");
|
||
});
|
||
}
|
||
|
||
public async Task StopMonitoringAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
_isMonitoring = false;
|
||
LogManager.Info("性能监控已停止");
|
||
});
|
||
}
|
||
|
||
public List<PerformanceData> GetPerformanceHistory(TimeSpan? timeRange = null)
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
if (timeRange.HasValue)
|
||
{
|
||
var cutoffTime = DateTime.Now - timeRange.Value;
|
||
return _performanceHistory.Where(p => p.Timestamp >= cutoffTime).ToList();
|
||
}
|
||
return new List<PerformanceData>(_performanceHistory);
|
||
}
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
try
|
||
{
|
||
_isMonitoring = false;
|
||
_currentProcess?.Dispose();
|
||
LogManager.Info("PerformanceMonitor已清理");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"PerformanceMonitor清理失败: {ex.Message}", ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 模型分割器管理器实现
|
||
|
||
/// <summary>
|
||
/// 默认模型分割器管理器实现
|
||
/// </summary>
|
||
public class DefaultModelSplitterManager : IModelSplitterManager
|
||
{
|
||
private bool _isRunning;
|
||
private string _outputDirectory;
|
||
|
||
public bool CanRun => !_isRunning && HasValidModel();
|
||
|
||
public DefaultModelSplitterManager()
|
||
{
|
||
_outputDirectory = Path.Combine(Environment.CurrentDirectory, "ModelSplitter", "Output");
|
||
if (!Directory.Exists(_outputDirectory))
|
||
{
|
||
Directory.CreateDirectory(_outputDirectory);
|
||
}
|
||
}
|
||
|
||
private bool HasValidModel()
|
||
{
|
||
try
|
||
{
|
||
// 检查Navisworks中是否有已加载的模型
|
||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||
return document != null && document.Models != null && document.Models.Count > 0;
|
||
}
|
||
catch
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> RunModelSplitterAsync()
|
||
{
|
||
if (!CanRun)
|
||
{
|
||
LogManager.Warning("模型分割器无法运行:条件不满足");
|
||
return false;
|
||
}
|
||
|
||
return await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
_isRunning = true;
|
||
LogManager.Info("开始模型分层拆分");
|
||
|
||
// 这里应该实现实际的模型分割逻辑
|
||
// 1. 获取当前Navisworks文档
|
||
// 2. 按照楼层、区域或其他标准进行分割
|
||
// 3. 导出各个分割后的模型
|
||
|
||
var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
|
||
if (document?.Models != null)
|
||
{
|
||
// 模拟分割过程
|
||
System.Threading.Thread.Sleep(2000);
|
||
|
||
// 实际实现中,这里会调用ModelSplitterManager的分割逻辑
|
||
// var splitterResult = ModelSplitterManager.SplitByFloors(document);
|
||
|
||
LogManager.Info("模型分层拆分完成");
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"模型分割器运行失败: {ex.Message}", ex);
|
||
return false;
|
||
}
|
||
finally
|
||
{
|
||
_isRunning = false;
|
||
}
|
||
});
|
||
}
|
||
|
||
public async Task ConfigureAsync()
|
||
{
|
||
await Task.Run(() =>
|
||
{
|
||
try
|
||
{
|
||
// 这里可以打开模型分割器的配置对话框
|
||
// 或者加载配置设置
|
||
LogManager.Info("模型分割器配置界面已打开");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"配置模型分割器失败: {ex.Message}", ex);
|
||
}
|
||
});
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
_isRunning = false;
|
||
LogManager.Info("ModelSplitterManager已清理");
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
} |