48 changed files with 632 additions and 403 deletions
@ -1,5 +1,5 @@ |
|||||||
// image_metadata_model.dart |
// image_metadata_model.dart |
||||||
import 'package:problem_check_system/data/models/image_status.dart'; |
import 'package:problem_check_system/app/core/data/models/image_status.dart'; |
||||||
|
|
||||||
class ImageMetadata { |
class ImageMetadata { |
||||||
final String localPath; |
final String localPath; |
@ -1,7 +1,7 @@ |
|||||||
import 'dart:convert'; |
import 'dart:convert'; |
||||||
|
|
||||||
import 'package:problem_check_system/data/models/image_metadata_model.dart'; |
import 'package:problem_check_system/app/core/data/models/image_metadata_model.dart'; |
||||||
import 'package:problem_check_system/data/models/problem_sync_status.dart'; |
import 'package:problem_check_system/app/core/data/models/problem_sync_status.dart'; |
||||||
|
|
||||||
/// 问题的数据模型。 |
/// 问题的数据模型。 |
||||||
/// 用于表示系统中的一个具体问题,包含了问题的描述、位置、图片等信息。 |
/// 用于表示系统中的一个具体问题,包含了问题的描述、位置、图片等信息。 |
@ -1,7 +1,7 @@ |
|||||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||||
import 'package:problem_check_system/data/models/image_metadata_model.dart'; |
import 'package:problem_check_system/app/core/data/models/image_metadata_model.dart'; |
||||||
import 'package:problem_check_system/data/models/problem_model.dart'; |
import 'package:problem_check_system/app/core/data/models/problem_model.dart'; |
||||||
import 'package:problem_check_system/data/repositories/auth_repository.dart'; |
import 'package:problem_check_system/app/core/data/repositories/auth_repository.dart'; |
||||||
import 'package:uuid/uuid.dart'; |
import 'package:uuid/uuid.dart'; |
||||||
|
|
||||||
enum ProblemSyncStatus { |
enum ProblemSyncStatus { |
@ -1,10 +1,10 @@ |
|||||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||||
import 'package:get_storage/get_storage.dart'; |
import 'package:get_storage/get_storage.dart'; |
||||||
import 'package:problem_check_system/core/utils/constants/api_endpoints.dart'; |
import 'package:problem_check_system/app/core/utils/constants/api_endpoints.dart'; |
||||||
import 'package:problem_check_system/data/models/auth_model.dart'; |
import 'package:problem_check_system/app/core/data/models/auth_model.dart'; |
||||||
import 'package:problem_check_system/data/models/user/user.dart'; |
import 'package:problem_check_system/app/core/data/models/user/user.dart'; |
||||||
import 'package:problem_check_system/data/providers/network_status_service.dart'; |
import 'package:problem_check_system/app/core/data/services/network_status_service.dart'; |
||||||
import 'package:problem_check_system/data/providers/http_provider.dart'; |
import 'package:problem_check_system/app/core/data/services/http_provider.dart'; |
||||||
|
|
||||||
class AuthRepository extends GetxService { |
class AuthRepository extends GetxService { |
||||||
final HttpProvider httpProvider; |
final HttpProvider httpProvider; |
@ -0,0 +1,21 @@ |
|||||||
|
// lib/app/features/enterprise/presentation/bindings/enterprise_form_binding.dart |
||||||
|
|
||||||
|
import 'package:get/get.dart'; |
||||||
|
import 'package:problem_check_system/app/features/enterprise/data/model/enterprise_model.dart'; |
||||||
|
import 'package:problem_check_system/app/features/enterprise/presentation/controllers/enterprise_form_controller.dart'; // 确保导入您的模型 |
||||||
|
|
||||||
|
class EnterpriseFormBinding extends Bindings { |
||||||
|
@override |
||||||
|
void dependencies() { |
||||||
|
// 1. 尝试从路由参数中获取 Enterprise 对象。 |
||||||
|
// - 如果是修改模式,Get.arguments 会是您传入的 Enterprise 对象。 |
||||||
|
// - 如果是新增模式,Get.arguments 会是 null。 |
||||||
|
// - 使用 as Enterprise? 进行安全的类型转换。 |
||||||
|
final Enterprise? enterpriseToEdit = Get.arguments as Enterprise?; |
||||||
|
|
||||||
|
// 2. 将获取到的参数(可能为 null)传递给 Controller 的构造函数。 |
||||||
|
Get.lazyPut<EnterpriseFormController>( |
||||||
|
() => EnterpriseFormController(initialData: enterpriseToEdit), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:get/get.dart'; |
||||||
|
import 'package:problem_check_system/app/features/enterprise/data/model/enterprise_model.dart'; |
||||||
|
|
||||||
|
class EnterpriseFormController extends GetxController { |
||||||
|
// 通过构造函数接收可能存在的初始数据 |
||||||
|
final Enterprise? initialData; |
||||||
|
EnterpriseFormController({this.initialData}); |
||||||
|
|
||||||
|
// --- 状态管理 --- |
||||||
|
var isEditMode = false.obs; |
||||||
|
var pageTitle = '新增企业'.obs; |
||||||
|
|
||||||
|
// --- 表单控制器 --- |
||||||
|
final enterpriseNameController = TextEditingController(); |
||||||
|
final enterpriseAddressController = TextEditingController(); |
||||||
|
final contactPersonController = TextEditingController(); |
||||||
|
final contactPhoneController = TextEditingController(); |
||||||
|
final hazardSourceController = TextEditingController(); |
||||||
|
|
||||||
|
// 用于存储下拉选择框的值 |
||||||
|
final Rx<String?> selectedEnterpriseType = Rx<String?>(null); |
||||||
|
final Rx<String?> selectedEnterpriseScale = Rx<String?>(null); |
||||||
|
|
||||||
|
@override |
||||||
|
void onInit() { |
||||||
|
super.onInit(); |
||||||
|
// 判断是新增还是修改模式 |
||||||
|
if (initialData != null) { |
||||||
|
isEditMode.value = true; |
||||||
|
pageTitle.value = '修改信息'; |
||||||
|
// 用初始数据填充表单 |
||||||
|
enterpriseNameController.text = initialData!.companyName; |
||||||
|
// ... 初始化其他控制器 |
||||||
|
} else { |
||||||
|
isEditMode.value = false; |
||||||
|
pageTitle.value = '新增企业'; |
||||||
|
// 新增模式,表单为空 (或有默认值) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 提交表单的逻辑 |
||||||
|
void submitForm() { |
||||||
|
if (isEditMode.value) { |
||||||
|
_updateEnterprise(); |
||||||
|
} else { |
||||||
|
_createEnterprise(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void _createEnterprise() { |
||||||
|
print('执行新增逻辑...'); |
||||||
|
// 调用新增 API |
||||||
|
// Get.find<ApiService>().createEnterprise(...); |
||||||
|
Get.back(result: true); // 返回并通知列表刷新 |
||||||
|
} |
||||||
|
|
||||||
|
void _updateEnterprise() { |
||||||
|
print('执行修改逻辑, ID: ${initialData!.id}'); |
||||||
|
// 调用修改 API |
||||||
|
// Get.find<ApiService>().updateEnterprise(initialData!.id, ...); |
||||||
|
Get.back(result: true); // 返回并通知列表刷新 |
||||||
|
} |
||||||
|
|
||||||
|
@override |
||||||
|
void onClose() { |
||||||
|
enterpriseNameController.dispose(); |
||||||
|
enterpriseAddressController.dispose(); |
||||||
|
contactPersonController.dispose(); |
||||||
|
contactPhoneController.dispose(); |
||||||
|
hazardSourceController.dispose(); |
||||||
|
super.onClose(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,267 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:get/get.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
import 'package:problem_check_system/app/features/enterprise/presentation/controllers/enterprise_form_controller.dart'; |
||||||
|
|
||||||
|
// ------------------- 页面视图 (View) ------------------- |
||||||
|
// 使用 GetView 可以方便地访问控制器 |
||||||
|
class EnterpriseFormPage extends GetView<EnterpriseFormController> { |
||||||
|
const EnterpriseFormPage({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Scaffold( |
||||||
|
backgroundColor: const Color(0xFFF5F5F5), |
||||||
|
appBar: _buildAppBar(), |
||||||
|
body: SafeArea( |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: SingleChildScrollView( |
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), |
||||||
|
child: Column( |
||||||
|
children: [ |
||||||
|
_buildInfoSection( |
||||||
|
title: '必填信息', |
||||||
|
children: [ |
||||||
|
_buildTextField( |
||||||
|
label: '企业名称', |
||||||
|
hint: '达拉特旗', |
||||||
|
controller: controller.enterpriseNameController, |
||||||
|
isRequired: true, |
||||||
|
), |
||||||
|
_buildDropdownField( |
||||||
|
label: '企业类型', |
||||||
|
hint: '请选择企业类型', |
||||||
|
isRequired: true, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
SizedBox(height: 12.h), |
||||||
|
_buildInfoSection( |
||||||
|
title: '选填信息', |
||||||
|
children: [ |
||||||
|
_buildTextField( |
||||||
|
label: '企业地址', |
||||||
|
hint: '请输入企业地址', |
||||||
|
controller: controller.enterpriseAddressController, |
||||||
|
), |
||||||
|
_buildDropdownField(label: '企业规模', hint: '请选择企业规模'), |
||||||
|
_buildTextField( |
||||||
|
label: '联系人', |
||||||
|
hint: '请输入联系人姓名', |
||||||
|
controller: controller.contactPersonController, |
||||||
|
), |
||||||
|
_buildTextField( |
||||||
|
label: '联系电话', |
||||||
|
hint: '请输入联系电话', |
||||||
|
controller: controller.contactPhoneController, |
||||||
|
), |
||||||
|
_buildTextField( |
||||||
|
label: '有无重大危险源;重大危险源情况', |
||||||
|
hint: '请输入有无重大危险源;重大危险源情况', |
||||||
|
controller: controller.hazardSourceController, |
||||||
|
hasDivider: false, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
_buildBottomButtons(), |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 将 controller 传进来以获取动态标题 |
||||||
|
PreferredSizeWidget _buildAppBar() { |
||||||
|
return PreferredSize( |
||||||
|
preferredSize: Size.fromHeight(56.h), |
||||||
|
child: Container( |
||||||
|
decoration: const BoxDecoration( |
||||||
|
// ... 渐变色 |
||||||
|
), |
||||||
|
child: AppBar( |
||||||
|
// ... 其他 AppBar 属性 |
||||||
|
// 使用 Obx 来监听 pageTitle 的变化 |
||||||
|
title: Obx( |
||||||
|
() => Text( |
||||||
|
controller.pageTitle.value, |
||||||
|
style: TextStyle( |
||||||
|
fontSize: 18.sp, |
||||||
|
color: Colors.white, |
||||||
|
fontWeight: FontWeight.bold, |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
centerTitle: true, |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 构建信息区块 (例如 "必填信息") |
||||||
|
Widget _buildInfoSection({ |
||||||
|
required String title, |
||||||
|
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: [ |
||||||
|
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), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
SizedBox(height: 10.h), |
||||||
|
...children, |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 构建带标签的文本输入框 |
||||||
|
Widget _buildTextField({ |
||||||
|
required String label, |
||||||
|
required String hint, |
||||||
|
required TextEditingController controller, |
||||||
|
bool isRequired = false, |
||||||
|
bool hasDivider = true, |
||||||
|
}) { |
||||||
|
return Column( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||||
|
child: _buildLabel(label, isRequired), |
||||||
|
), |
||||||
|
TextFormField( |
||||||
|
controller: controller, |
||||||
|
decoration: InputDecoration( |
||||||
|
hintText: hint, |
||||||
|
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 14.sp), |
||||||
|
border: InputBorder.none, |
||||||
|
isDense: true, |
||||||
|
contentPadding: EdgeInsets.zero, |
||||||
|
), |
||||||
|
style: TextStyle(fontSize: 14.sp, color: Colors.black87), |
||||||
|
), |
||||||
|
if (hasDivider) const Divider(height: 1, color: Color(0xFFF0F0F0)), |
||||||
|
], |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 构建下拉选择框样式 |
||||||
|
Widget _buildDropdownField({ |
||||||
|
required String label, |
||||||
|
required String hint, |
||||||
|
bool isRequired = false, |
||||||
|
}) { |
||||||
|
return Column( |
||||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||||
|
children: [ |
||||||
|
Padding( |
||||||
|
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||||
|
child: _buildLabel(label, isRequired), |
||||||
|
), |
||||||
|
GestureDetector( |
||||||
|
onTap: () { |
||||||
|
// 在此处理下拉框点击事件,例如弹出一个选择列表 |
||||||
|
Get.snackbar('提示', '这是一个下拉选择框'); |
||||||
|
}, |
||||||
|
child: Container( |
||||||
|
color: Colors.transparent, // 使整个区域可点击 |
||||||
|
child: Row( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||||
|
children: [ |
||||||
|
Text( |
||||||
|
hint, |
||||||
|
style: TextStyle(color: Colors.grey[400], fontSize: 14.sp), |
||||||
|
), |
||||||
|
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), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 构建底部的取消和确定按钮 |
||||||
|
Widget _buildBottomButtons() { |
||||||
|
return Container( |
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), |
||||||
|
color: Colors.white, |
||||||
|
child: Row( |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: OutlinedButton( |
||||||
|
onPressed: () => Get.back(), |
||||||
|
style: OutlinedButton.styleFrom( |
||||||
|
padding: EdgeInsets.symmetric(vertical: 12.h), |
||||||
|
side: BorderSide(color: Colors.grey[300]!), |
||||||
|
shape: RoundedRectangleBorder( |
||||||
|
borderRadius: BorderRadius.circular(8.r), |
||||||
|
), |
||||||
|
), |
||||||
|
child: Text( |
||||||
|
'取消', |
||||||
|
style: TextStyle(fontSize: 16.sp, color: Colors.black54), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
SizedBox(width: 16.w), |
||||||
|
Expanded( |
||||||
|
child: ElevatedButton( |
||||||
|
onPressed: controller.submitForm, |
||||||
|
style: ElevatedButton.styleFrom( |
||||||
|
backgroundColor: const Color(0xFF2B8CFF), |
||||||
|
padding: EdgeInsets.symmetric(vertical: 12.h), |
||||||
|
elevation: 0, |
||||||
|
shape: RoundedRectangleBorder( |
||||||
|
borderRadius: BorderRadius.circular(8.r), |
||||||
|
), |
||||||
|
), |
||||||
|
child: Text( |
||||||
|
'确定', |
||||||
|
style: TextStyle(fontSize: 16.sp, color: Colors.white), |
||||||
|
), |
||||||
|
), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
import 'package:flutter/material.dart'; |
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||||
|
import 'package:get/get.dart'; |
||||||
|
import 'package:problem_check_system/app/features/enterprise/presentation/widgets/enterprise_card.dart'; |
||||||
|
import '../controllers/enterprise_list_controller.dart'; |
||||||
|
|
||||||
|
class EnterpriseListPage extends GetView<EnterpriseListController> { |
||||||
|
const EnterpriseListPage({super.key}); |
||||||
|
|
||||||
|
@override |
||||||
|
Widget build(BuildContext context) { |
||||||
|
return Scaffold( |
||||||
|
appBar: AppBar( |
||||||
|
title: Text( |
||||||
|
'企业列表', |
||||||
|
style: TextStyle( |
||||||
|
fontWeight: FontWeight.bold, |
||||||
|
fontFamily: 'MyFont', |
||||||
|
fontSize: 18.sp, |
||||||
|
color: Colors.white, |
||||||
|
), |
||||||
|
), |
||||||
|
backgroundColor: const Color(0xFF3B82F6), |
||||||
|
elevation: 0, |
||||||
|
centerTitle: true, |
||||||
|
actions: [ |
||||||
|
IconButton( |
||||||
|
icon: Icon(Icons.add, color: Colors.white), // 使用 .sp |
||||||
|
onPressed: () { |
||||||
|
controller.navigateToAddForm(); |
||||||
|
}, |
||||||
|
), |
||||||
|
IconButton( |
||||||
|
icon: Icon(Icons.upload, color: Colors.pink[300]), // 使用 .sp |
||||||
|
onPressed: () { |
||||||
|
controller.navigateToUploadPage(); |
||||||
|
}, |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
body: Stack( |
||||||
|
children: [ |
||||||
|
Column( |
||||||
|
children: [ |
||||||
|
_buildFilterBar(), |
||||||
|
// 使用 Obx 包裹需要响应式更新的 Widget |
||||||
|
Expanded( |
||||||
|
child: Obx(() { |
||||||
|
if (controller.enterpriseList.isEmpty) { |
||||||
|
return const Center(child: CircularProgressIndicator()); |
||||||
|
} |
||||||
|
return ListView.builder( |
||||||
|
padding: EdgeInsets.symmetric( |
||||||
|
horizontal: 16.w, // 使用 .w |
||||||
|
vertical: 8.h, // 使用 .h |
||||||
|
), |
||||||
|
itemCount: controller.enterpriseList.length, |
||||||
|
itemBuilder: (context, index) { |
||||||
|
final enterprise = controller.enterpriseList[index]; |
||||||
|
return Padding( |
||||||
|
padding: EdgeInsets.only(bottom: 12.h), // 使用 .h |
||||||
|
// child: _EnterpriseCard(enterprise: enterprise), |
||||||
|
child: EnterpriseCard( |
||||||
|
enterprise: enterprise, |
||||||
|
onEdit: () { |
||||||
|
controller.navigateToEditForm(enterprise); |
||||||
|
}, |
||||||
|
onViewProblems: () {}, |
||||||
|
), |
||||||
|
); |
||||||
|
}, |
||||||
|
); |
||||||
|
}), |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Widget _buildFilterBar() { |
||||||
|
return Container( |
||||||
|
padding: EdgeInsets.fromLTRB(16.w, 12.h, 16.w, 12.h), // 使用 .w 和 .h |
||||||
|
color: Colors.white, |
||||||
|
child: Row( |
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||||
|
children: [ |
||||||
|
Expanded( |
||||||
|
child: Row( |
||||||
|
children: [ |
||||||
|
const Text('企业名称', style: TextStyle(color: Colors.black54)), |
||||||
|
SizedBox(width: 4.w), // 使用 .w |
||||||
|
Icon( |
||||||
|
Icons.search, |
||||||
|
size: 20.sp, |
||||||
|
color: Colors.black54, |
||||||
|
), // 使用 .sp |
||||||
|
], |
||||||
|
), |
||||||
|
), |
||||||
|
_buildDropdown('选择日期'), |
||||||
|
_buildDropdown('近一周'), |
||||||
|
_buildDropdown('类型'), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Widget _buildDropdown(String text) { |
||||||
|
return Padding( |
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.w), // 使用 .w |
||||||
|
child: Row( |
||||||
|
children: [ |
||||||
|
Text(text, style: const TextStyle(color: Colors.black54)), |
||||||
|
const Icon(Icons.arrow_drop_down, color: Colors.black54), |
||||||
|
], |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -1,280 +0,0 @@ |
|||||||
import 'package:flutter/material.dart'; |
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
||||||
import 'package:get/get.dart'; |
|
||||||
import 'package:problem_check_system/modules/enterprise_list/model/enterprise_model.dart'; |
|
||||||
import 'package:problem_check_system/modules/enterprise_list/widgets/enterprise_card.dart'; |
|
||||||
import 'enterprise_list_controller.dart'; |
|
||||||
|
|
||||||
class EnterpriseListPage extends GetView<EnterpriseListController> { |
|
||||||
const EnterpriseListPage({super.key}); |
|
||||||
|
|
||||||
@override |
|
||||||
Widget build(BuildContext context) { |
|
||||||
return Scaffold( |
|
||||||
appBar: AppBar( |
|
||||||
title: Text( |
|
||||||
'企业列表', |
|
||||||
style: TextStyle( |
|
||||||
fontWeight: FontWeight.bold, |
|
||||||
fontFamily: 'MyFont', |
|
||||||
fontSize: 18.sp, |
|
||||||
color: Colors.white, |
|
||||||
), |
|
||||||
), |
|
||||||
backgroundColor: const Color(0xFF3B82F6), |
|
||||||
elevation: 0, |
|
||||||
centerTitle: true, |
|
||||||
actions: [ |
|
||||||
IconButton( |
|
||||||
icon: Icon(Icons.add, color: Colors.white), // 使用 .sp |
|
||||||
onPressed: () { |
|
||||||
// 处理筛选按钮点击事件 |
|
||||||
}, |
|
||||||
), |
|
||||||
IconButton( |
|
||||||
icon: Icon(Icons.upload, color: Colors.pink[300]), // 使用 .sp |
|
||||||
onPressed: () { |
|
||||||
// 处理筛选按钮点击事件 |
|
||||||
}, |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
body: Stack( |
|
||||||
children: [ |
|
||||||
Column( |
|
||||||
children: [ |
|
||||||
_buildFilterBar(), |
|
||||||
// 使用 Obx 包裹需要响应式更新的 Widget |
|
||||||
Expanded( |
|
||||||
child: Obx(() { |
|
||||||
if (controller.enterpriseList.isEmpty) { |
|
||||||
return const Center(child: CircularProgressIndicator()); |
|
||||||
} |
|
||||||
return ListView.builder( |
|
||||||
padding: EdgeInsets.symmetric( |
|
||||||
horizontal: 16.w, // 使用 .w |
|
||||||
vertical: 8.h, // 使用 .h |
|
||||||
), |
|
||||||
itemCount: controller.enterpriseList.length, |
|
||||||
itemBuilder: (context, index) { |
|
||||||
final enterprise = controller.enterpriseList[index]; |
|
||||||
return Padding( |
|
||||||
padding: EdgeInsets.only(bottom: 12.h), // 使用 .h |
|
||||||
// child: _EnterpriseCard(enterprise: enterprise), |
|
||||||
child: EnterpriseCard(), |
|
||||||
); |
|
||||||
}, |
|
||||||
); |
|
||||||
}), |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
Widget _buildFilterBar() { |
|
||||||
return Container( |
|
||||||
padding: EdgeInsets.fromLTRB(16.w, 12.h, 16.w, 12.h), // 使用 .w 和 .h |
|
||||||
color: Colors.white, |
|
||||||
child: Row( |
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
||||||
children: [ |
|
||||||
Expanded( |
|
||||||
child: Row( |
|
||||||
children: [ |
|
||||||
const Text('企业名称', style: TextStyle(color: Colors.black54)), |
|
||||||
SizedBox(width: 4.w), // 使用 .w |
|
||||||
Icon( |
|
||||||
Icons.search, |
|
||||||
size: 20.sp, |
|
||||||
color: Colors.black54, |
|
||||||
), // 使用 .sp |
|
||||||
], |
|
||||||
), |
|
||||||
), |
|
||||||
_buildDropdown('选择日期'), |
|
||||||
_buildDropdown('近一周'), |
|
||||||
_buildDropdown('类型'), |
|
||||||
], |
|
||||||
), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
Widget _buildDropdown(String text) { |
|
||||||
return Padding( |
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8.w), // 使用 .w |
|
||||||
child: Row( |
|
||||||
children: [ |
|
||||||
Text(text, style: const TextStyle(color: Colors.black54)), |
|
||||||
const Icon(Icons.arrow_drop_down, color: Colors.black54), |
|
||||||
], |
|
||||||
), |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
class _EnterpriseCard extends StatelessWidget { |
|
||||||
final Enterprise enterprise; |
|
||||||
const _EnterpriseCard({required this.enterprise}); |
|
||||||
|
|
||||||
@override |
|
||||||
Widget build(BuildContext context) { |
|
||||||
return Container( |
|
||||||
padding: EdgeInsets.all(16.r), // 使用 .r 保证四边 padding 比例一致 |
|
||||||
decoration: BoxDecoration( |
|
||||||
color: Colors.white, |
|
||||||
borderRadius: BorderRadius.circular(8.r), // 使用 .r |
|
||||||
), |
|
||||||
child: Column( |
|
||||||
crossAxisAlignment: CrossAxisAlignment.start, |
|
||||||
children: [ |
|
||||||
Row( |
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
||||||
crossAxisAlignment: CrossAxisAlignment.start, |
|
||||||
children: [ |
|
||||||
Column( |
|
||||||
crossAxisAlignment: CrossAxisAlignment.start, |
|
||||||
children: [ |
|
||||||
Text( |
|
||||||
'企业名称', |
|
||||||
style: TextStyle(fontSize: 9.sp, color: Colors.grey), |
|
||||||
), |
|
||||||
SizedBox(height: 4.h), // 使用 .h |
|
||||||
Text( |
|
||||||
enterprise.companyName, |
|
||||||
style: TextStyle( |
|
||||||
fontSize: 12.5.sp, |
|
||||||
fontWeight: FontWeight.w500, |
|
||||||
), |
|
||||||
maxLines: 1, |
|
||||||
overflow: TextOverflow.ellipsis, |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
|
|
||||||
Column( |
|
||||||
crossAxisAlignment: CrossAxisAlignment.start, |
|
||||||
children: [ |
|
||||||
Text( |
|
||||||
'企业类型', |
|
||||||
style: TextStyle(fontSize: 9.sp, color: Colors.grey), |
|
||||||
), |
|
||||||
SizedBox(height: 4.h), // 使用 .h |
|
||||||
Text( |
|
||||||
enterprise.companyType, |
|
||||||
maxLines: 1, |
|
||||||
overflow: TextOverflow.ellipsis, |
|
||||||
style: TextStyle( |
|
||||||
fontSize: 12.5.sp, |
|
||||||
fontWeight: FontWeight.w500, |
|
||||||
), |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
|
|
||||||
Container( |
|
||||||
padding: EdgeInsets.symmetric( |
|
||||||
horizontal: 5.w, |
|
||||||
vertical: 2.h, |
|
||||||
), // 使用 .w 和 .h |
|
||||||
decoration: BoxDecoration( |
|
||||||
// color: Colors.orange[100], |
|
||||||
borderRadius: BorderRadius.circular(10.r), // 使用 .r |
|
||||||
border: Border.all(color: Colors.red), |
|
||||||
), |
|
||||||
child: Text( |
|
||||||
'信息未上传', |
|
||||||
maxLines: 1, |
|
||||||
style: TextStyle(fontSize: 9.sp, color: Colors.red), // 使用 .sp |
|
||||||
), |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
SizedBox(height: 16.h), // 使用 .h |
|
||||||
Row( |
|
||||||
children: [ |
|
||||||
Icon( |
|
||||||
Icons.description, |
|
||||||
size: 16.sp, |
|
||||||
color: Colors.grey, |
|
||||||
), // 使用 .sp |
|
||||||
SizedBox(width: 4.w), // 使用 .w |
|
||||||
Text( |
|
||||||
'问题总数: ${enterprise.totalIssues}', |
|
||||||
style: TextStyle(fontSize: 12.sp, color: Colors.grey), // 使用 .sp |
|
||||||
), |
|
||||||
SizedBox(width: 16.w), // 使用 .w |
|
||||||
Icon( |
|
||||||
Icons.access_time, |
|
||||||
size: 16.sp, |
|
||||||
color: Colors.grey, |
|
||||||
), // 使用 .sp |
|
||||||
SizedBox(width: 4.w), // 使用 .w |
|
||||||
Text( |
|
||||||
'创建时间: ${enterprise.creationTime}', |
|
||||||
style: TextStyle(fontSize: 12.sp, color: Colors.grey), // 使用 .sp |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
// SizedBox(height: 16.h), // 使用 .h |
|
||||||
Row( |
|
||||||
children: [ |
|
||||||
_buildTag('已上传 ${enterprise.uploaded}', Colors.blue), |
|
||||||
SizedBox(width: 8.w), // 使用 .w |
|
||||||
_buildTag('未上传 ${enterprise.notUploaded}', Colors.red), |
|
||||||
const Spacer(), |
|
||||||
Icon(Icons.edit, size: 16.sp, color: Colors.grey), // 使用 .sp |
|
||||||
SizedBox(width: 4.w), // 使用 .w |
|
||||||
Text( |
|
||||||
'修改信息', |
|
||||||
style: TextStyle( |
|
||||||
fontSize: 9.5.sp, |
|
||||||
color: Colors.grey, |
|
||||||
), // 使用 .sp |
|
||||||
), |
|
||||||
SizedBox(width: 16.w), // 使用 .w |
|
||||||
ElevatedButton( |
|
||||||
onPressed: () {}, |
|
||||||
style: ElevatedButton.styleFrom( |
|
||||||
backgroundColor: const Color(0xFF3B82F6), |
|
||||||
|
|
||||||
shape: RoundedRectangleBorder( |
|
||||||
borderRadius: BorderRadius.circular(4.r), // 使用 .r |
|
||||||
), |
|
||||||
// padding: EdgeInsets.symmetric( |
|
||||||
// horizontal: 16.w, // 使用 .w |
|
||||||
// vertical: 8.h, // 使用 .h |
|
||||||
// ), |
|
||||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, |
|
||||||
), |
|
||||||
child: const Text( |
|
||||||
'查看问题', |
|
||||||
style: TextStyle(color: Colors.white), |
|
||||||
), |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
], |
|
||||||
), |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
Widget _buildTag(String text, Color color) { |
|
||||||
return Container( |
|
||||||
padding: EdgeInsets.symmetric( |
|
||||||
horizontal: 6.w, |
|
||||||
vertical: 2.h, |
|
||||||
), // 使用 .w 和 .h |
|
||||||
decoration: BoxDecoration( |
|
||||||
color: color.withOpacity(0.1), |
|
||||||
borderRadius: BorderRadius.circular(4.r), // 使用 .r |
|
||||||
), |
|
||||||
child: Text( |
|
||||||
text, |
|
||||||
style: TextStyle(color: color, fontSize: 8.5.sp), |
|
||||||
), // 使用 .sp |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue