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

@@ -12,6 +12,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import '../../../data/models/journal_element.dart';
import '../bloc/editor_bloc.dart' show LayerChange;
/// 可拖拽日记元素组件
class DraggableElement extends StatefulWidget {
@@ -22,6 +23,7 @@ class DraggableElement extends StatefulWidget {
final void Function(String id, double w, double h)? onResized;
final void Function(String id, double rotation)? onRotated;
final ValueChanged<String> onDeleted;
final void Function(String id, LayerChange change)? onLayerChanged;
const DraggableElement({
super.key,
@@ -32,6 +34,7 @@ class DraggableElement extends StatefulWidget {
this.onResized,
this.onRotated,
required this.onDeleted,
this.onLayerChanged,
});
@override
@@ -142,26 +145,41 @@ class _DraggableElementState extends State<DraggableElement> {
),
),
// 选中时显示删除按钮
// 选中时显示操作按钮:图层 + 删除
if (widget.isSelected)
Positioned(
top: -12,
right: -12,
child: GestureDetector(
onTap: () => widget.onDeleted(widget.element.id),
child: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// 置顶
_ActionButton(
icon: Icons.flip_to_front_rounded,
color: Theme.of(context).colorScheme.primary,
onTap: () => widget.onLayerChanged?.call(
widget.element.id,
LayerChange.bringToFront,
),
),
const SizedBox(width: 4),
// 置底
_ActionButton(
icon: Icons.flip_to_back_rounded,
color: Theme.of(context).colorScheme.primary,
onTap: () => widget.onLayerChanged?.call(
widget.element.id,
LayerChange.sendToBack,
),
),
const SizedBox(width: 4),
// 删除
_ActionButton(
icon: Icons.close_rounded,
color: Theme.of(context).colorScheme.error,
shape: BoxShape.circle,
onTap: () => widget.onDeleted(widget.element.id),
),
child: const Icon(
Icons.close_rounded,
size: 16,
color: Colors.white,
),
),
],
),
),
],
@@ -279,3 +297,32 @@ class _DraggableElementState extends State<DraggableElement> {
);
}
}
/// 选中元素的操作按钮(图层/删除)
class _ActionButton extends StatelessWidget {
final IconData icon;
final Color color;
final VoidCallback onTap;
const _ActionButton({
required this.icon,
required this.color,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
child: Icon(icon, size: 16, color: Colors.white),
),
);
}
}