现场上报模块使用说明
快速开始
1. 在路由中注册页面
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:maibu_satabot_v2/features/v2/report/report.dart';
// 在路由配置中添加
GoRoute(
path: '/report',
builder: (context, state) => BlocProvider(
create: (context) => ReportDependencyInjector.createReportCubit(),
child: const ReportPage(),
),
),
2. 跳转到上报页面
context.push('/report');
架构说明
清洁架构分层
lib/features/v2/report/
├── domain/ # 领域层(核心业务逻辑)
│ ├── entities/ # 实体类
│ │ └── report_entity.dart
│ ├── repositories/ # 仓储接口
│ │ └── report_repository.dart
│ └── usecases/ # 用例
│ └── submit_report_usecase.dart
├── data/ # 数据层(数据获取与存储)
│ ├── datasources/ # 数据源
│ │ ├── report_remote_datasource.dart
│ │ └── report_remote_datasource_impl.dart
│ ├── models/ # 数据模型
│ │ └── report_model.dart
│ └── repositories/ # 仓储实现
│ └── report_repository_impl.dart
├── presentation/ # 表现层(UI + 状态管理)
│ ├── constants/ # 常量
│ │ └── report_constants.dart
│ ├── cubit/ # 状态管理
│ │ └── report_cubit.dart
│ ├── states/ # 状态定义
│ │ └── report_state.dart
│ ├── pages/ # 页面
│ │ └── report_page.dart
│ ── widgets/ # 组件
│ ├── report_type_selector.dart
│ ├── device_selector.dart
│ ├── description_input.dart
│ ├── media_uploader.dart
│ └── level_selector.dart
├── di/ # 依赖注入
│ └── report_di.dart
└── report.dart # 统一导出
核心功能
1. 上报类型选择
- 设备故障
- 巡检记录
- 隐患上报
- 缺陷上报
2. 设备选择
- 点击选择设备(需实现设备选择页面)
3. 问题描述
- 多行文本输入
- 最大 200 字符限制
- 实时字符计数
4. 媒体上传
- 拍照上传
- 录像上传
- 图片预览
- 删除已上传图片
5. 问题等级
- 一般(灰色)
- 重要(橙色)
- 紧急(红色)
表单验证
提交时自动验证以下必填项:
- 设备选择
- 问题描述
- 问题等级
状态管理
状态类型
ReportInitial: 初始状态ReportFormState: 表单数据状态ReportSubmitting: 提交中状态ReportSuccess: 提交成功状态ReportFailure: 提交失败状态
Cubit 方法
selectReportType(ReportType): 选择上报类型selectDevice(String): 选择设备updateDescription(String): 更新问题描述selectProblemLevel(ProblemLevel): 选择问题等级addMediaFile(String): 添加媒体文件removeMediaFile(int): 删除媒体文件submitReport(): 提交上报resetForm(): 重置表单
自定义扩展
1. 对接真实 API
修改 ReportRemoteDataSourceImpl:
class ReportRemoteDataSourceImpl implements ReportRemoteDataSource {
final Dio dio; // 注入 Dio 实例
@override
Future<Either<Failure, bool>> submitReport(ReportModel report) async {
try {
final response = await dio.post(
'/api/report/submit',
data: report.toJson(),
);
if (response.statusCode == 200) {
return right(true);
} else {
return left(ServerFailure('提交失败'));
}
} catch (e) {
return left(NetworkFailure('网络错误: $e'));
}
}
}
2. 实现设备选择
在 ReportPage 中修改 _showDevicePicker 方法:
void _showDevicePicker(BuildContext context) {
// 跳转到设备选择页面
context.push('/device-select').then((device) {
if (device != null) {
context.read<ReportCubit>().selectDevice(device);
}
});
}
3. 实现真实的相机/相册功能
添加依赖:
dependencies:
image_picker: ^1.1.2
修改 MediaUploader:
final ImagePicker picker = ImagePicker();
Future<void> _pickImage() async {
final XFile? image = await picker.pickImage(source: ImageSource.camera);
if (image != null) {
cubit.addMediaFile(image.path);
}
}
依赖说明
项目已有依赖
- flutter_bloc: ^9.1.1
- equatable: ^2.0.8
- fpdart: ^1.2.0
可选依赖(按需添加)
- image_picker: ^1.1.2 (图片/视频选择)
- dio: ^5.9.0 (HTTP 请求,项目已有)
注意事项
- 所有颜色、尺寸常量已抽取到
report_constants.dart - 遵循清洁架构原则,内层不依赖外层
- 使用 fpdart 进行错误处理(Either 类型)
- 所有 UI 组件已适配 iOS 安全区
- 模拟数据已实现,可直接运行测试
后续开发建议
- 实现真实的设备选择页面
- 对接后端 API
- 添加图片压缩功能
- 实现离线缓存
- 添加草稿保存功能