马良AI写作初始化仓库

This commit is contained in:
邓滨杰
2025-09-10 00:07:52 +08:00
parent 3c06bb1a03
commit 39c0f8840f
1309 changed files with 318528 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:ainoval/models/novel_structure.dart'; // Changed from novel_chapter.dart
import 'package:ainoval/models/novel_setting_item.dart';
import 'package:ainoval/services/api_service/repositories/editor_repository.dart'; // Changed from novel_chapter_repository.dart
import 'package:ainoval/services/api_service/repositories/novel_ai_repository.dart'; // New repository for AI features
import 'package:ainoval/utils/logger.dart';
part 'ai_setting_generation_event.dart';
part 'ai_setting_generation_state.dart';
class AISettingGenerationBloc extends Bloc<AISettingGenerationEvent, AISettingGenerationState> {
final EditorRepository _editorRepository; // Changed
final NovelAIRepository _novelAIRepository;
List<Chapter> _loadedChapters = []; // Changed from NovelChapter
AISettingGenerationBloc({
required EditorRepository editorRepository, // Changed
required NovelAIRepository novelAIRepository,
}) : _editorRepository = editorRepository, // Changed
_novelAIRepository = novelAIRepository,
super(AISettingGenerationInitial()) {
on<LoadInitialDataForAISettingPanel>(_onLoadInitialData);
on<GenerateSettingsRequested>(_onGenerateSettingsRequested);
// on<AdoptGeneratedSetting>(_onAdoptGeneratedSetting); // For later
}
Future<void> _onLoadInitialData(
LoadInitialDataForAISettingPanel event,
Emitter<AISettingGenerationState> emit,
) async {
emit(AISettingGenerationLoadingChapters());
try {
final novel = await _editorRepository.getNovelWithAllScenes(event.novelId); // Use existing method that loads all structure
if (novel != null) {
_loadedChapters = novel.acts.expand((act) => act.chapters).toList();
// Sort chapters by their order, assuming Act and Chapter orders are set
_loadedChapters.sort((a, b) {
// Find act orders first
final actA = novel.acts.firstWhere((act) => act.chapters.contains(a));
final actB = novel.acts.firstWhere((act) => act.chapters.contains(b));
if (actA.order != actB.order) {
return actA.order.compareTo(actB.order);
}
return a.order.compareTo(b.order);
});
emit(AISettingGenerationDataLoaded(chapters: _loadedChapters, novel: novel));
} else {
AppLogger.e('AISettingGenerationBloc', 'Novel not found: ${event.novelId}');
emit(AISettingGenerationFailure(error: '小说未找到', chapters: [], novel: null));
}
} catch (e, stackTrace) {
AppLogger.e('AISettingGenerationBloc', 'Error loading chapters for AI Panel', e, stackTrace);
emit(AISettingGenerationFailure(error: '加载章节列表失败: ${e.toString()}', chapters: [], novel: null));
}
}
Future<void> _onGenerateSettingsRequested(
GenerateSettingsRequested event,
Emitter<AISettingGenerationState> emit,
) async {
final currentChapters = _loadedChapters;
emit(AISettingGenerationInProgress());
try {
final settings = await _novelAIRepository.generateNovelSettings(
novelId: event.novelId,
startChapterId: event.startChapterId,
endChapterId: event.endChapterId,
settingTypes: event.settingTypes,
maxSettingsPerType: event.maxSettingsPerType,
additionalInstructions: event.additionalInstructions,
);
// 保持当前的Novel引用
final currentNovel = (state is AISettingGenerationDataLoaded) ? (state as AISettingGenerationDataLoaded).novel : null;
emit(AISettingGenerationSuccess(generatedSettings: settings, chapters: currentChapters, novel: currentNovel));
} catch (e, stackTrace) {
AppLogger.e('AISettingGenerationBloc', 'Error generating settings', e, stackTrace);
final currentNovel = (state is AISettingGenerationDataLoaded) ? (state as AISettingGenerationDataLoaded).novel : null;
emit(AISettingGenerationFailure(error: '生成设定失败: ${e.toString()}', chapters: currentChapters, novel: currentNovel));
}
}
// Future<void> _onAdoptGeneratedSetting(
// AdoptGeneratedSetting event,
// Emitter<AISettingGenerationState> emit,
// ) async {
// // This will interact with SettingBloc or its repository
// // For now, just log. Will require careful state management
// AppLogger.i('AISettingGenerationBloc', 'Adopting setting: ${event.settingItem.name} to group ${event.targetGroupId}');
// // Potentially re-emit current success state or a new state indicating adoption is in progress/done
// if (state is AISettingGenerationSuccess) {
// emit(AISettingGenerationSuccess(
// generatedSettings: (state as AISettingGenerationSuccess).generatedSettings.where((s) => s.id != event.settingItem.id).toList(), // Example: remove adopted item
// chapters: _loadedChapters,
// ));
// }
// }
}

