Browse Source

feat : 新增问题选择企业

dev
徐振升 2 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. 79
      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);
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<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/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/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/presentation/controllers/problem_form_controller.dart';
@ -51,15 +51,15 @@ class ProblemFormBinding extends Bindings {
),
);
Get.put<GetEnterpriseListUsecase>(
GetEnterpriseListUsecase(repository: Get.find<EnterpriseRepository>()),
Get.put<GetEnterprisesUsecase>(
GetEnterprisesUsecase(repository: Get.find<EnterpriseRepository>()),
);
Get.lazyPut<ProblemFormController>(
() => ProblemFormController(
problem: problem,
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/image_status.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/usecases/get_enterprise_list_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprises_usecase.dart';
import 'dart:io';
import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart';
import 'package:uuid/uuid.dart';
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;
late Map<String, dynamic> bindInfo;
@ -35,13 +40,13 @@ class ProblemFormController extends GetxController {
final TextEditingController descriptionController = TextEditingController();
final TextEditingController locationController = TextEditingController();
final RxList<XFile> selectedImages = <XFile>[].obs;
final GetEnterpriseListUsecase getEnterpriseListUsecase;
final GetEnterprisesUsecase getEnterprisesUsecase;
// 使便
ProblemFormController({
this.problem,
this.formMode = FormMode.view,
required this.getEnterpriseListUsecase,
required this.getEnterprisesUsecase,
}) {
if (problem != null) {
if (problem!.bindData != null) {
@ -62,6 +67,7 @@ class ProblemFormController extends GetxController {
void onInit() {
super.onInit();
updatePageTitle();
_fetchEnterprises();
}
@override
@ -85,9 +91,27 @@ class ProblemFormController extends GetxController {
}
}
//
Future<List<EnterpriseListItem>> getAllEnterprises() async {
return await getEnterpriseListUsecase();
// 4. :
Future<void> _fetchEnterprises() async {
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

79
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:image_picker/image_picker.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';
class ProblemFormPage extends GetView<ProblemFormController> {
@ -18,7 +19,27 @@ class ProblemFormPage extends GetView<ProblemFormController> {
leadingVisible: true,
),
body: SafeArea(
child: Column(
child: Obx(() {
// 1.
if (controller.isLoading.value) {
return const Center(child: CircularProgressIndicator());
}
// 2.
if (controller.error.isNotEmpty) {
return Center(
child: Text(
controller.error.value,
style: const TextStyle(color: Colors.red),
),
);
}
// 3.
if (controller.enterpriseList.isEmpty) {
return const Center(child: Text('没有可用的企业'));
}
return Column(
children: [
Expanded(
child: SingleChildScrollView(
@ -84,7 +105,8 @@ class ProblemFormPage extends GetView<ProblemFormController> {
//
if (!controller.isReadOnly) _bottomButton(),
],
),
);
}),
),
);
}
@ -436,7 +458,29 @@ class ProblemFormPage extends GetView<ProblemFormController> {
const SizedBox(height: 20.0),
// --- 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/services.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: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';
import 'package:problem_check_system/app/app.dart';
void main() async {
// Flutter Binding
@ -23,81 +19,3 @@ void main() async {
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