阶段一:删除冗余的UIStateMachine
- 删除 src/Core/UIStateMachine.cs - UIStateMachine和UIState枚举完全未使用 - 项目实际使用PathEditState作为状态管理 - 编译验证通过,无任何错误 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
47ade72438
commit
b048235657
@ -5,6 +5,7 @@
|
||||
### [2025/09/29]
|
||||
|
||||
1. [x] (功能)导出导航地图为图片
|
||||
2. [x] (功能)增加时间标签功能,以限速和路径段评估路径运行时间
|
||||
|
||||
### [2025/09/28]
|
||||
|
||||
|
||||
225
doc/working/code_cleanup_plan.md
Normal file
225
doc/working/code_cleanup_plan.md
Normal file
@ -0,0 +1,225 @@
|
||||
# NavisworksTransport 代码清理方案
|
||||
|
||||
**创建日期**: 2025-09-30
|
||||
**目标**: 清理冗余代码、消除重复功能、移除向后兼容逻辑
|
||||
|
||||
## 执行原则
|
||||
|
||||
遵循CLAUDE.md中的开发原则:
|
||||
|
||||
- ✅ 让问题快速暴露 > 让程序看起来正常运行
|
||||
- ✅ 报错比静默失败好
|
||||
- ✅ 最小化修改 > 复杂全面的逻辑
|
||||
- ✅ 明确拒绝向后兼容性
|
||||
|
||||
## 一、UI状态管理冗余清理
|
||||
|
||||
### 1.1 问题分析
|
||||
|
||||
**重复系统**:
|
||||
|
||||
- `UIStateManager` (src/Core/UIStateManager.cs) - 线程安全的UI更新队列机制
|
||||
- `UIStateMachine` (src/Core/UIStateMachine.cs) - UI状态转换和历史跟踪
|
||||
|
||||
**问题**:
|
||||
|
||||
- 两者都是单例模式
|
||||
- 都处理UI线程同步
|
||||
- UIStateMachine依赖UIStateManager进行UI更新
|
||||
- 造成双重抽象,增加复杂度
|
||||
|
||||
### 1.2 清理方案
|
||||
|
||||
**保留**: `UIStateManager` - 核心UI线程调度器
|
||||
|
||||
**删除**: `UIStateMachine` 及相关文件
|
||||
|
||||
- src/Core/UIStateMachine.cs
|
||||
|
||||
**迁移策略**:
|
||||
|
||||
1. 检查所有引用UIStateMachine的代码
|
||||
2. 将状态枚举(UIState)迁移到独立文件或PathPlanningModels
|
||||
3. 将状态转换逻辑简化为直接的状态变更
|
||||
4. 移除状态历史跟踪(过度设计)
|
||||
|
||||
### 1.3 UIUpdate框架简化(可选)
|
||||
|
||||
**问题**:src/Core/UIUpdate/ 目录包含完整框架(8个文件),但实际使用率低
|
||||
|
||||
**方案A(激进)**:删除整个UIUpdate框架,统一使用UIStateManager
|
||||
**方案B(保守)**:保留UIUpdateService核心,删除监控和复杂功能
|
||||
|
||||
**建议**:采用方案A - 当前项目规模不需要如此复杂的UI更新框架
|
||||
|
||||
## 二、动画管理器合并
|
||||
|
||||
### 2.1 问题分析
|
||||
|
||||
**两个动画管理器**:
|
||||
|
||||
- `PathAnimationManager` - 基于Transform的通用动画
|
||||
- `LogisticsAnimationManager` - 针对Navisworks 2026优化
|
||||
|
||||
**使用情况**:
|
||||
|
||||
- AnimationControlViewModel 同时实例化两者
|
||||
- StartAnimationCommand 使用 LogisticsAnimationManager
|
||||
- 功能有重叠
|
||||
|
||||
### 2.2 清理方案
|
||||
|
||||
**保留**: `LogisticsAnimationManager` - 符合2026专属策略
|
||||
|
||||
**删除**: `PathAnimationManager` 及相关代码
|
||||
|
||||
- src/Core/Animation/PathAnimationManager.cs
|
||||
- AnimationFrame, AnimationState, CollisionPair 等辅助类(如果LogisticsAnimationManager不需要)
|
||||
|
||||
**迁移步骤**:
|
||||
|
||||
1. 检查PathAnimationManager中是否有LogisticsAnimationManager缺少的功能
|
||||
2. 将必要功能迁移到LogisticsAnimationManager
|
||||
3. 更新AnimationControlViewModel只使用LogisticsAnimationManager
|
||||
4. 删除PathAnimationManager文件
|
||||
|
||||
## 三、WPF Services清理
|
||||
|
||||
### 3.1 零使用率类删除
|
||||
|
||||
**立即删除**:
|
||||
|
||||
- `DataBindingBestPractices` (src/UI/WPF/Services/DataBindingBestPractices.cs) - 0次外部引用
|
||||
- `CrossViewModelSynchronizer` (src/UI/WPF/Services/CrossViewModelSynchronizer.cs) - 仅被BestPractices使用
|
||||
|
||||
### 3.2 虚拟化集合(可选)
|
||||
|
||||
**文件**: src/UI/WPF/Collections/VirtualizedObservableCollection.cs
|
||||
|
||||
**问题**: 只被DataBindingBestPractices引用,无实际业务使用
|
||||
|
||||
**建议**: 删除(如果未来需要处理大数据集,重新实现更简单)
|
||||
|
||||
### 3.3 保留的Services
|
||||
|
||||
**保留并继续使用**:
|
||||
|
||||
- `SmartDataBindingOptimizer` - ViewModelBase依赖
|
||||
- `BindingExpressionOptimizer` - SmartDataBindingOptimizer依赖
|
||||
- `DataBindingPerformanceMonitor` - 多处使用(可考虑简化)
|
||||
|
||||
## 四、向后兼容代码清理
|
||||
|
||||
### 4.1 明确标注的旧版代码
|
||||
|
||||
**删除位置**:
|
||||
|
||||
1. **PathAnimationManager.cs**
|
||||
- Line 143: `public event EventHandler AnimationCompleted;` - 旧版事件
|
||||
- Line 904: `AnimationCompleted?.Invoke(this, EventArgs.Empty);` - 触发旧版事件
|
||||
- 注释:"旧版,保留兼容性" / "保持兼容性"
|
||||
|
||||
2. **ModelSplitterManager.cs**
|
||||
- Line 1584-1593: `GenerateFileName(string layerName, SplitConfiguration config)` 方法
|
||||
- 注释:"旧版本兼容性方法"
|
||||
- 方案:删除此重载,统一使用带Strategy参数的新版本
|
||||
|
||||
3. **LayerManagementViewModel.cs**
|
||||
- Line 1712: 类似的`GenerateFileName`旧版方法
|
||||
- 统一使用新版本实现
|
||||
|
||||
### 4.2 清理原则
|
||||
|
||||
- 遇到"旧版"、"兼容"、"fallback"等标注,直接删除
|
||||
- 不做任何"备用方案"或"容错处理"
|
||||
- 如有问题,让它快速暴露
|
||||
|
||||
## 五、辅助文件清理
|
||||
|
||||
### 5.1 临时文档
|
||||
|
||||
**检查并删除**:
|
||||
|
||||
- `path_visualization_ui.txt` - XAML代码片段,确认已集成到代码后删除
|
||||
|
||||
### 5.2 不删除的文件
|
||||
|
||||
以下管理器使用率合理,保留:
|
||||
|
||||
- PathInputMonitor (58次引用)
|
||||
- IdleEventManager (58次引用)
|
||||
- DocumentStateManager (58次引用)
|
||||
|
||||
## 执行计划
|
||||
|
||||
### 阶段一:UI状态管理清理(高风险)
|
||||
|
||||
1. [ ] 分析UIStateMachine所有引用点
|
||||
2. [ ] 迁移UIState枚举到PathPlanningModels
|
||||
3. [ ] 更新所有引用UIStateMachine的代码改用简单状态
|
||||
4. [ ] 删除UIStateMachine.cs
|
||||
5. [ ] 编译验证
|
||||
|
||||
### 阶段二:动画管理器合并(中风险)
|
||||
|
||||
1. [ ] 对比两个动画管理器的功能差异
|
||||
2. [ ] 将PathAnimationManager独有功能迁移到LogisticsAnimationManager
|
||||
3. [ ] 更新AnimationControlViewModel
|
||||
4. [ ] 删除PathAnimationManager.cs
|
||||
5. [ ] 编译验证
|
||||
|
||||
### 阶段三:WPF Services清理(低风险)
|
||||
|
||||
1. [ ] 删除DataBindingBestPractices.cs
|
||||
2. [ ] 删除CrossViewModelSynchronizer.cs
|
||||
3. [ ] 删除VirtualizedObservableCollection.cs
|
||||
4. [ ] 编译验证
|
||||
|
||||
### 阶段四:向后兼容代码清理(低风险)
|
||||
|
||||
1. [ ] 删除PathAnimationManager的AnimationCompleted事件及触发代码
|
||||
2. [ ] 删除ModelSplitterManager的旧版GenerateFileName
|
||||
3. [ ] 删除LayerManagementViewModel的旧版GenerateFileName
|
||||
4. [ ] 编译验证
|
||||
|
||||
### 阶段五:最终验证
|
||||
|
||||
1. [ ] 完整编译
|
||||
2. [ ] 运行单元测试
|
||||
3. [ ] 删除path_visualization_ui.txt
|
||||
4. [ ] 更新CHANGELOG.md
|
||||
5. [ ] Git commit
|
||||
|
||||
## 预期效果
|
||||
|
||||
**代码减少**:
|
||||
|
||||
- 删除文件:约8-10个
|
||||
- 减少代码行数:约3000-5000行
|
||||
|
||||
**架构改进**:
|
||||
|
||||
- 消除UI状态管理的重复抽象
|
||||
- 统一动画管理接口
|
||||
- 移除未使用的优化工具
|
||||
- 清除所有向后兼容负担
|
||||
|
||||
**风险评估**:
|
||||
|
||||
- 高风险:UI状态管理重构(需要仔细测试)
|
||||
- 中风险:动画管理器合并(可能影响现有功能)
|
||||
- 低风险:删除未使用的Services和兼容代码
|
||||
|
||||
## 回滚策略
|
||||
|
||||
每个阶段完成后创建Git commit,便于回滚:
|
||||
|
||||
```bash
|
||||
git commit -m "阶段X: [具体内容]"
|
||||
```
|
||||
|
||||
如遇问题:
|
||||
|
||||
```bash
|
||||
git revert HEAD # 回滚最后一次提交
|
||||
```
|
||||
@ -1,744 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NavisworksTransport.Utils;
|
||||
|
||||
namespace NavisworksTransport.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// UI状态机 - 管理整个应用的UI状态转换
|
||||
/// 提供线程安全的状态管理、状态转换验证和历史跟踪功能
|
||||
/// 集成UIStateManager进行状态变更的UI通知
|
||||
/// </summary>
|
||||
public class UIStateMachine
|
||||
{
|
||||
#region 字段和属性
|
||||
|
||||
private static UIStateMachine _instance;
|
||||
private static readonly object _instanceLock = new object();
|
||||
|
||||
private UIState _currentState = UIState.Idle;
|
||||
private readonly object _stateLock = new object();
|
||||
private readonly UIStateManager _uiStateManager;
|
||||
|
||||
// 状态历史记录
|
||||
private readonly List<StateTransitionRecord> _stateHistory = new List<StateTransitionRecord>();
|
||||
private readonly int _maxHistoryRecords = 100; // 最大历史记录数
|
||||
|
||||
// 状态转换验证规则
|
||||
private readonly Dictionary<UIState, HashSet<UIState>> _allowedTransitions;
|
||||
|
||||
// 状态变更事件
|
||||
public event EventHandler<StateChangedEventArgs> StateChanged;
|
||||
public event EventHandler<StateTransitionEventArgs> StateTransitioning;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UIStateMachine的单例实例
|
||||
/// </summary>
|
||||
public static UIStateMachine Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
lock (_instanceLock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new UIStateMachine();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前UI状态(线程安全)
|
||||
/// </summary>
|
||||
public UIState CurrentState
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
return _currentState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取状态历史记录的快照
|
||||
/// </summary>
|
||||
public StateTransitionRecord[] StateHistory
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
return _stateHistory.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前状态描述
|
||||
/// </summary>
|
||||
public string CurrentStateDescription => GetStateDescription(CurrentState);
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前状态是否为忙碌状态
|
||||
/// </summary>
|
||||
public bool IsBusy => IsStateStrictBusy(CurrentState);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
|
||||
private UIStateMachine()
|
||||
{
|
||||
try
|
||||
{
|
||||
_uiStateManager = UIStateManager.Instance;
|
||||
_allowedTransitions = InitializeStateTransitions();
|
||||
|
||||
LogManager.Info("UIStateMachine初始化完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UIStateMachine初始化失败: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化状态转换规则
|
||||
/// </summary>
|
||||
/// <returns>状态转换规则字典</returns>
|
||||
private Dictionary<UIState, HashSet<UIState>> InitializeStateTransitions()
|
||||
{
|
||||
var transitions = new Dictionary<UIState, HashSet<UIState>>();
|
||||
|
||||
// Idle状态可以转换到任何状态
|
||||
transitions[UIState.Idle] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Planning,
|
||||
UIState.Updating,
|
||||
UIState.Animating,
|
||||
UIState.Error,
|
||||
UIState.Loading,
|
||||
UIState.Exporting,
|
||||
UIState.Editing
|
||||
};
|
||||
|
||||
// Planning状态的转换
|
||||
transitions[UIState.Planning] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Updating,
|
||||
UIState.Error,
|
||||
UIState.Editing
|
||||
};
|
||||
|
||||
// Updating状态的转换
|
||||
transitions[UIState.Updating] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Planning,
|
||||
UIState.Error,
|
||||
UIState.Animating
|
||||
};
|
||||
|
||||
// Animating状态的转换
|
||||
transitions[UIState.Animating] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Updating,
|
||||
UIState.Error
|
||||
};
|
||||
|
||||
// Loading状态的转换
|
||||
transitions[UIState.Loading] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Error,
|
||||
UIState.Planning
|
||||
};
|
||||
|
||||
// Exporting状态的转换
|
||||
transitions[UIState.Exporting] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Error
|
||||
};
|
||||
|
||||
// Editing状态的转换
|
||||
transitions[UIState.Editing] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Planning,
|
||||
UIState.Updating,
|
||||
UIState.Error
|
||||
};
|
||||
|
||||
// Error状态可以转换到Idle或回到任何正常状态
|
||||
transitions[UIState.Error] = new HashSet<UIState>
|
||||
{
|
||||
UIState.Idle,
|
||||
UIState.Planning,
|
||||
UIState.Updating,
|
||||
UIState.Animating,
|
||||
UIState.Loading,
|
||||
UIState.Exporting,
|
||||
UIState.Editing
|
||||
};
|
||||
|
||||
return transitions;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 状态转换核心方法
|
||||
|
||||
/// <summary>
|
||||
/// 尝试转换状态(线程安全)
|
||||
/// </summary>
|
||||
/// <param name="newState">目标状态</param>
|
||||
/// <param name="context">转换上下文信息</param>
|
||||
/// <returns>转换是否成功</returns>
|
||||
public bool TryTransition(UIState newState, string context = null)
|
||||
{
|
||||
var currentState = CurrentState;
|
||||
|
||||
// 如果是相同状态,直接返回true
|
||||
if (currentState == newState)
|
||||
{
|
||||
LogManager.Debug($"UIStateMachine状态转换跳过: 已处于{GetStateDescription(newState)}状态");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 验证转换是否被允许
|
||||
if (!IsTransitionAllowed(currentState, newState))
|
||||
{
|
||||
LogManager.Warning($"UIStateMachine非法状态转换: {GetStateDescription(currentState)} -> {GetStateDescription(newState)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteStateTransition(currentState, newState, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制转换状态(用于错误恢复)
|
||||
/// </summary>
|
||||
/// <param name="newState">目标状态</param>
|
||||
/// <param name="context">转换上下文信息</param>
|
||||
/// <returns>转换是否成功</returns>
|
||||
public bool ForceTransition(UIState newState, string context = "强制转换")
|
||||
{
|
||||
var currentState = CurrentState;
|
||||
LogManager.Warning($"UIStateMachine强制状态转换: {GetStateDescription(currentState)} -> {GetStateDescription(newState)}");
|
||||
|
||||
return ExecuteStateTransition(currentState, newState, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行状态转换的核心逻辑
|
||||
/// </summary>
|
||||
/// <param name="fromState">源状态</param>
|
||||
/// <param name="toState">目标状态</param>
|
||||
/// <param name="context">转换上下文</param>
|
||||
/// <returns>转换是否成功</returns>
|
||||
private bool ExecuteStateTransition(UIState fromState, UIState toState, string context)
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 触发状态转换前事件
|
||||
var transitionArgs = new StateTransitionEventArgs(fromState, toState, context);
|
||||
OnStateTransitioning(transitionArgs);
|
||||
|
||||
// 如果事件处理器取消了转换
|
||||
if (transitionArgs.Cancel)
|
||||
{
|
||||
LogManager.Info($"UIStateMachine状态转换被取消: {GetStateDescription(fromState)} -> {GetStateDescription(toState)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
_currentState = toState;
|
||||
|
||||
// 记录状态历史
|
||||
RecordStateTransition(fromState, toState, context);
|
||||
|
||||
// 触发状态变更事件
|
||||
var changedArgs = new StateChangedEventArgs(fromState, toState, context);
|
||||
OnStateChanged(changedArgs);
|
||||
|
||||
LogManager.Info($"UIStateMachine状态转换成功: {GetStateDescription(fromState)} -> {GetStateDescription(toState)}");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UIStateMachine状态转换失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证状态转换是否被允许
|
||||
/// </summary>
|
||||
/// <param name="fromState">源状态</param>
|
||||
/// <param name="toState">目标状态</param>
|
||||
/// <returns>转换是否被允许</returns>
|
||||
private bool IsTransitionAllowed(UIState fromState, UIState toState)
|
||||
{
|
||||
if (_allowedTransitions.ContainsKey(fromState))
|
||||
{
|
||||
return _allowedTransitions[fromState].Contains(toState);
|
||||
}
|
||||
|
||||
// 如果没有定义转换规则,默认允许转换到Error和Idle状态
|
||||
return toState == UIState.Error || toState == UIState.Idle;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 状态历史和查询方法
|
||||
|
||||
/// <summary>
|
||||
/// 记录状态转换历史
|
||||
/// </summary>
|
||||
/// <param name="fromState">源状态</param>
|
||||
/// <param name="toState">目标状态</param>
|
||||
/// <param name="context">转换上下文</param>
|
||||
private void RecordStateTransition(UIState fromState, UIState toState, string context)
|
||||
{
|
||||
var record = new StateTransitionRecord
|
||||
{
|
||||
FromState = fromState,
|
||||
ToState = toState,
|
||||
Context = context ?? string.Empty,
|
||||
Timestamp = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_stateHistory.Add(record);
|
||||
|
||||
// 清理过多的历史记录
|
||||
if (_stateHistory.Count > _maxHistoryRecords)
|
||||
{
|
||||
_stateHistory.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定时间范围内的状态历史
|
||||
/// </summary>
|
||||
/// <param name="since">起始时间</param>
|
||||
/// <returns>状态转换记录数组</returns>
|
||||
public StateTransitionRecord[] GetStateHistorySince(DateTime since)
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
return _stateHistory.Where(record => record.Timestamp >= since).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最近的N条状态历史记录
|
||||
/// </summary>
|
||||
/// <param name="count">记录数量</param>
|
||||
/// <returns>状态转换记录数组</returns>
|
||||
public StateTransitionRecord[] GetRecentStateHistory(int count = 10)
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
var takeCount = Math.Min(count, _stateHistory.Count);
|
||||
return _stateHistory.Skip(_stateHistory.Count - takeCount).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空状态历史记录
|
||||
/// </summary>
|
||||
public void ClearStateHistory()
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
_stateHistory.Clear();
|
||||
LogManager.Info("UIStateMachine状态历史已清空");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 状态回滚功能
|
||||
|
||||
/// <summary>
|
||||
/// 回滚到上一个状态
|
||||
/// </summary>
|
||||
/// <returns>回滚是否成功</returns>
|
||||
public bool RollbackToPreviousState()
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
if (_stateHistory.Count >= 2)
|
||||
{
|
||||
// 获取倒数第二条记录的FromState
|
||||
var previousRecord = _stateHistory[_stateHistory.Count - 2];
|
||||
var targetState = previousRecord.ToState;
|
||||
|
||||
return TryTransition(targetState, "状态回滚");
|
||||
}
|
||||
|
||||
LogManager.Warning("UIStateMachine无法回滚: 没有足够的状态历史");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回滚到指定状态
|
||||
/// </summary>
|
||||
/// <param name="targetState">目标状态</param>
|
||||
/// <returns>回滚是否成功</returns>
|
||||
public bool RollbackToState(UIState targetState)
|
||||
{
|
||||
return TryTransition(targetState, $"回滚到{GetStateDescription(targetState)}状态");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 实用工具方法
|
||||
|
||||
/// <summary>
|
||||
/// 获取状态的中文描述
|
||||
/// </summary>
|
||||
/// <param name="state">UI状态</param>
|
||||
/// <returns>状态描述</returns>
|
||||
public static string GetStateDescription(UIState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case UIState.Idle:
|
||||
return "空闲";
|
||||
case UIState.Planning:
|
||||
return "路径规划中";
|
||||
case UIState.Updating:
|
||||
return "更新中";
|
||||
case UIState.Animating:
|
||||
return "动画播放中";
|
||||
case UIState.Loading:
|
||||
return "加载中";
|
||||
case UIState.Exporting:
|
||||
return "导出中";
|
||||
case UIState.Editing:
|
||||
return "编辑中";
|
||||
case UIState.Error:
|
||||
return "错误状态";
|
||||
default:
|
||||
return "未知状态";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取状态优先级(用于状态冲突解决)
|
||||
/// </summary>
|
||||
/// <param name="state">UI状态</param>
|
||||
/// <returns>状态优先级(数值越大优先级越高)</returns>
|
||||
public static int GetStatePriority(UIState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case UIState.Error:
|
||||
return 100; // 错误状态最高优先级
|
||||
case UIState.Exporting:
|
||||
return 80; // 导出操作高优先级
|
||||
case UIState.Loading:
|
||||
return 70; // 加载操作高优先级
|
||||
case UIState.Animating:
|
||||
return 60; // 动画播放中等优先级
|
||||
case UIState.Planning:
|
||||
return 50; // 路径规划中等优先级
|
||||
case UIState.Updating:
|
||||
return 40; // 更新操作中等优先级
|
||||
case UIState.Editing:
|
||||
return 30; // 编辑操作较低优先级
|
||||
case UIState.Idle:
|
||||
return 10; // 空闲状态最低优先级
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断状态是否为忙碌状态
|
||||
/// </summary>
|
||||
/// <param name="state">UI状态</param>
|
||||
/// <returns>是否为忙碌状态</returns>
|
||||
public static bool IsStateStrictBusy(UIState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case UIState.Planning:
|
||||
case UIState.Updating:
|
||||
case UIState.Animating:
|
||||
case UIState.Loading:
|
||||
case UIState.Exporting:
|
||||
return true;
|
||||
case UIState.Idle:
|
||||
case UIState.Editing:
|
||||
case UIState.Error:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待状态变为指定状态(异步)
|
||||
/// </summary>
|
||||
/// <param name="targetState">目标状态</param>
|
||||
/// <param name="timeout">超时时间(毫秒)</param>
|
||||
/// <returns>是否在超时前达到目标状态</returns>
|
||||
public async Task<bool> WaitForStateAsync(UIState targetState, int timeout = 30000)
|
||||
{
|
||||
var startTime = DateTime.UtcNow;
|
||||
var timeoutSpan = TimeSpan.FromMilliseconds(timeout);
|
||||
|
||||
while (CurrentState != targetState && DateTime.UtcNow - startTime < timeoutSpan)
|
||||
{
|
||||
await Task.Delay(100); // 每100ms检查一次
|
||||
}
|
||||
|
||||
var success = CurrentState == targetState;
|
||||
if (!success)
|
||||
{
|
||||
LogManager.Warning($"UIStateMachine等待状态超时: 目标状态={GetStateDescription(targetState)}, 当前状态={GetStateDescription(CurrentState)}");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件处理
|
||||
|
||||
/// <summary>
|
||||
/// 触发状态变更事件
|
||||
/// </summary>
|
||||
/// <param name="args">状态变更事件参数</param>
|
||||
protected virtual void OnStateChanged(StateChangedEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用UIStateManager确保在UI线程中触发事件
|
||||
if (_uiStateManager.IsUIThread)
|
||||
{
|
||||
StateChanged?.Invoke(this, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
_uiStateManager.QueueUIUpdate(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
StateChanged?.Invoke(this, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UIStateMachine状态变更事件处理失败: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UIStateMachine OnStateChanged异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发状态转换前事件
|
||||
/// </summary>
|
||||
/// <param name="args">状态转换事件参数</param>
|
||||
protected virtual void OnStateTransitioning(StateTransitionEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
StateTransitioning?.Invoke(this, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Error($"UIStateMachine OnStateTransitioning异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 释放资源
|
||||
|
||||
/// <summary>
|
||||
/// 释放状态机资源
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
ClearStateHistory();
|
||||
StateChanged = null;
|
||||
StateTransitioning = null;
|
||||
|
||||
LogManager.Info("UIStateMachine已释放");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region 枚举和事件参数类
|
||||
|
||||
/// <summary>
|
||||
/// UI状态枚举
|
||||
/// </summary>
|
||||
public enum UIState
|
||||
{
|
||||
/// <summary>
|
||||
/// 空闲状态 - 无任何操作进行
|
||||
/// </summary>
|
||||
Idle,
|
||||
|
||||
/// <summary>
|
||||
/// 路径规划状态 - 正在进行路径规划计算
|
||||
/// </summary>
|
||||
Planning,
|
||||
|
||||
/// <summary>
|
||||
/// 更新状态 - 正在更新UI或数据
|
||||
/// </summary>
|
||||
Updating,
|
||||
|
||||
/// <summary>
|
||||
/// 动画播放状态 - 正在播放路径动画
|
||||
/// </summary>
|
||||
Animating,
|
||||
|
||||
/// <summary>
|
||||
/// 加载状态 - 正在加载模型或数据
|
||||
/// </summary>
|
||||
Loading,
|
||||
|
||||
/// <summary>
|
||||
/// 导出状态 - 正在导出数据或模型
|
||||
/// </summary>
|
||||
Exporting,
|
||||
|
||||
/// <summary>
|
||||
/// 编辑状态 - 正在编辑路径或参数
|
||||
/// </summary>
|
||||
Editing,
|
||||
|
||||
/// <summary>
|
||||
/// 错误状态 - 发生错误需要处理
|
||||
/// </summary>
|
||||
Error
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态转换记录
|
||||
/// </summary>
|
||||
public class StateTransitionRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// 源状态
|
||||
/// </summary>
|
||||
public UIState FromState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标状态
|
||||
/// </summary>
|
||||
public UIState ToState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换上下文信息
|
||||
/// </summary>
|
||||
public string Context { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换时间戳
|
||||
/// </summary>
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态变更事件参数
|
||||
/// </summary>
|
||||
public class StateChangedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 前一个状态
|
||||
/// </summary>
|
||||
public UIState PreviousState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public UIState CurrentState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换上下文信息
|
||||
/// </summary>
|
||||
public string Context { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换时间戳
|
||||
/// </summary>
|
||||
public DateTime Timestamp { get; }
|
||||
|
||||
public StateChangedEventArgs(UIState previousState, UIState currentState, string context)
|
||||
{
|
||||
PreviousState = previousState;
|
||||
CurrentState = currentState;
|
||||
Context = context ?? string.Empty;
|
||||
Timestamp = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态转换前事件参数
|
||||
/// </summary>
|
||||
public class StateTransitionEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 源状态
|
||||
/// </summary>
|
||||
public UIState FromState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标状态
|
||||
/// </summary>
|
||||
public UIState ToState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换上下文信息
|
||||
/// </summary>
|
||||
public string Context { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否取消转换
|
||||
/// </summary>
|
||||
public bool Cancel { get; set; } = false;
|
||||
|
||||
public StateTransitionEventArgs(UIState fromState, UIState toState, string context)
|
||||
{
|
||||
FromState = fromState;
|
||||
ToState = toState;
|
||||
Context = context ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user