View File

@@ -0,0 +1,60 @@
part of 'ai_setting_generation_bloc.dart';
abstract class AISettingGenerationEvent extends Equatable {
const AISettingGenerationEvent();
@override
List<Object?> get props => [];
}
class LoadInitialDataForAISettingPanel extends AISettingGenerationEvent {
final String novelId;
const LoadInitialDataForAISettingPanel(this.novelId);
@override
List<Object> get props => [novelId];
}
class GenerateSettingsRequested extends AISettingGenerationEvent {
final String novelId;
final String startChapterId;
final String? endChapterId;
final List<String> settingTypes; // Values from SettingType enum
final int maxSettingsPerType;
final String additionalInstructions;
const GenerateSettingsRequested({
required this.novelId,
required this.startChapterId,
this.endChapterId,
required this.settingTypes,
required this.maxSettingsPerType,
required this.additionalInstructions,
});
@override
List<Object?> get props => [
novelId,
startChapterId,
endChapterId,
settingTypes,
maxSettingsPerType,
additionalInstructions,
];
}
// Event for when user wants to adopt a setting (to be implemented fully later)
class AdoptGeneratedSetting extends AISettingGenerationEvent {
final NovelSettingItem settingItem;
final String targetGroupId; // ID of the SettingGroup to add to
final String novelId;
const AdoptGeneratedSetting({
required this.settingItem,
required this.targetGroupId,
required this.novelId,
});
@override
List<Object> get props => [settingItem, targetGroupId, novelId];
}

View File

@@ -0,0 +1,56 @@
part of 'ai_setting_generation_bloc.dart';
abstract class AISettingGenerationState extends Equatable {
const AISettingGenerationState();
@override
List<Object?> get props => [];
}
class AISettingGenerationInitial extends AISettingGenerationState {}
class AISettingGenerationLoadingChapters extends AISettingGenerationState {}
class AISettingGenerationDataLoaded extends AISettingGenerationState {
final List<Chapter> chapters;
final Novel? novel; // 添加Novel信息以获取Act数据
// availableSettingTypes are derived from SettingType enum directly in UI
// User selections are managed by the UI state for now.
const AISettingGenerationDataLoaded({required this.chapters, this.novel});
@override
List<Object?> get props => [chapters, novel];
}
class AISettingGenerationInProgress extends AISettingGenerationState {}
class AISettingGenerationSuccess extends AISettingGenerationState {
final List<NovelSettingItem> generatedSettings;
final List<Chapter> chapters; // Keep chapters loaded
final Novel? novel; // 添加Novel信息
const AISettingGenerationSuccess({
required this.generatedSettings,
required this.chapters,
this.novel,
});
@override
List<Object?> get props => [generatedSettings, chapters, novel];
}
class AISettingGenerationFailure extends AISettingGenerationState {
final String error;
final List<Chapter> chapters; // Keep chapters loaded if available
final Novel? novel; // 添加Novel信息
const AISettingGenerationFailure({
required this.error,
required this.chapters,
this.novel,
});
@override
List<Object?> get props => [error, chapters, novel];
}