You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

256 lines
9.7 KiB

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:problem_check_system/modules/problem/controllers/problem_controller.dart';
import 'package:problem_check_system/data/models/problem_model.dart';
import 'package:problem_check_system/modules/problem/views/widgets/date_picker_button.dart';
import 'package:problem_check_system/modules/problem/views/widgets/problem_card.dart';
import 'package:problem_check_system/modules/problem/views/problem_form_page.dart';
class ProblemPage extends GetView<ProblemController> {
const ProblemPage({super.key});
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 0,
length: 2,
child: Scaffold(
body: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 812.h),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 375.w,
height: 83.5.h,
alignment: Alignment.bottomLeft,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Color(0xFF418CFC), Color(0xFF3DBFFC)],
),
),
child: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
color: const Color(0xfffff7f7),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
topRight: Radius.circular(60),
),
),
tabs: const [
Tab(text: '问题列表'),
Tab(text: '历史问题列表'),
],
labelStyle: TextStyle(
fontFamily: 'MyFont',
fontWeight: FontWeight.w800,
fontSize: 14.sp,
),
unselectedLabelStyle: TextStyle(
fontFamily: 'MyFont',
fontWeight: FontWeight.w800,
fontSize: 14.sp,
),
labelColor: Colors.black,
unselectedLabelColor: Colors.white,
),
),
Expanded(
child: TabBarView(
children: [
Column(
children: [
Container(
margin: EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [DatePickerButton(), DatePickerButton()],
),
),
Expanded(
child: Obx(() {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
// +1 是为了在列表末尾添加一个额外的“空”项
itemCount: controller.problems.length + 1,
itemBuilder: (context, index) {
// 如果是最后一个“空”项,返回一个 SizedBox
if (index == controller.problems.length) {
return SizedBox(height: 79.5.h);
}
// 否则,返回正常的列表项
final problem = controller.problems[index];
return _buildSwipeableProblemCard(
problem,
controller,
);
},
);
}),
),
],
),
Obx(() {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: controller.problems.length,
itemBuilder: (context, index) {
final problem = controller.problems[index];
return _buildSwipeableProblemCard(
problem,
controller,
viewType: ProblemCardViewType.checkbox,
);
},
);
}),
],
),
),
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: FloatingActionButton(
heroTag: "btn_add",
onPressed: () {
Get.to(() => ProblemFormPage());
},
shape: CircleBorder(),
backgroundColor: Colors.blue[300],
foregroundColor: Colors.white,
child: const Icon(Icons.add),
),
),
Positioned(
bottom: 56.h, // 设置距离底部100像素
right: 27.w, // 设置距离右侧16像素(通常的浮动按钮默认位置)
child: Obx(() {
final bool isOnline = controller.isOnline.value;
return FloatingActionButton(
heroTag: "btn_upload",
onPressed: isOnline
? () => controller.uploadAllUnuploaded()
: null,
foregroundColor: Colors.white,
backgroundColor: isOnline
? Colors.red[300]
: Colors.grey[400],
child: Icon(
isOnline
? Icons.file_upload_outlined
: Icons.cloud_off_outlined,
),
);
}),
),
],
),
),
);
}
Widget _buildSwipeableProblemCard(
Problem problem,
ProblemController controller, {
ProblemCardViewType viewType = ProblemCardViewType.buttons,
}) {
return Dismissible(
key: Key(problem.id ?? UniqueKey().toString()),
direction: DismissDirection.endToStart,
background: Container(
color: Colors.red,
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20.w),
child: Icon(Icons.delete, color: Colors.white, size: 30.sp),
),
confirmDismiss: (direction) async {
return await _showDeleteConfirmationDialog(problem);
},
onDismissed: (direction) {
controller.deleteProblem(problem);
Get.snackbar('成功', '问题已删除');
},
child: ProblemCard(problem, viewType: viewType),
);
}
Future<bool> _showDeleteConfirmationDialog(Problem problem) async {
return await Get.bottomSheet<bool>(
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: 16),
Text(
'确认删除',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text(
'确定要删除这个问题吗?此操作不可撤销。',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
),
SizedBox(height: 24),
ElevatedButton(
onPressed: () => Get.back(result: true),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
padding: EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
'删除',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
SizedBox(height: 8),
TextButton(
onPressed: () => Get.back(result: false),
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 16),
),
child: Text(
'取消',
style: TextStyle(color: Colors.grey[700], fontSize: 16),
),
),
SizedBox(height: 16),
],
),
),
),
isDismissible: false,
) ??
false;
}
}