- 添加 CodeGraph、Android 和通用 gitignore 配置 - 创建项目元数据文件跟踪 Flutter 项目属性 - 添加 Codex AI 指导文档 AGENTS.md 说明项目架构 - 配置代码分析选项 analysis_options.yaml - 设置 Android 应用清单权限和 Kiosk 模式配置 - 实现中英文国际化支持 AppLocalizations - 配置 GoRouter 应用路由导航 - 创建明亮工业控制风格的主题配置 AppTheme
161 lines
4.1 KiB
Dart
161 lines
4.1 KiB
Dart
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;
|
||
}); |