11 changed files with 382 additions and 293 deletions
@ -0,0 +1,10 @@
|
||||
import 'package:get/get.dart'; |
||||
import 'package:problem_check_system/app/features/enterprise/presentation/controllers/enterprise_form_controller.dart'; |
||||
|
||||
class EnterpriseInfoBinding extends Bindings { |
||||
@override |
||||
void dependencies() { |
||||
// 2. 将获取到的参数(可能为 null)传递给 Controller 的构造函数。 |
||||
Get.lazyPut<EnterpriseFormController>(() => EnterpriseFormController()); |
||||
} |
||||
} |
||||
@ -0,0 +1,8 @@
|
||||
import 'package:get/get.dart'; |
||||
import 'package:problem_check_system/app/features/enterprise/presentation/controllers/enterprise_form_controller.dart'; |
||||
|
||||
class EnterpriseInfoController extends GetxController { |
||||
EnterpriseInfoController({required this.enterpriseFormController}); |
||||
|
||||
final EnterpriseFormController enterpriseFormController; |
||||
} |
||||
@ -0,0 +1,257 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:get/get.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:problem_check_system/app/core/models/company_enum.dart'; |
||||
import 'package:problem_check_system/app/features/enterprise/presentation/controllers/enterprise_form_controller.dart'; |
||||
|
||||
// 这是一个可复用的 "视图" 组件,不包含 Scaffold |
||||
class EnterpriseFormView extends GetView<EnterpriseFormController> { |
||||
const EnterpriseFormView({super.key}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
// 根 Widget 是 Form,包裹着可滚动的内容 |
||||
return Form( |
||||
key: controller.formKey, |
||||
child: SingleChildScrollView( |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), |
||||
child: Column( |
||||
children: [ |
||||
// --- 这里是所有表单内容 --- |
||||
buildTitleSection(title: '必填信息'), |
||||
SizedBox(height: 12.h), |
||||
_buildInfoSection( |
||||
children: [ |
||||
_buildTextField( |
||||
label: '企业名称', |
||||
hint: '达拉特旗', |
||||
textController: controller.enterpriseNameController, |
||||
validator: (value) { |
||||
if (value == null || value.isEmpty) { |
||||
return '企业名称不能为空'; |
||||
} |
||||
return null; |
||||
}, |
||||
isRequired: true, |
||||
), |
||||
_buildCompanyTypeDropdown(), |
||||
], |
||||
), |
||||
SizedBox(height: 12.h), |
||||
buildTitleSection(title: '选填信息'), |
||||
SizedBox(height: 12.h), |
||||
_buildInfoSection( |
||||
children: [ |
||||
_buildTextField( |
||||
label: '企业地址', |
||||
hint: '请输入企业地址', |
||||
textController: controller.enterpriseAddressController, |
||||
), |
||||
_buildCompanyScopeDropdown(), |
||||
_buildTextField( |
||||
label: '联系人', |
||||
hint: '请输入联系人姓名', |
||||
textController: controller.contactPersonController, |
||||
), |
||||
_buildTextField( |
||||
label: '联系电话', |
||||
hint: '请输入联系电话', |
||||
textController: controller.contactPhoneController, |
||||
), |
||||
_buildTextField( |
||||
label: '有无重大危险源;重大危险源情况', |
||||
hint: '请输入有无重大危险源;重大危险源情况', |
||||
textController: controller.hazardSourceController, |
||||
hasDivider: false, |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
// --- 所有构建UI的辅助方法都移到这里 --- |
||||
Widget buildTitleSection({required String title}) { |
||||
return Row( |
||||
children: [ |
||||
Container(width: 4.w, height: 16.h, color: Colors.blue), |
||||
SizedBox(width: 8.w), |
||||
Text( |
||||
title, |
||||
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
|
||||
// 构建信息区块 (例如 "必填信息") |
||||
Widget _buildInfoSection({required List<Widget> children}) { |
||||
return Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(8.r), |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [...children], |
||||
), |
||||
); |
||||
} |
||||
|
||||
// 构建带标签的文本输入框 |
||||
Widget _buildTextField({ |
||||
required String label, |
||||
required String hint, |
||||
required TextEditingController textController, |
||||
bool isRequired = false, |
||||
bool hasDivider = true, |
||||
String? Function(String?)? validator, |
||||
}) { |
||||
return Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: _buildLabel(label, isRequired), |
||||
), |
||||
TextFormField( |
||||
controller: textController, |
||||
readOnly: controller.isReadOnly, |
||||
validator: validator, |
||||
decoration: InputDecoration( |
||||
hintText: hint, |
||||
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 14.sp), |
||||
border: InputBorder.none, |
||||
isDense: true, |
||||
contentPadding: EdgeInsets.zero, |
||||
enabledBorder: controller.isReadOnly ? InputBorder.none : null, |
||||
focusedBorder: controller.isReadOnly ? InputBorder.none : null, |
||||
), |
||||
style: TextStyle(fontSize: 14.sp, color: Colors.black87), |
||||
), |
||||
if (hasDivider) const Divider(height: 1, color: Color(0xFFF0F0F0)), |
||||
], |
||||
); |
||||
} |
||||
|
||||
// 构建下拉选择框样式 |
||||
// [新] 构建企业类型下拉框 |
||||
Widget _buildCompanyTypeDropdown() { |
||||
return Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: _buildLabel('企业类型', true), // isRequired = true |
||||
), |
||||
// 使用 Obx 监听 controller 中 selectedType 的变化 |
||||
Obx( |
||||
() => DropdownButtonFormField<CompanyType>( |
||||
initialValue: controller.selectedType.value, |
||||
validator: (value) { |
||||
if (value == null) { |
||||
return '请选择企业类型'; |
||||
} |
||||
return null; |
||||
}, |
||||
hint: Text( |
||||
'请选择企业类型', |
||||
style: TextStyle(color: Colors.grey[400], fontSize: 14.sp), |
||||
), |
||||
isExpanded: true, // 让下拉菜单撑满宽度 |
||||
decoration: const InputDecoration( |
||||
border: InputBorder.none, |
||||
isDense: true, |
||||
contentPadding: EdgeInsets.zero, |
||||
), |
||||
items: CompanyType.values.map((CompanyType type) { |
||||
return DropdownMenuItem<CompanyType>( |
||||
value: type, |
||||
child: Text( |
||||
type.displayText, |
||||
style: TextStyle(fontSize: 14.sp), |
||||
), |
||||
); |
||||
}).toList(), |
||||
onChanged: controller.isReadOnly |
||||
? null // 设置为 null 即可禁用 |
||||
: (CompanyType? newValue) { |
||||
controller.selectedType.value = newValue; |
||||
}, |
||||
// 自定义下拉箭头图标 |
||||
icon: controller.isReadOnly |
||||
? const SizedBox.shrink() |
||||
: const Icon(Icons.arrow_drop_down, color: Colors.grey), |
||||
), |
||||
), |
||||
const Divider(height: 1, color: Color(0xFFF0F0F0)), |
||||
], |
||||
); |
||||
} |
||||
|
||||
// [新] 构建企业规模下拉框 |
||||
Widget _buildCompanyScopeDropdown() { |
||||
return Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: _buildLabel('企业规模', false), // isRequired = false |
||||
), |
||||
Obx( |
||||
() => DropdownButtonFormField<CompanyScope>( |
||||
initialValue: controller.selectedScope.value, |
||||
hint: Text( |
||||
'请选择企业规模', |
||||
style: TextStyle(color: Colors.grey[400], fontSize: 14.sp), |
||||
), |
||||
isExpanded: true, |
||||
decoration: const InputDecoration( |
||||
border: InputBorder.none, |
||||
isDense: true, |
||||
contentPadding: EdgeInsets.zero, |
||||
), |
||||
items: CompanyScope.values.map((CompanyScope scope) { |
||||
return DropdownMenuItem<CompanyScope>( |
||||
value: scope, |
||||
child: Text( |
||||
scope.displayText, |
||||
style: TextStyle(fontSize: 14.sp), |
||||
), |
||||
); |
||||
}).toList(), |
||||
onChanged: controller.isReadOnly |
||||
? null // 设置为 null 即可禁用 |
||||
: (CompanyScope? newValue) { |
||||
controller.selectedScope.value = newValue; |
||||
}, |
||||
icon: controller.isReadOnly |
||||
? const SizedBox.shrink() |
||||
: const Icon(Icons.arrow_drop_down, color: Colors.grey), |
||||
), |
||||
), |
||||
const Divider(height: 1, color: Color(0xFFF0F0F0)), |
||||
], |
||||
); |
||||
} |
||||
|
||||
// 构建字段标签 (带红色星号) |
||||
Widget _buildLabel(String label, bool isRequired) { |
||||
return RichText( |
||||
text: TextSpan( |
||||
style: TextStyle(fontSize: 14.sp, color: Colors.black87), |
||||
children: [ |
||||
if (isRequired) |
||||
const TextSpan( |
||||
text: '* ', |
||||
style: TextStyle(color: Colors.red), |
||||
), |
||||
TextSpan(text: label), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue