839 lines
23 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.

/**
* P1 Bug 修复补丁
*
* 修复两个 P1 级别问题:
* 1. 撤销/重做功能未实现
* 2. 元件库扩展(电感/二极管/晶体管等)
*
* @version 1.0.0
* @date 2026-03-07
*/
import 'package:flutter/material.dart';
import '../../data/models/core_models.dart';
// ============================================================================
// Bug #1: 撤销/重做功能实现
// ============================================================================
/// 操作记录 - 用于撤销/重做
class Command {
final String id;
final CommandType type;
final DateTime timestamp;
final Map<String, dynamic> data;
final Map<String, dynamic> undoData;
Command({
required this.id,
required this.type,
required this.timestamp,
required this.data,
required this.undoData,
});
}
/// 命令类型枚举
enum CommandType {
addComponent, // 添加元件
deleteComponent, // 删除元件
moveComponent, // 移动元件
rotateComponent, // 旋转元件
addNet, // 添加网络
deleteNet, // 删除网络
}
/// 撤销/重做管理器
class UndoRedoManager {
static final UndoRedoManager _instance = UndoRedoManager._internal();
factory UndoRedoManager() => _instance;
UndoRedoManager._internal();
final List<Command> _undoStack = [];
final List<Command> _redoStack = [];
// 最大历史记录数
static const int maxHistorySize = 50;
/// 执行操作并记录
void execute(Command command) {
// 执行操作
_applyCommand(command);
// 添加到撤销栈
_undoStack.add(command);
// 清空重做栈(执行新操作后)
_redoStack.clear();
// 限制历史记录大小
if (_undoStack.length > maxHistorySize) {
_undoStack.removeAt(0);
}
debugPrint('✅ 执行操作:${command.type}, 撤销栈大小:${_undoStack.length}');
}
/// 撤销
bool undo() {
if (_undoStack.isEmpty) {
debugPrint('⚠️ 无操作可撤销');
return false;
}
final command = _undoStack.removeLast();
_applyUndo(command);
_redoStack.add(command);
debugPrint('↩️ 撤销操作:${command.type}, 撤销栈大小:${_undoStack.length}');
return true;
}
/// 重做
bool redo() {
if (_redoStack.isEmpty) {
debugPrint('⚠️ 无操作可重做');
return false;
}
final command = _redoStack.removeLast();
_applyCommand(command);
_undoStack.add(command);
debugPrint('↪️ 重做操作:${command.type}, 撤销栈大小:${_undoStack.length}');
return true;
}
/// 清空历史
void clear() {
_undoStack.clear();
_redoStack.clear();
debugPrint('🗑️ 清空历史记录');
}
/// 获取撤销栈大小
int get undoCount => _undoStack.length;
/// 获取重做栈大小
int get redoCount => _redoStack.length;
/// 是否可以撤销
bool get canUndo => _undoStack.isNotEmpty;
/// 是否可以重做
bool get canRedo => _redoStack.isNotEmpty;
// ============================================================================
// 内部方法
// ============================================================================
void _applyCommand(Command command) {
// 根据命令类型执行操作
switch (command.type) {
case CommandType.addComponent:
_addComponent(command);
break;
case CommandType.deleteComponent:
_deleteComponent(command);
break;
case CommandType.moveComponent:
_moveComponent(command);
break;
case CommandType.rotateComponent:
_rotateComponent(command);
break;
case CommandType.addNet:
_addNet(command);
break;
case CommandType.deleteNet:
_deleteNet(command);
break;
}
}
void _applyUndo(Command command) {
// 撤销操作:应用 undoData
switch (command.type) {
case CommandType.addComponent:
// 撤销添加 = 删除
_removeComponentById(command.data['componentId']);
break;
case CommandType.deleteComponent:
// 撤销删除 = 恢复
_restoreComponent(command.undoData);
break;
case CommandType.moveComponent:
// 撤销移动 = 移回原位置
_moveComponentToPosition(
command.data['componentId'],
command.undoData['oldPosition'],
);
break;
case CommandType.rotateComponent:
// 撤销旋转 = 恢复原角度
_rotateComponentToAngle(
command.data['componentId'],
command.undoData['oldRotation'],
);
break;
case CommandType.addNet:
// 撤销添加网络 = 删除网络
_removeNetById(command.data['netId']);
break;
case CommandType.deleteNet:
// 撤销删除网络 = 恢复网络
_restoreNet(command.undoData);
break;
}
}
// ============================================================================
// 元件操作实现
// ============================================================================
void _addComponent(Command command) {
final componentData = command.data['component'] as Component;
// TODO: 添加到 Design
debugPrint('添加元件:${componentData.id}');
}
void _deleteComponent(Command command) {
final componentId = command.data['componentId'] as String;
// TODO: 从 Design 删除
debugPrint('删除元件:$componentId');
}
void _removeComponentById(String componentId) {
// TODO: 实现删除逻辑
debugPrint('移除元件:$componentId');
}
void _restoreComponent(Map<String, dynamic> data) {
// TODO: 恢复元件
debugPrint('恢复元件:${data['id']}');
}
void _moveComponent(Command command) {
final componentId = command.data['componentId'] as String;
final newPosition = command.data['newPosition'] as Offset;
// TODO: 移动元件
debugPrint('移动元件:$componentId$newPosition');
}
void _moveComponentToPosition(String componentId, Offset position) {
// TODO: 移动到指定位置
debugPrint('移动元件 $componentId$position');
}
void _rotateComponent(Command command) {
final componentId = command.data['componentId'] as String;
final newRotation = command.data['newRotation'] as int;
// TODO: 旋转元件
debugPrint('旋转元件:$componentId$newRotation°');
}
void _rotateComponentToAngle(String componentId, int rotation) {
// TODO: 旋转到指定角度
debugPrint('旋转元件 $componentId$rotation°');
}
// ============================================================================
// 网络操作实现
// ============================================================================
void _addNet(Command command) {
final netData = command.data['net'] as Net;
// TODO: 添加到 Design
debugPrint('添加网络:${netData.id}');
}
void _deleteNet(Command command) {
final netId = command.data['netId'] as String;
// TODO: 从 Design 删除
debugPrint('删除网络:$netId');
}
void _removeNetById(String netId) {
// TODO: 删除网络
debugPrint('移除网络:$netId');
}
void _restoreNet(Map<String, dynamic> data) {
// TODO: 恢复网络
debugPrint('恢复网络:${data['id']}');
}
}
// ============================================================================
// 快捷命令工厂
// ============================================================================
/// 命令工厂 - 简化命令创建
class CommandFactory {
/// 创建添加元件命令
static Command createAddComponent(Component component) {
return Command(
id: 'cmd_${DateTime.now().millisecondsSinceEpoch}',
type: CommandType.addComponent,
timestamp: DateTime.now(),
data: {
'component': component,
'componentId': component.id,
},
undoData: {
'componentId': component.id,
},
);
}
/// 创建删除元件命令
static Command createDeleteComponent(String componentId, Component component) {
return Command(
id: 'cmd_${DateTime.now().millisecondsSinceEpoch}',
type: CommandType.deleteComponent,
timestamp: DateTime.now(),
data: {
'componentId': componentId,
},
undoData: {
'id': component.id,
'component': component,
},
);
}
/// 创建移动元件命令
static Command createMoveComponent(
String componentId,
Offset oldPosition,
Offset newPosition,
) {
return Command(
id: 'cmd_${DateTime.now().millisecondsSinceEpoch}',
type: CommandType.moveComponent,
timestamp: DateTime.now(),
data: {
'componentId': componentId,
'oldPosition': oldPosition,
'newPosition': newPosition,
},
undoData: {
'oldPosition': oldPosition,
},
);
}
/// 创建旋转元件命令
static Command createRotateComponent(
String componentId,
int oldRotation,
int newRotation,
) {
return Command(
id: 'cmd_${DateTime.now().millisecondsSinceEpoch}',
type: CommandType.rotateComponent,
timestamp: DateTime.now(),
data: {
'componentId': componentId,
'oldRotation': oldRotation,
'newRotation': newRotation,
},
undoData: {
'oldRotation': oldRotation,
},
);
}
}
// ============================================================================
// Bug #2: 元件库扩展
// ============================================================================
/// 扩展元件库服务 - 添加更多常用元件
class ExtendedComponentLibraryService {
static final ExtendedComponentLibraryService _instance =
ExtendedComponentLibraryService._internal();
factory ExtendedComponentLibraryService() => _instance;
ExtendedComponentLibraryService._internal();
/// 获取所有可用元件(包含基础 + 扩展)
List<ComponentTemplate> getAllComponents() {
return [
// 基础元件(来自 ComponentLibraryService
...ComponentLibraryService().getCommonComponents(),
// 扩展元件
...getPassiveComponents(),
...getActiveComponents(),
...getConnectorComponents(),
...getSwitchComponents(),
];
}
/// 无源元件
List<ComponentTemplate> getPassiveComponents() {
return [
// 电感
ComponentTemplate(
id: 'inductor',
name: '电感',
category: 'passive',
symbol: 'L',
pinCount: 2,
pins: [
PinDefinition(pinId: '1', x: -10, y: 0, direction: PinDirection.left),
PinDefinition(pinId: '2', x: 10, y: 0, direction: PinDirection.right),
],
graphics: [
// 电感线圈符号
GraphicElement(
type: GraphicType.line,
points: [Offset(-10, 0), Offset(-8, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.arc,
center: Offset(-5, 0),
radius: 3,
startAngle: 180,
sweepAngle: 180,
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.arc,
center: Offset(0, 0),
radius: 3,
startAngle: 180,
sweepAngle: 180,
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.arc,
center: Offset(5, 0),
radius: 3,
startAngle: 180,
sweepAngle: 180,
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.line,
points: [Offset(8, 0), Offset(10, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
],
),
// 可变电阻
ComponentTemplate(
id: 'potentiometer',
name: '电位器',
category: 'passive',
symbol: 'RV',
pinCount: 3,
pins: [
PinDefinition(pinId: '1', x: -10, y: 5, direction: PinDirection.left),
PinDefinition(pinId: '2', x: 10, y: 5, direction: PinDirection.right),
PinDefinition(pinId: '3', x: 0, y: -10, direction: PinDirection.up),
],
graphics: [
// 电阻主体
GraphicElement(
type: GraphicType.zigzag,
points: [
Offset(-8, 5), Offset(-6, 2), Offset(-4, 8),
Offset(-2, 2), Offset(0, 8), Offset(2, 2),
Offset(4, 8), Offset(6, 2), Offset(8, 5),
],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 滑动触点箭头
GraphicElement(
type: GraphicType.line,
points: [Offset(0, -10), Offset(0, 3)],
style: LineStyle.solid,
width: 1.5,
color: Colors.black,
arrowHead: true,
),
],
),
];
}
/// 有源元件
List<ComponentTemplate> getActiveComponents() {
return [
// 二极管
ComponentTemplate(
id: 'diode',
name: '二极管',
category: 'active',
symbol: 'D',
pinCount: 2,
pins: [
PinDefinition(pinId: 'A', x: -10, y: 0, direction: PinDirection.left),
PinDefinition(pinId: 'K', x: 10, y: 0, direction: PinDirection.right),
],
graphics: [
// 三角形(阳极)
GraphicElement(
type: GraphicType.triangle,
points: [
Offset(-5, -6), Offset(-5, 6), Offset(5, 0),
],
style: LineStyle.solid,
width: 1,
color: Colors.black,
filled: false,
),
// 横线(阴极)
GraphicElement(
type: GraphicType.line,
points: [Offset(5, -6), Offset(5, 6)],
style: LineStyle.solid,
width: 2,
color: Colors.black,
),
// 引线
GraphicElement(
type: GraphicType.line,
points: [Offset(-10, 0), Offset(-5, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.line,
points: [Offset(5, 0), Offset(10, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
],
),
// NPN 三极管
ComponentTemplate(
id: 'npn_transistor',
name: 'NPN 三极管',
category: 'active',
symbol: 'Q',
pinCount: 3,
pins: [
PinDefinition(pinId: 'B', x: -15, y: 0, direction: PinDirection.left),
PinDefinition(pinId: 'C', x: 15, y: -10, direction: PinDirection.right),
PinDefinition(pinId: 'E', x: 15, y: 10, direction: PinDirection.right),
],
graphics: [
// 圆圈
GraphicElement(
type: GraphicType.circle,
points: [Offset(0, 0)],
radius: 12,
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 基极横线
GraphicElement(
type: GraphicType.line,
points: [Offset(-15, 0), Offset(-5, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 竖线
GraphicElement(
type: GraphicType.line,
points: [Offset(-5, -8), Offset(-5, 8)],
style: LineStyle.solid,
width: 2,
color: Colors.black,
),
// 集电极斜线
GraphicElement(
type: GraphicType.line,
points: [Offset(-2, -5), Offset(12, -10)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 发射极斜线(带箭头)
GraphicElement(
type: GraphicType.line,
points: [Offset(-2, 5), Offset(12, 10)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
arrowHead: true,
),
],
),
// PNP 三极管
ComponentTemplate(
id: 'pnp_transistor',
name: 'PNP 三极管',
category: 'active',
symbol: 'Q',
pinCount: 3,
pins: [
PinDefinition(pinId: 'B', x: -15, y: 0, direction: PinDirection.left),
PinDefinition(pinId: 'C', x: 15, y: -10, direction: PinDirection.right),
PinDefinition(pinId: 'E', x: 15, y: 10, direction: PinDirection.right),
],
graphics: [
// 圆圈
GraphicElement(
type: GraphicType.circle,
points: [Offset(0, 0)],
radius: 12,
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 基极横线
GraphicElement(
type: GraphicType.line,
points: [Offset(-15, 0), Offset(-5, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 竖线
GraphicElement(
type: GraphicType.line,
points: [Offset(-5, -8), Offset(-5, 8)],
style: LineStyle.solid,
width: 2,
color: Colors.black,
),
// 集电极斜线
GraphicElement(
type: GraphicType.line,
points: [Offset(-2, -5), Offset(12, -10)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 发射极斜线(箭头向内)
GraphicElement(
type: GraphicType.line,
points: [Offset(12, 10), Offset(-2, 5)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
arrowHead: true,
),
],
),
// MOSFET N 沟道
ComponentTemplate(
id: 'mosfet_n',
name: 'N 沟道 MOSFET',
category: 'active',
symbol: 'Q',
pinCount: 3,
pins: [
PinDefinition(pinId: 'G', x: -15, y: 0, direction: PinDirection.left),
PinDefinition(pinId: 'D', x: 15, y: -10, direction: PinDirection.right),
PinDefinition(pinId: 'S', x: 15, y: 10, direction: PinDirection.right),
],
graphics: [
// 栅极
GraphicElement(
type: GraphicType.line,
points: [Offset(-15, 0), Offset(-5, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 漏极
GraphicElement(
type: GraphicType.line,
points: [Offset(5, -10), Offset(15, -10)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 源极
GraphicElement(
type: GraphicType.line,
points: [Offset(5, 10), Offset(15, 10)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 垂直线
GraphicElement(
type: GraphicType.line,
points: [Offset(5, -8), Offset(5, 8)],
style: LineStyle.solid,
width: 2,
color: Colors.black,
),
],
),
];
}
/// 连接器
List<ComponentTemplate> getConnectorComponents() {
return [
// 排针
ComponentTemplate(
id: 'header_2p',
name: '2P 排针',
category: 'connector',
symbol: 'J',
pinCount: 2,
pins: [
PinDefinition(pinId: '1', x: 0, y: -10, direction: PinDirection.up),
PinDefinition(pinId: '2', x: 0, y: 10, direction: PinDirection.down),
],
graphics: [
// 矩形主体
GraphicElement(
type: GraphicType.rectangle,
points: [Offset(-8, -15), Offset(8, 15)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
// 引脚点
GraphicElement(
type: GraphicType.circle,
points: [Offset(0, -10)],
radius: 2,
style: LineStyle.solid,
width: 1,
color: Colors.black,
filled: true,
fillColor: Colors.black,
),
GraphicElement(
type: GraphicType.circle,
points: [Offset(0, 10)],
radius: 2,
style: LineStyle.solid,
width: 1,
color: Colors.black,
filled: true,
fillColor: Colors.black,
),
],
),
];
}
/// 开关
List<ComponentTemplate> getSwitchComponents() {
return [
// 单刀单掷开关
ComponentTemplate(
id: 'spst_switch',
name: 'SPST 开关',
category: 'switch',
symbol: 'S',
pinCount: 2,
pins: [
PinDefinition(pinId: '1', x: -10, y: 0, direction: PinDirection.left),
PinDefinition(pinId: '2', x: 10, y: 0, direction: PinDirection.right),
],
graphics: [
// 触点
GraphicElement(
type: GraphicType.circle,
points: [Offset(-8, 0)],
radius: 2,
style: LineStyle.solid,
width: 1,
color: Colors.black,
filled: true,
fillColor: Colors.black,
),
GraphicElement(
type: GraphicType.circle,
points: [Offset(8, 0)],
radius: 2,
style: LineStyle.solid,
width: 1,
color: Colors.black,
filled: true,
fillColor: Colors.black,
),
// 开关臂(断开状态)
GraphicElement(
type: GraphicType.line,
points: [Offset(-6, 0), Offset(6, -8)],
style: LineStyle.solid,
width: 2,
color: Colors.black,
),
// 引线
GraphicElement(
type: GraphicType.line,
points: [Offset(-10, 0), Offset(-8, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
GraphicElement(
type: GraphicType.line,
points: [Offset(8, 0), Offset(10, 0)],
style: LineStyle.solid,
width: 1,
color: Colors.black,
),
],
),
];
}
}
// ============================================================================
// 使用示例
// ============================================================================
/*
// 撤销/重做使用示例
final undoRedo = UndoRedoManager();
// 添加元件(带撤销支持)
final component = library.createComponentFromTemplate(template, x: 100, y: 100);
final command = CommandFactory.createAddComponent(component);
undoRedo.execute(command);
// 撤销
if (undoRedo.canUndo) {
undoRedo.undo();
}
// 重做
if (undoRedo.canRedo) {
undoRedo.redo();
}
// 扩展元件库使用示例
final extLibrary = ExtendedComponentLibraryService();
final allComponents = extLibrary.getAllComponents();
// 获取特定类型元件
final passiveComponents = extLibrary.getPassiveComponents();
final activeComponents = extLibrary.getActiveComponents();
final diode = passiveComponents.firstWhere((c) => c.id == 'diode');
*/