import 'package:equatable/equatable.dart'; import '../../models/setting_generation_session.dart'; import '../../models/setting_node.dart'; import '../../models/setting_generation_event.dart' as event_model; import '../../models/compose_preview.dart'; import '../../models/strategy_template_info.dart'; import '../../utils/setting_node_utils.dart'; // 导入工具类 abstract class SettingGenerationState extends Equatable { const SettingGenerationState(); @override List get props => []; } /// 初始状态 class SettingGenerationInitial extends SettingGenerationState { const SettingGenerationInitial(); } /// 加载中 class SettingGenerationLoading extends SettingGenerationState { final String? message; const SettingGenerationLoading({this.message}); @override List get props => [message]; } /// 策略已加载 class StrategiesLoaded extends SettingGenerationState { final List strategies; const StrategiesLoaded(this.strategies); @override List get props => [strategies]; } /// 待机状态(准备开始生成) class SettingGenerationReady extends SettingGenerationState { final List strategies; final List sessions; final String? activeSessionId; final String adjustmentPrompt; final String viewMode; const SettingGenerationReady({ required this.strategies, this.sessions = const [], this.activeSessionId, this.adjustmentPrompt = '', this.viewMode = 'compact', }); @override List get props => [ strategies, sessions, activeSessionId, adjustmentPrompt, viewMode, ]; SettingGenerationReady copyWith({ List? strategies, List? sessions, String? activeSessionId, String? adjustmentPrompt, String? viewMode, }) { return SettingGenerationReady( strategies: strategies ?? this.strategies, sessions: sessions ?? this.sessions, activeSessionId: activeSessionId ?? this.activeSessionId, adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt, viewMode: viewMode ?? this.viewMode, ); } } /// 节点渲染状态枚举 enum NodeRenderState { pending, // 待渲染(在队列中) rendering, // 正在渲染(动画中) rendered, // 已渲染完成 } /// 节点渲染信息 class NodeRenderInfo { final String nodeId; final NodeRenderState state; final DateTime? renderStartTime; final Duration? renderDuration; const NodeRenderInfo({ required this.nodeId, required this.state, this.renderStartTime, this.renderDuration, }); NodeRenderInfo copyWith({ NodeRenderState? state, DateTime? renderStartTime, Duration? renderDuration, }) { return NodeRenderInfo( nodeId: nodeId, state: state ?? this.state, renderStartTime: renderStartTime ?? this.renderStartTime, renderDuration: renderDuration ?? this.renderDuration, ); } } /// 生成中 class SettingGenerationInProgress extends SettingGenerationState { final List strategies; final List sessions; final String activeSessionId; final SettingGenerationSession activeSession; final String? selectedNodeId; final String viewMode; final String adjustmentPrompt; final Map pendingChanges; final Set highlightedNodeIds; final Map> editHistory; final List events; final bool isGenerating; final String? currentOperation; // 新增:写作编排流的预览缓存(仅前端展示,不落库) final List composePreview; // 新增的渲染状态管理字段 final Map nodeRenderStates; final List renderQueue; final Set renderedNodeIds; final List pendingNodes; // 粘性警告(例如余额不足提醒),不会被后续普通事件覆盖 final String? stickyWarning; const SettingGenerationInProgress({ required this.strategies, required this.sessions, required this.activeSessionId, required this.activeSession, this.selectedNodeId, this.viewMode = 'compact', this.adjustmentPrompt = '', this.pendingChanges = const {}, this.highlightedNodeIds = const {}, this.editHistory = const {}, this.isGenerating = false, this.currentOperation, this.composePreview = const [], this.events = const [], this.nodeRenderStates = const {}, this.renderQueue = const [], this.renderedNodeIds = const {}, this.pendingNodes = const [], this.stickyWarning, }); @override List get props => [ strategies, sessions, activeSessionId, activeSession, selectedNodeId, viewMode, adjustmentPrompt, pendingChanges, highlightedNodeIds, editHistory, isGenerating, currentOperation, composePreview, events, nodeRenderStates, renderQueue, renderedNodeIds, stickyWarning, ]; SettingGenerationInProgress copyWith({ List? strategies, List? sessions, String? activeSessionId, SettingGenerationSession? activeSession, String? selectedNodeId, String? viewMode, String? adjustmentPrompt, Map? pendingChanges, Set? highlightedNodeIds, Map>? editHistory, bool? isGenerating, String? currentOperation, List? composePreview, List? events, Map? nodeRenderStates, List? renderQueue, Set? renderedNodeIds, List? pendingNodes, String? stickyWarning, }) { return SettingGenerationInProgress( strategies: strategies ?? this.strategies, sessions: sessions ?? this.sessions, activeSessionId: activeSessionId ?? this.activeSessionId, activeSession: activeSession ?? this.activeSession, selectedNodeId: selectedNodeId ?? this.selectedNodeId, viewMode: viewMode ?? this.viewMode, adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt, pendingChanges: pendingChanges ?? this.pendingChanges, highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds, editHistory: editHistory ?? this.editHistory, isGenerating: isGenerating ?? this.isGenerating, currentOperation: currentOperation ?? this.currentOperation, composePreview: composePreview ?? this.composePreview, events: events ?? this.events, nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates, renderQueue: renderQueue ?? this.renderQueue, renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds, pendingNodes: pendingNodes ?? this.pendingNodes, stickyWarning: stickyWarning ?? this.stickyWarning, ); } /// 获取当前选中的节点 SettingNode? get selectedNode { if (selectedNodeId == null) return null; return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!); } /// 获取可以渲染的节点列表(父节点为空或已渲染) List get renderableNodeIds { return SettingNodeUtils.getRenderableNodeIds( activeSession.rootNodes, renderQueue, renderedNodeIds, ); } } /// 生成完成 class SettingGenerationCompleted extends SettingGenerationState { final List strategies; final List sessions; final String activeSessionId; final SettingGenerationSession activeSession; final String? selectedNodeId; final String viewMode; final String adjustmentPrompt; final Map pendingChanges; final Set highlightedNodeIds; final Map> editHistory; final List events; final String message; // 新增的渲染状态管理字段 final Map nodeRenderStates; final Set renderedNodeIds; final String? stickyWarning; const SettingGenerationCompleted({ required this.strategies, required this.sessions, required this.activeSessionId, required this.activeSession, this.selectedNodeId, this.viewMode = 'compact', this.adjustmentPrompt = '', this.pendingChanges = const {}, this.highlightedNodeIds = const {}, this.editHistory = const {}, this.events = const [], required this.message, this.nodeRenderStates = const {}, this.renderedNodeIds = const {}, this.stickyWarning, }); @override List get props => [ strategies, sessions, activeSessionId, activeSession, selectedNodeId, viewMode, adjustmentPrompt, pendingChanges, highlightedNodeIds, editHistory, events, message, nodeRenderStates, renderedNodeIds, stickyWarning, ]; SettingGenerationCompleted copyWith({ List? strategies, List? sessions, String? activeSessionId, SettingGenerationSession? activeSession, String? selectedNodeId, String? viewMode, String? adjustmentPrompt, Map? pendingChanges, Set? highlightedNodeIds, Map>? editHistory, List? events, String? message, Map? nodeRenderStates, Set? renderedNodeIds, String? stickyWarning, }) { return SettingGenerationCompleted( strategies: strategies ?? this.strategies, sessions: sessions ?? this.sessions, activeSessionId: activeSessionId ?? this.activeSessionId, activeSession: activeSession ?? this.activeSession, selectedNodeId: selectedNodeId ?? this.selectedNodeId, viewMode: viewMode ?? this.viewMode, adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt, pendingChanges: pendingChanges ?? this.pendingChanges, highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds, editHistory: editHistory ?? this.editHistory, events: events ?? this.events, message: message ?? this.message, nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates, renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds, stickyWarning: stickyWarning ?? this.stickyWarning, ); } /// 获取当前选中的节点 SettingNode? get selectedNode { if (selectedNodeId == null) return null; return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!); } } /// 节点修改中状态(专门用于节点修改,避免整个设定树重新渲染) class SettingGenerationNodeUpdating extends SettingGenerationState { final List strategies; final List sessions; final String activeSessionId; final SettingGenerationSession activeSession; final String? selectedNodeId; final String viewMode; final String adjustmentPrompt; final Map pendingChanges; final Set highlightedNodeIds; final Map> editHistory; final List events; final String message; // 节点修改特有字段 final String updatingNodeId; // 正在修改的节点ID final String modificationPrompt; // 修改提示词 final String scope; // 修改范围 final bool isUpdating; // 是否正在更新中 // 渲染状态管理字段 final Map nodeRenderStates; final Set renderedNodeIds; const SettingGenerationNodeUpdating({ required this.strategies, required this.sessions, required this.activeSessionId, required this.activeSession, this.selectedNodeId, this.viewMode = 'compact', this.adjustmentPrompt = '', this.pendingChanges = const {}, this.highlightedNodeIds = const {}, this.editHistory = const {}, this.events = const [], this.message = '', required this.updatingNodeId, this.modificationPrompt = '', this.scope = 'self', this.isUpdating = false, this.nodeRenderStates = const {}, this.renderedNodeIds = const {}, }); @override List get props => [ strategies, sessions, activeSessionId, activeSession, selectedNodeId, viewMode, adjustmentPrompt, pendingChanges, highlightedNodeIds, editHistory, events, message, updatingNodeId, modificationPrompt, scope, isUpdating, nodeRenderStates, renderedNodeIds, ]; SettingGenerationNodeUpdating copyWith({ List? strategies, List? sessions, String? activeSessionId, SettingGenerationSession? activeSession, String? selectedNodeId, String? viewMode, String? adjustmentPrompt, Map? pendingChanges, Set? highlightedNodeIds, Map>? editHistory, List? events, String? message, String? updatingNodeId, String? modificationPrompt, String? scope, bool? isUpdating, Map? nodeRenderStates, Set? renderedNodeIds, }) { return SettingGenerationNodeUpdating( strategies: strategies ?? this.strategies, sessions: sessions ?? this.sessions, activeSessionId: activeSessionId ?? this.activeSessionId, activeSession: activeSession ?? this.activeSession, selectedNodeId: selectedNodeId ?? this.selectedNodeId, viewMode: viewMode ?? this.viewMode, adjustmentPrompt: adjustmentPrompt ?? this.adjustmentPrompt, pendingChanges: pendingChanges ?? this.pendingChanges, highlightedNodeIds: highlightedNodeIds ?? this.highlightedNodeIds, editHistory: editHistory ?? this.editHistory, events: events ?? this.events, message: message ?? this.message, updatingNodeId: updatingNodeId ?? this.updatingNodeId, modificationPrompt: modificationPrompt ?? this.modificationPrompt, scope: scope ?? this.scope, isUpdating: isUpdating ?? this.isUpdating, nodeRenderStates: nodeRenderStates ?? this.nodeRenderStates, renderedNodeIds: renderedNodeIds ?? this.renderedNodeIds, ); } /// 获取当前选中的节点 SettingNode? get selectedNode { if (selectedNodeId == null) return null; return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, selectedNodeId!); } /// 获取正在修改的节点 SettingNode? get updatingNode { return SettingNodeUtils.findNodeInTree(activeSession.rootNodes, updatingNodeId); } } /// 保存成功 class SettingGenerationSaved extends SettingGenerationState { final List savedSettingIds; final String message; // 新增:保留会话列表和当前活跃会话ID,避免UI刷新 final List sessions; final String? activeSessionId; const SettingGenerationSaved({ required this.savedSettingIds, this.message = '设定已成功保存', this.sessions = const [], this.activeSessionId, }); @override List get props => [savedSettingIds, message, sessions, activeSessionId]; } /// 错误状态 class SettingGenerationError extends SettingGenerationState { final String message; final dynamic error; final StackTrace? stackTrace; final bool isRecoverable; // 新增:保留会话列表和当前活跃会话 ID,避免 UI 在错误时丢失历史记录 final List sessions; final String? activeSessionId; const SettingGenerationError({ required this.message, this.error, this.stackTrace, this.isRecoverable = true, this.sessions = const [], this.activeSessionId, }); @override List get props => [ message, error, stackTrace, isRecoverable, sessions, activeSessionId, ]; SettingGenerationError copyWith({ String? message, dynamic error, StackTrace? stackTrace, bool? isRecoverable, List? sessions, String? activeSessionId, }) { return SettingGenerationError( message: message ?? this.message, error: error ?? this.error, stackTrace: stackTrace ?? this.stackTrace, isRecoverable: isRecoverable ?? this.isRecoverable, sessions: sessions ?? this.sessions, activeSessionId: activeSessionId ?? this.activeSessionId, ); } }