Browse Source

feat : 新增问题选择企业

dev
徐振升 3 days ago
parent
commit
4ec2e41e51
  1. 85
      lib/app/app.dart
  2. 40
      lib/app/core/models/use_case/use_case.dart
  3. 7
      lib/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart
  4. 2
      lib/app/features/enterprise/domain/repositories/enterprise_repository.dart
  5. 12
      lib/app/features/enterprise/domain/usecases/get_enterprises_usecase.dart
  6. 8
      lib/app/features/problem/presentation/bindings/problem_form_binding.dart
  7. 40
      lib/app/features/problem/presentation/controllers/problem_form_controller.dart
  8. 201
      lib/app/features/problem/presentation/pages/problem_form_page.dart
  9. 84
      lib/main.dart

85
lib/app/app.dart

@ -0,0 +1,85 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:problem_check_system/app/core/routes/app_pages.dart';
import 'package:problem_check_system/app/core/routes/app_routes.dart'; //
import 'package:problem_check_system/app/core/bindings/initial_binding.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
// 稿, dp
return ScreenUtilInit(
designSize: const Size(375, 812),
minTextAdapt: true,
splitScreenMode: true,
builder: (context, _) {
// 使 _ child
return GetMaterialApp(
debugShowCheckedModeBanner: false,
// --- ---
localizationsDelegates: const [
// Material
GlobalMaterialLocalizations.delegate,
// Widgets
GlobalWidgetsLocalizations.delegate,
// iOS
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('zh', 'CN'), //
],
title: '问题检查系统', // 使
theme: ThemeData(
useMaterial3: true,
// 使 colorSchemeSeed M3
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlue),
primaryColor: Colors.lightBlue,
// () NavigationBar
navigationBarTheme: NavigationBarThemeData(
// 1.
height: 48, // 70
// 2.
// 使 MaterialStateProperty.resolveWith
iconTheme: WidgetStateProperty.resolveWith((states) {
// IconThemeData
return IconThemeData(
size: 24, // 24 28
);
}),
//
labelBehavior:
NavigationDestinationLabelBehavior.onlyShowSelected,
// backgroundColor: Colors.white,
//
indicatorColor: Colors.deepOrange.shade200,
// 使 indicatorShape
// indicatorShape: const CustomIndicatorShape(
// //
// // horizontalPadding: 24.0, //
// // horizontalPadding: 8.0, //
// horizontalPadding: 0, //
// ),
//
labelTextStyle: WidgetStateProperty.all(
TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.deepOrange,
),
),
),
),
// 使 GetX
initialRoute: AppRoutes.login, // 使
initialBinding: InitialBinding(), //
getPages: AppPages.routes, //
);
},
);
}
}

40
lib/app/core/models/use_case/use_case.dart

@ -0,0 +1,40 @@
// // lib/core/usecases/usecase.dart
// // UseCase
// // Type: (: List<EnterpriseEntity>)
// // Params: UseCase所需要的参数 (: ID )
// import 'package:equatable/equatable.dart';
// abstract class UseCase<Type, Params> {
// /// Use Case call
// /// Future
// /// Either<Failure, Type>
// /// Left (Failure)Right (Type)
// Future<Either<Failure, Type>> call(Params params);
// }
// // lib/core/usecases/usecase.dart ()
// /// UseCase 使
// class NoParams extends Equatable {
// @override
// List<Object?> get props => [];
// }
// // Failure
// abstract class Failure extends Equatable {
// const Failure([List properties = const <dynamic>[]]);
// @override
// List<Object?> get props => [];
// }
// //
// /// API 使
// class ServerFailure extends Failure {}
// /// 使
// class CacheFailure extends Failure {}
// /// 使
// class NetworkFailure extends Failure {}

7
lib/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart

@ -185,4 +185,11 @@ class EnterpriseRepositoryImpl implements EnterpriseRepository {
final enterpriseModel = EnterpriseModel.fromEntity(chosenEnterprise); final enterpriseModel = EnterpriseModel.fromEntity(chosenEnterprise);
return localDataSource.upsertEnterprise(enterpriseModel); return localDataSource.upsertEnterprise(enterpriseModel);
} }
@override
Future<List<Enterprise>> getAllEnterprises() async {
final models = await localDataSource.getAllEnterprises();
final enterprises = models.map((model) => model.toEntity()).toList();
return enterprises;
}
} }

2
lib/app/features/enterprise/domain/repositories/enterprise_repository.dart

@ -29,4 +29,6 @@ abstract class EnterpriseRepository implements SyncableRepository<Enterprise> {
Future<SyncResult> syncWithServer(); Future<SyncResult> syncWithServer();
// [] // []
Future<void> resolveConflictAndUpdate(Enterprise chosenEnterprise); Future<void> resolveConflictAndUpdate(Enterprise chosenEnterprise);
//
Future<List<Enterprise>> getAllEnterprises();
} }

12
lib/app/features/enterprise/domain/usecases/get_enterprises_usecase.dart

@ -0,0 +1,12 @@
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart';
class GetEnterprisesUsecase {
final EnterpriseRepository repository;
GetEnterprisesUsecase({required this.repository});
Future<List<Enterprise>> call() {
return repository.getAllEnterprises();
}
}

8
lib/app/features/problem/presentation/bindings/problem_form_binding.dart

@ -6,7 +6,7 @@ import 'package:problem_check_system/app/features/enterprise/data/datasources/en
import 'package:problem_check_system/app/features/enterprise/data/datasources/enterprise_remote_data_source.dart'; import 'package:problem_check_system/app/features/enterprise/data/datasources/enterprise_remote_data_source.dart';
import 'package:problem_check_system/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart'; import 'package:problem_check_system/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart';
import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart'; import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprises_usecase.dart';
import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart'; import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart';
import 'package:problem_check_system/app/features/problem/presentation/controllers/problem_form_controller.dart'; import 'package:problem_check_system/app/features/problem/presentation/controllers/problem_form_controller.dart';
@ -51,15 +51,15 @@ class ProblemFormBinding extends Bindings {
), ),
); );
Get.put<GetEnterpriseListUsecase>( Get.put<GetEnterprisesUsecase>(
GetEnterpriseListUsecase(repository: Get.find<EnterpriseRepository>()), GetEnterprisesUsecase(repository: Get.find<EnterpriseRepository>()),
); );
Get.lazyPut<ProblemFormController>( Get.lazyPut<ProblemFormController>(
() => ProblemFormController( () => ProblemFormController(
problem: problem, problem: problem,
formMode: formMode, formMode: formMode,
getEnterpriseListUsecase: Get.find<GetEnterpriseListUsecase>(), getEnterprisesUsecase: Get.find<GetEnterprisesUsecase>(),
), ),
); );
} }

40
lib/app/features/problem/presentation/controllers/problem_form_controller.dart

@ -9,14 +9,19 @@ import 'package:path_provider/path_provider.dart';
import 'package:problem_check_system/app/core/models/form_mode.dart'; import 'package:problem_check_system/app/core/models/form_mode.dart';
import 'package:problem_check_system/app/core/models/image_status.dart'; import 'package:problem_check_system/app/core/models/image_status.dart';
import 'package:problem_check_system/app/core/models/image_metadata_model.dart'; import 'package:problem_check_system/app/core/models/image_metadata_model.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_list_item.dart'; import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprises_usecase.dart';
import 'dart:io'; import 'dart:io';
import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart'; import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
class ProblemFormController extends GetxController { class ProblemFormController extends GetxController {
final RxBool isLoading = false.obs; // 2. : 使 .obs 使
final isLoading = true.obs; //
final error = ''.obs; //
final enterpriseList = <Enterprise>[].obs; //
final selectedEnterprise = Rxn<Enterprise>();
final ProblemEntity? problem; final ProblemEntity? problem;
late Map<String, dynamic> bindInfo; late Map<String, dynamic> bindInfo;
@ -35,13 +40,13 @@ class ProblemFormController extends GetxController {
final TextEditingController descriptionController = TextEditingController(); final TextEditingController descriptionController = TextEditingController();
final TextEditingController locationController = TextEditingController(); final TextEditingController locationController = TextEditingController();
final RxList<XFile> selectedImages = <XFile>[].obs; final RxList<XFile> selectedImages = <XFile>[].obs;
final GetEnterpriseListUsecase getEnterpriseListUsecase; final GetEnterprisesUsecase getEnterprisesUsecase;
// 使便 // 使便
ProblemFormController({ ProblemFormController({
this.problem, this.problem,
this.formMode = FormMode.view, this.formMode = FormMode.view,
required this.getEnterpriseListUsecase, required this.getEnterprisesUsecase,
}) { }) {
if (problem != null) { if (problem != null) {
if (problem!.bindData != null) { if (problem!.bindData != null) {
@ -62,6 +67,7 @@ class ProblemFormController extends GetxController {
void onInit() { void onInit() {
super.onInit(); super.onInit();
updatePageTitle(); updatePageTitle();
_fetchEnterprises();
} }
@override @override
@ -85,9 +91,27 @@ class ProblemFormController extends GetxController {
} }
} }
// // 4. :
Future<List<EnterpriseListItem>> getAllEnterprises() async { Future<void> _fetchEnterprises() async {
return await getEnterpriseListUsecase(); try {
isLoading(true);
error(''); //
final result = await getEnterprisesUsecase(); // UseCase
enterpriseList.assignAll(result); //
} catch (e) {
error.value = '加载企业列表失败: $e'; //
} finally {
isLoading(false); //
}
}
// 5. : UI调用以更新状态
void selectEnterprise(Enterprise? enterprise) {
selectedEnterprise.value = enterprise;
//
if (enterprise != null) {
print('Selected: ${enterprise.name}');
}
} }
// pickImage // pickImage

201
lib/app/features/problem/presentation/pages/problem_form_page.dart

@ -4,6 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:problem_check_system/app/core/pages/widgets/custom_app_bar.dart'; import 'package:problem_check_system/app/core/pages/widgets/custom_app_bar.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/problem/presentation/controllers/problem_form_controller.dart'; import 'package:problem_check_system/app/features/problem/presentation/controllers/problem_form_controller.dart';
class ProblemFormPage extends GetView<ProblemFormController> { class ProblemFormPage extends GetView<ProblemFormController> {
@ -18,73 +19,94 @@ class ProblemFormPage extends GetView<ProblemFormController> {
leadingVisible: true, leadingVisible: true,
), ),
body: SafeArea( body: SafeArea(
child: Column( child: Obx(() {
children: [ // 1.
Expanded( if (controller.isLoading.value) {
child: SingleChildScrollView( return const Center(child: CircularProgressIndicator());
child: Column( }
children: [
if (controller.isShowBindData) // 2.
Container( if (controller.error.isNotEmpty) {
color: Colors.white, return Center(
padding: const EdgeInsets.symmetric( child: Text(
horizontal: 16.0, controller.error.value,
vertical: 8.0, style: const TextStyle(color: Colors.red),
), ),
child: Column( );
crossAxisAlignment: CrossAxisAlignment.start, }
children: <Widget>[
_buildSection( // 3.
'项目名称', if (controller.enterpriseList.isEmpty) {
controller.bindInfo['projectName'], return const Center(child: Text('没有可用的企业'));
), }
_buildDivider(), return Column(
_buildSection( children: [
'企业名称', Expanded(
controller.bindInfo['companyName'], child: SingleChildScrollView(
), child: Column(
_buildDivider(), children: [
_buildSection( if (controller.isShowBindData)
'要素名称', Container(
controller.bindInfo['censorElementName'], color: Colors.white,
), padding: const EdgeInsets.symmetric(
_buildDivider(), horizontal: 16.0,
_buildSection( vertical: 8.0,
'评估内容', ),
controller.bindInfo['pgContent'], child: Column(
), crossAxisAlignment: CrossAxisAlignment.start,
_buildDivider(), children: <Widget>[
_buildSection( _buildSection(
'建议项', '项目名称',
controller.bindInfo['suggestion'], controller.bindInfo['projectName'],
), ),
_buildDivider(), _buildDivider(),
_buildSection('问题类型', ''), _buildSection(
_buildDivider(), '企业名称',
_buildSection('工艺设备名称', ''), controller.bindInfo['companyName'],
], ),
_buildDivider(),
_buildSection(
'要素名称',
controller.bindInfo['censorElementName'],
),
_buildDivider(),
_buildSection(
'评估内容',
controller.bindInfo['pgContent'],
),
_buildDivider(),
_buildSection(
'建议项',
controller.bindInfo['suggestion'],
),
_buildDivider(),
_buildSection('问题类型', ''),
_buildDivider(),
_buildSection('工艺设备名称', ''),
],
),
), ),
_buildDropDownCard(title: '企业名称'),
_buildInputCard(
title: '问题描述',
textController: controller.descriptionController,
hintText: '请输入问题描述',
), ),
_buildDropDownCard(title: '企业名称'), _buildInputCard(
_buildInputCard( title: '所在位置',
title: '问题描述', textController: controller.locationController,
textController: controller.descriptionController, hintText: '请输入问题所在位置',
hintText: '请输入问题描述', ),
), _buildImageCard(context),
_buildInputCard( ],
title: '所在位置', ),
textController: controller.locationController,
hintText: '请输入问题所在位置',
),
_buildImageCard(context),
],
), ),
), ),
), //
// if (!controller.isReadOnly) _bottomButton(),
if (!controller.isReadOnly) _bottomButton(), ],
], );
), }),
), ),
); );
} }
@ -436,7 +458,29 @@ class ProblemFormPage extends GetView<ProblemFormController> {
const SizedBox(height: 20.0), const SizedBox(height: 20.0),
// --- 2. --- // --- 2. ---
_buildDropdownSelector(), Padding(
padding: EdgeInsetsGeometry.only(left: 16.w, right: 16.w),
child: DropdownButtonHideUnderline(
child: DropdownButton<Enterprise>(
//
hint: const Text('请选择一个企业'),
isExpanded: true,
//
value: controller.selectedEnterprise.value,
// map从控制器列表动态生成
items: controller.enterpriseList.map((enterprise) {
return DropdownMenuItem<Enterprise>(
value: enterprise, // EnterpriseEntity对象本身
child: Text(enterprise.name), //
);
}).toList(),
//
onChanged: (newValue) {
controller.selectEnterprise(newValue);
},
),
),
),
], ],
), ),
); );
@ -487,33 +531,4 @@ class ProblemFormPage extends GetView<ProblemFormController> {
], ],
); );
} }
///
Widget _buildDropdownSelector() {
// 使 InkWell 使
return InkWell(
onTap: () {
//
print('下拉选择区域被点击');
},
// 使
borderRadius: BorderRadius.circular(8.0),
child: Padding(
padding: EdgeInsets.only(left: 16.w, top: 0, right: 16.w, bottom: 16.h),
child: Row(
// 使 spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//
const Text(
'山东汇丰石化集团有限公司',
style: TextStyle(fontSize: 16, color: Colors.black54),
),
//
Icon(Icons.arrow_drop_down, color: Colors.grey[700]),
],
),
),
);
}
} }

