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