Files
kuaishai2/lib/features/program_detail/providers/steps_provider.dart
Developer 5d28bf631b chore(project): 初始化项目基础配置文件
- 添加 CodeGraph、Android 和通用 gitignore 配置
- 创建项目元数据文件跟踪 Flutter 项目属性
- 添加 Codex AI 指导文档 AGENTS.md 说明项目架构
- 配置代码分析选项 analysis_options.yaml
- 设置 Android 应用清单权限和 Kiosk 模式配置
- 实现中英文国际化支持 AppLocalizations
- 配置 GoRouter 应用路由导航
- 创建明亮工业控制风格的主题配置 AppTheme
2026-06-04 11:19:44 +08:00

161 lines
4.1 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:flutter_riverpod/flutter_riverpod.dart';
import '../../programs/models/step.dart';
import '../../programs/services/program_service.dart';
/// 步骤状态
class StepsState {
final List<Step> steps;
final int? selectedStepId;
final bool isLoading;
final String? error;
const StepsState({
this.steps = const [],
this.selectedStepId,
this.isLoading = false,
this.error,
});
StepsState copyWith({
List<Step>? steps,
int? selectedStepId,
bool? isLoading,
String? error,
bool clearSelection = false,
bool clearError = false,
}) {
return StepsState(
steps: steps ?? this.steps,
selectedStepId: clearSelection ? null : (selectedStepId ?? this.selectedStepId),
isLoading: isLoading ?? this.isLoading,
error: clearError ? null : (error ?? this.error),
);
}
/// 获取选中的步骤
Step? get selectedStep {
if (selectedStepId == null) return null;
return steps.where((s) => s.id == selectedStepId).firstOrNull;
}
}
/// 步骤 Notifier
class StepsNotifier extends StateNotifier<StepsState> {
final ProgramService _service;
final int programId;
StepsNotifier(this._service, this.programId) : super(const StepsState()) {
loadSteps();
}
/// 加载步骤
Future<void> loadSteps() async {
state = state.copyWith(isLoading: true, clearError: true);
try {
final steps = await _service.getStepsByProgramId(programId);
state = state.copyWith(steps: steps, isLoading: false);
} catch (e) {
state = state.copyWith(isLoading: false, error: e.toString());
}
}
/// 选择步骤
void selectStep(int? stepId) {
state = state.copyWith(selectedStepId: stepId);
}
/// 清除选择
void clearSelection() {
state = state.copyWith(clearSelection: true);
}
/// 添加步骤
Future<bool> addStep(Step step) async {
try {
await _service.addStep(step);
await loadSteps();
return true;
} catch (e) {
state = state.copyWith(error: e.toString());
return false;
}
}
/// 更新步骤
Future<bool> updateStep(Step step) async {
if (step.id == null) return false;
try {
await _service.updateStep(step);
await loadSteps();
return true;
} catch (e) {
state = state.copyWith(error: e.toString());
return false;
}
}
/// 删除步骤
Future<bool> deleteStep(int stepId) async {
try {
await _service.deleteStep(stepId);
if (state.selectedStepId == stepId) {
state = state.copyWith(clearSelection: true);
}
await loadSteps();
return true;
} catch (e) {
state = state.copyWith(error: e.toString());
return false;
}
}
/// 批量删除步骤
Future<bool> deleteSteps(List<int> stepIds) async {
try {
await _service.deleteSteps(stepIds);
if (stepIds.contains(state.selectedStepId)) {
state = state.copyWith(clearSelection: true);
}
await loadSteps();
return true;
} catch (e) {
state = state.copyWith(error: e.toString());
return false;
}
}
/// 重新排序步骤
Future<void> reorderSteps(int oldIndex, int newIndex) async {
final steps = List<Step>.from(state.steps);
final step = steps.removeAt(oldIndex);
steps.insert(newIndex, step);
// 更新 step_no
for (int i = 0; i < steps.length; i++) {
steps[i] = steps[i].copyWith(stepNo: i + 1);
}
state = state.copyWith(steps: steps);
// 持久化排序
await _service.reorderSteps(programId, steps.map((s) => s.id!).toList());
}
}
/// 程序服务 Provider
final programServiceProvider = Provider<ProgramService>((ref) {
return ProgramService.instance;
});
/// 步骤 Provider按程序ID
final stepsProvider = StateNotifierProvider.family<StepsNotifier, StepsState, int>(
(ref, programId) {
final service = ref.watch(programServiceProvider);
return StepsNotifier(service, programId);
},
);
/// 选中的步骤 Provider
final selectedStepProvider = Provider.family<Step?, int>((ref, programId) {
return ref.watch(stepsProvider(programId)).selectedStep;
});