Files
MaliangAINovalWriter/AINoval/lib/screens/editor/widgets/menu_definitions.dart
2025-09-10 00:07:52 +08:00

356 lines
9.4 KiB
Dart
Raw 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: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<void> 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<void> 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<MenuItemData> items;
const MenuSectionData({
required this.title,
required this.items,
});
}
/// 模型菜单分区数据模型
class ModelMenuSectionData {
final String title;
final List<ModelMenuItemData> items;
const ModelMenuSectionData({
required this.title,
required this.items,
});
}
/// Model菜单定义
class ModelMenuDefinitions {
static List<dynamic> getMenuItems({
required bool isValidated,
required bool isDefault,
required Future<void> Function(String) onValidate,
required Future<void> Function(String) onSetDefault,
required Future<void> Function(String) onEdit,
required Future<void> 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<dynamic> 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<dynamic> 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<dynamic> 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<bool> _confirmAndDelete(BuildContext context, String title, String message) async {
final confirmed = await DialogUtils.showDangerousConfirmDialog(
context: context,
title: title,
message: message,
);
return confirmed;
}