import 'package:ainoval/blocs/editor/editor_bloc.dart'; import 'package:ainoval/utils/logger.dart'; import 'package:ainoval/screens/editor/widgets/dialogs.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:ainoval/screens/editor/controllers/editor_screen_controller.dart'; /// 通用菜单项数据模型 class MenuItemData { final IconData icon; final String label; final Future Function(BuildContext, EditorBloc, String, String?, String?)? onTap; final bool hasSubmenu; final bool disabled; final bool isDangerous; const MenuItemData({ required this.icon, required this.label, this.onTap, this.hasSubmenu = false, this.disabled = false, this.isDangerous = false, }); } /// 模型菜单项数据模型(扩展用于模型操作) class ModelMenuItemData { final IconData icon; final String label; final Future Function(String configId)? onTap; final bool hasSubmenu; final bool disabled; final bool isDangerous; const ModelMenuItemData({ required this.icon, required this.label, this.onTap, this.hasSubmenu = false, this.disabled = false, this.isDangerous = false, }); } /// 菜单分区数据模型 class MenuSectionData { final String title; final List items; const MenuSectionData({ required this.title, required this.items, }); } /// 模型菜单分区数据模型 class ModelMenuSectionData { final String title; final List items; const ModelMenuSectionData({ required this.title, required this.items, }); } /// Model菜单定义 class ModelMenuDefinitions { static List getMenuItems({ required bool isValidated, required bool isDefault, required Future Function(String) onValidate, required Future Function(String) onSetDefault, required Future Function(String) onEdit, required Future Function(String) onDelete, }) { return [ // 验证操作 ModelMenuItemData( icon: isValidated ? Icons.verified : Icons.wifi_protected_setup, label: isValidated ? '重新验证' : '验证连接', onTap: onValidate, ), // 设为默认(如果不是默认模型) if (!isDefault) ModelMenuItemData( icon: Icons.star, label: '设为默认', onTap: onSetDefault, ), // 编辑操作 ModelMenuItemData( icon: Icons.edit, label: '编辑', onTap: onEdit, ), // 分隔线 "divider", // 危险操作 ModelMenuItemData( icon: Icons.delete_outline, label: '删除', isDangerous: true, onTap: onDelete, ), ]; } } /// Act菜单定义 class ActMenuDefinitions { static List getMenuItems() { return [ // 基本操作 MenuItemData( icon: Icons.add, label: '添加新章节', onTap: (context, editorBloc, actId, _, __) async { editorBloc.add(AddNewChapter( novelId: editorBloc.novelId, actId: actId, title: '新章节 ${DateTime.now().millisecondsSinceEpoch % 100}', )); }, ), MenuItemData( icon: Icons.edit, label: '重命名Act', onTap: null, ), // 导出选项 MenuSectionData( title: '导出选项', items: [ MenuItemData( icon: Icons.file_download, label: '导出为PDF', onTap: (context, editorBloc, actId, _, __) async { // 实现导出为PDF功能 }, ), MenuItemData( icon: Icons.file_download, label: '导出为Word', onTap: (context, editorBloc, actId, _, __) async { // 实现导出为Word功能 }, ), ], ), // 危险操作 MenuItemData( icon: Icons.delete_outline, label: '删除Act', isDangerous: true, onTap: (context, editorBloc, actId, _, __) async { final confirmed = await _confirmAndDelete( context, '删除Act', '确定要删除这个Act吗?此操作不可撤销。', ); if (confirmed) { editorBloc.add(DeleteAct( novelId: editorBloc.novelId, actId: actId, )); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('正在删除卷...'), duration: Duration(seconds: 2), ), ); } }, ), ]; } } /// Chapter菜单定义 class ChapterMenuDefinitions { static List getMenuItems() { return [ // 基本操作 MenuItemData( icon: Icons.add, label: '添加新场景', onTap: (context, editorBloc, actId, chapterId, _) async { _addNewScene(context, editorBloc, actId, chapterId!); }, ), MenuItemData( icon: Icons.edit, label: '重命名章节', onTap: null, ), // 分隔线 "divider", // 额外功能 MenuItemData( icon: Icons.tag, label: '禁用编号', onTap: (context, editorBloc, actId, chapterId, _) async { // 实现禁用编号功能 }, ), MenuItemData( icon: Icons.content_copy, label: '复制所有场景内容', onTap: (context, editorBloc, actId, chapterId, _) async { // 实现复制场景内容功能 }, ), // 分隔线 "divider", // 危险操作 MenuItemData( icon: Icons.delete_outline, label: '删除章节', isDangerous: true, onTap: (context, editorBloc, actId, chapterId, _) async { final confirmed = await _confirmAndDelete( context, '删除章节', '确定要删除这个章节吗?此操作不可撤销,章节内的所有场景都将被删除。', ); if (confirmed) { // 实现删除章节功能 editorBloc.add(DeleteChapter( novelId: editorBloc.novelId, actId: actId, chapterId: chapterId!, )); // 显示操作反馈 ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('正在删除章节...'), duration: Duration(seconds: 2), ), ); } }, ), ]; } /// 添加新场景 static void _addNewScene(BuildContext context, EditorBloc editorBloc, String actId, String chapterId) { final newSceneId = DateTime.now().millisecondsSinceEpoch.toString(); AppLogger.i('Chapter', '添加新场景:actId=$actId, chapterId=$chapterId, sceneId=$newSceneId'); editorBloc.add(AddNewScene( novelId: editorBloc.novelId, actId: actId, chapterId: chapterId, sceneId: newSceneId, )); } } /// Scene菜单定义 class SceneMenuDefinitions { static List getMenuItems() { return [ MenuItemData( icon: Icons.copy_outlined, label: '复制场景', onTap: (context, editorBloc, actId, chapterId, sceneId) async { // 实现复制场景功能 // editorBloc.add(DuplicateScene( // novelId: editorBloc.novelId, // actId: actId, // chapterId: chapterId!, // sceneId: sceneId!, // )); }, ), MenuItemData( icon: Icons.splitscreen_outlined, label: '拆分场景', onTap: (context, editorBloc, actId, chapterId, sceneId) async { // 实现拆分场景功能 }, ), MenuSectionData( title: 'AI功能', items: [ MenuItemData( icon: Icons.auto_awesome, label: '生成摘要', onTap: (context, editorBloc, actId, chapterId, sceneId) async { editorBloc.add(GenerateSceneSummaryRequested( sceneId: sceneId!, )); }, ), MenuItemData( icon: Icons.psychology, label: '改进内容', onTap: (context, editorBloc, actId, chapterId, sceneId) async { // 实现AI改进内容功能 }, ), ], ), // 分隔线 "divider", // 危险操作 MenuItemData( icon: Icons.delete_outline, label: '删除场景', isDangerous: true, onTap: (context, editorBloc, actId, chapterId, sceneId) async { final confirmed = await _confirmAndDelete( context, '删除场景', '确定要删除这个场景吗?此操作不可撤销。', ); if (confirmed) { editorBloc.add(DeleteScene( novelId: editorBloc.novelId, actId: actId, chapterId: chapterId!, sceneId: sceneId!, )); } }, ), ]; } } /// 通用确认删除对话框 Future _confirmAndDelete(BuildContext context, String title, String message) async { final confirmed = await DialogUtils.showDangerousConfirmDialog( context: context, title: title, message: message, ); return confirmed; }