84
lib/main.dart

@ -1,12 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:problem_check_system/app/core/routes/app_pages.dart'; import 'package:problem_check_system/app/app.dart';
import 'package:problem_check_system/app/core/routes/app_routes.dart'; //
import 'package:problem_check_system/app/core/bindings/initial_binding.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() async { void main() async {
// Flutter Binding // Flutter Binding
@ -23,81 +19,3 @@ void main() async {
runApp(const MainApp()); runApp(const MainApp());
} }
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
// 稿, dp
return ScreenUtilInit(
designSize: const Size(375, 812),
minTextAdapt: true,
splitScreenMode: true,
builder: (context, _) {
// 使 _ child
return GetMaterialApp(
debugShowCheckedModeBanner: false,
// --- ---
localizationsDelegates: const [
// Material
GlobalMaterialLocalizations.delegate,
// Widgets
GlobalWidgetsLocalizations.delegate,
// iOS
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: const [
Locale('zh', 'CN'), //
],
title: '问题检查系统', // 使
theme: ThemeData(
useMaterial3: true,
// 使 colorSchemeSeed M3
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlue),
primaryColor: Colors.lightBlue,
// () NavigationBar
navigationBarTheme: NavigationBarThemeData(
// 1.
height: 48, // 70
// 2.
// 使 MaterialStateProperty.resolveWith
iconTheme: WidgetStateProperty.resolveWith((states) {
// IconThemeData
return IconThemeData(
size: 24, // 24 28
);
}),
//
labelBehavior:
NavigationDestinationLabelBehavior.onlyShowSelected,
// backgroundColor: Colors.white,
//
indicatorColor: Colors.deepOrange.shade200,
// 使 indicatorShape
// indicatorShape: const CustomIndicatorShape(
// //
// // horizontalPadding: 24.0, //
// // horizontalPadding: 8.0, //
// horizontalPadding: 0, //
// ),
//
labelTextStyle: WidgetStateProperty.all(
TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Colors.deepOrange,
),
),
),
),
// 使 GetX
initialRoute: AppRoutes.login, // 使
initialBinding: InitialBinding(), //
getPages: AppPages.routes, //
);
},
);
}
}

Loading…
Cancel
Save