feat(app): 编辑器增强 — 查看模式 + 图层排序 + 标签/贴纸动态化

- EditorPage 新增查看模式: 打开已保存日记默认只读,编辑按钮切换
- EditorBloc 新增 ElementLayerChanged 事件,支持置顶/置底图层排序
- DraggableElement 添加图层控制按钮 (置顶/置底/删除)
- TagPanel 标签建议改为从日记历史动态生成 (Top 10 频率)
- StickerPickerSheet 重构,预留 API 扩展点
This commit is contained in:
iven
2026-06-07 10:43:37 +08:00
parent a5d2b0409f
commit a05374e8d1
5 changed files with 246 additions and 78 deletions

View File

@@ -99,6 +99,16 @@ class ElementSelected extends EditorEvent {
ElementSelected(this.elementId);
}
/// 图层顺序调整方向
enum LayerChange { bringToFront, sendToBack }
/// 调整元素图层顺序
class ElementLayerChanged extends EditorEvent {
final String elementId;
final LayerChange change;
ElementLayerChanged({required this.elementId, required this.change});
}
// --- 工具栏事件 ---
/// 切换活动工具
@@ -335,6 +345,7 @@ class EditorBloc extends Bloc<EditorEvent, EditorState> {
on<ElementResized>(_onElementResized);
on<ElementRotated>(_onElementRotated);
on<ElementSelected>(_onElementSelected);
on<ElementLayerChanged>(_onElementLayerChanged);
on<ElementsLoaded>(_onElementsLoaded);
// 日记加载事件
@@ -492,6 +503,36 @@ class EditorBloc extends Bloc<EditorEvent, EditorState> {
));
}
/// 调整元素图层顺序 — 置顶或置底
void _onElementLayerChanged(
ElementLayerChanged event,
Emitter<EditorState> emit,
) {
final elements = List<JournalElement>.from(state.elements);
final index = elements.indexWhere((e) => e.id == event.elementId);
if (index == -1) return;
switch (event.change) {
case LayerChange.bringToFront:
// 设为最大 zIndex + 1
final maxZ = elements.fold<int>(
0,
(max, e) => e.zIndex > max ? e.zIndex : max,
);
elements[index] = elements[index].copyWith(zIndex: maxZ + 1);
case LayerChange.sendToBack:
// 设为最小 zIndex - 1
final minZ = elements.fold<int>(
0,
(min, e) => e.zIndex < min ? e.zIndex : min,
);
elements[index] = elements[index].copyWith(zIndex: minZ - 1);
}
emit(state.copyWith(elements: elements, isDirty: true));
_scheduleAutoSave();
}
void _onElementsLoaded(ElementsLoaded event, Emitter<EditorState> emit) {
emit(state.copyWith(elements: event.elements));
}