Files
MaliangAINovalWriter/AINoval/lib/blocs/setting_generation/setting_generation_state.dart
2025-09-10 00:07:52 +08:00

537 lines
16 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Object?> get props => [];
}
/// 初始状态
class SettingGenerationInitial extends SettingGenerationState {
const SettingGenerationInitial();
}
/// 加载中
class SettingGenerationLoading extends SettingGenerationState {
final String? message;
const SettingGenerationLoading({this.message});
@override
List<Object?> get props => [message];
}
/// 策略已加载
class StrategiesLoaded extends SettingGenerationState {
final List<StrategyTemplateInfo> strategies;
const StrategiesLoaded(this.strategies);
@override
List<Object?> get props => [strategies];
}
/// 待机状态(准备开始生成)
class SettingGenerationReady extends SettingGenerationState {
final List<StrategyTemplateInfo> strategies;
final List<SettingGenerationSession> 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<Object?> get props => [
strategies,
sessions,
activeSessionId,
adjustmentPrompt,
viewMode,
];
SettingGenerationReady copyWith({
List<StrategyTemplateInfo>? strategies,
List<SettingGenerationSession>? 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<StrategyTemplateInfo> strategies;
final List<SettingGenerationSession> sessions;
final String activeSessionId;
final SettingGenerationSession activeSession;
final String? selectedNodeId;
final String viewMode;
final String adjustmentPrompt;
final Map<String, SettingNode> pendingChanges;
final Set<String> highlightedNodeIds;
final Map<String, List<SettingNode>> editHistory;
final List<event_model.SettingGenerationEvent> events;
final bool isGenerating;
final String? currentOperation;
// 新增:写作编排流的预览缓存(仅前端展示,不落库)
final List<ComposeChapterPreview> composePreview;
// 新增的渲染状态管理字段
final Map<String, NodeRenderInfo> nodeRenderStates;
final List<String> renderQueue;
final Set<String> renderedNodeIds;
final List<event_model.NodeCreatedEvent> 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<Object?> get props => [
strategies,
sessions,
activeSessionId,
activeSession,
selectedNodeId,
viewMode,
adjustmentPrompt,
pendingChanges,
highlightedNodeIds,
editHistory,
isGenerating,
currentOperation,
composePreview,
events,
nodeRenderStates,
renderQueue,
renderedNodeIds,
stickyWarning,
];
SettingGenerationInProgress copyWith({
List<StrategyTemplateInfo>? strategies,
List<SettingGenerationSession>? sessions,
String? activeSessionId,
SettingGenerationSession? activeSession,
String? selectedNodeId,
String? viewMode,
String? adjustmentPrompt,
Map<String, SettingNode>? pendingChanges,
Set<String>? highlightedNodeIds,
Map<String, List<SettingNode>>? editHistory,
bool? isGenerating,
String? currentOperation,
List<ComposeChapterPreview>? composePreview,
List<event_model.SettingGenerationEvent>? events,
Map<String, NodeRenderInfo>? nodeRenderStates,
List<String>? renderQueue,
Set<String>? renderedNodeIds,
List<event_model.NodeCreatedEvent>? 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<String> get renderableNodeIds {
return SettingNodeUtils.getRenderableNodeIds(
activeSession.rootNodes,
renderQueue,
renderedNodeIds,
);
}
}
/// 生成完成
class SettingGenerationCompleted extends SettingGenerationState {
final List<StrategyTemplateInfo> strategies;
final List<SettingGenerationSession> sessions;
final String activeSessionId;
final SettingGenerationSession activeSession;
final String? selectedNodeId;
final String viewMode;
final String adjustmentPrompt;
final Map<String, SettingNode> pendingChanges;
final Set<String> highlightedNodeIds;
final Map<String, List<SettingNode>> editHistory;
final List<event_model.SettingGenerationEvent> events;
final String message;
// 新增的渲染状态管理字段
final Map<String, NodeRenderInfo> nodeRenderStates;
final Set<String> 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<Object?> get props => [
strategies,
sessions,
activeSessionId,
activeSession,
selectedNodeId,
viewMode,
adjustmentPrompt,
pendingChanges,
highlightedNodeIds,
editHistory,
events,
message,
nodeRenderStates,
renderedNodeIds,
stickyWarning,
];
SettingGenerationCompleted copyWith({
List<StrategyTemplateInfo>? strategies,
List<SettingGenerationSession>? sessions,
String? activeSessionId,
SettingGenerationSession? activeSession,
String? selectedNodeId,
String? viewMode,
String? adjustmentPrompt,
Map<String, SettingNode>? pendingChanges,
Set<String>? highlightedNodeIds,
Map<String, List<SettingNode>>? editHistory,
List<event_model.SettingGenerationEvent>? events,
String? message,
Map<String, NodeRenderInfo>? nodeRenderStates,
Set<String>? 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<StrategyTemplateInfo> strategies;
final List<SettingGenerationSession> sessions;
final String activeSessionId;
final SettingGenerationSession activeSession;
final String? selectedNodeId;
final String viewMode;
final String adjustmentPrompt;
final Map<String, SettingNode> pendingChanges;
final Set<String> highlightedNodeIds;
final Map<String, List<SettingNode>> editHistory;
final List<event_model.SettingGenerationEvent> events;
final String message;
// 节点修改特有字段
final String updatingNodeId; // 正在修改的节点ID
final String modificationPrompt; // 修改提示词
final String scope; // 修改范围
final bool isUpdating; // 是否正在更新中
// 渲染状态管理字段
final Map<String, NodeRenderInfo> nodeRenderStates;
final Set<String> 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<Object?> get props => [
strategies,
sessions,
activeSessionId,
activeSession,
selectedNodeId,
viewMode,
adjustmentPrompt,
pendingChanges,
highlightedNodeIds,
editHistory,
events,
message,
updatingNodeId,
modificationPrompt,
scope,
isUpdating,
nodeRenderStates,
renderedNodeIds,
];
SettingGenerationNodeUpdating copyWith({
List<StrategyTemplateInfo>? strategies,
List<SettingGenerationSession>? sessions,
String? activeSessionId,
SettingGenerationSession? activeSession,
String? selectedNodeId,
String? viewMode,
String? adjustmentPrompt,
Map<String, SettingNode>? pendingChanges,
Set<String>? highlightedNodeIds,
Map<String, List<SettingNode>>? editHistory,
List<event_model.SettingGenerationEvent>? events,
String? message,
String? updatingNodeId,
String? modificationPrompt,
String? scope,
bool? isUpdating,
Map<String, NodeRenderInfo>? nodeRenderStates,
Set<String>? 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<String> savedSettingIds;
final String message;
// 新增保留会话列表和当前活跃会话ID避免UI刷新
final List<SettingGenerationSession> sessions;
final String? activeSessionId;
const SettingGenerationSaved({
required this.savedSettingIds,
this.message = '设定已成功保存',
this.sessions = const [],
this.activeSessionId,
});
@override
List<Object?> 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<SettingGenerationSession> sessions;
final String? activeSessionId;
const SettingGenerationError({
required this.message,
this.error,
this.stackTrace,
this.isRecoverable = true,
this.sessions = const [],
this.activeSessionId,
});
@override
List<Object?> get props => [
message,
error,
stackTrace,
isRecoverable,
sessions,
activeSessionId,
];
SettingGenerationError copyWith({
String? message,
dynamic error,
StackTrace? stackTrace,
bool? isRecoverable,
List<SettingGenerationSession>? 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,
);
}
}