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.

349 lines
11 KiB

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:problem_check_system/controllers/add_problem_controller.dart';
class AddProblemPage extends StatelessWidget {
AddProblemPage({super.key});
final AddProblemController controller = Get.put(AddProblemController());
// 显示底部选择器的方法
void _showImageSourceBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16.r)),
),
builder: (BuildContext context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 16.h),
Text(
'选择图片来源',
style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.bold),
),
SizedBox(height: 16.h),
Divider(height: 1.h),
ListTile(
leading: Icon(Icons.camera_alt, color: Colors.blue),
title: Text('拍照'),
onTap: () {
Navigator.pop(context);
controller.pickImage(ImageSource.camera);
},
),
Divider(height: 1.h),
ListTile(
leading: Icon(Icons.photo_library, color: Colors.blue),
title: Text('从相册选择'),
onTap: () {
Navigator.pop(context);
controller.pickImage(ImageSource.gallery);
},
),
Divider(height: 1.h),
ListTile(
leading: Icon(Icons.cancel, color: Colors.grey),
title: Text('取消', style: TextStyle(color: Colors.grey)),
onTap: () => Navigator.pop(context),
),
SizedBox(height: 8.h),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF418CFC), Color(0xFF3DBFFC)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new_rounded),
color: Colors.white,
onPressed: () {
Navigator.pop(context);
},
),
title: const Text('新增问题', style: TextStyle(color: Colors.white)),
centerTitle: true,
backgroundColor: Colors.transparent,
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Card(
margin: EdgeInsets.all(17.w),
child: Column(
children: [
ListTile(
title: const Text(
'问题描述',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
subtitle: TextField(
maxLines: null,
controller: controller.descriptionController,
decoration: const InputDecoration(
hintText: '请输入问题描述',
border: InputBorder.none,
),
),
),
],
),
),
Card(
margin: EdgeInsets.all(17.w),
child: Column(
children: [
ListTile(
title: const Text(
'所在位置',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
subtitle: TextField(
maxLines: null,
controller: controller.locationController,
decoration: const InputDecoration(
hintText: '请输入问题所在位置',
border: InputBorder.none,
),
),
),
],
),
),
Card(
margin: EdgeInsets.all(17.w),
child: Column(
children: [
ListTile(
title: const Text(
'问题图片',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8.h),
_buildImageGridWithAddButton(context),
],
),
),
],
),
),
],
),
),
),
_bottomButton(),
],
),
);
}
Widget _buildImageGridWithAddButton(BuildContext context) {
return Obx(() {
// 计算总项目数(图片数 + 添加按钮)
int totalItems = controller.selectedImages.length + 1;
return GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 8.w,
mainAxisSpacing: 8.h,
childAspectRatio: 1,
),
itemCount: totalItems,
itemBuilder: (context, index) {
// 如果是最后一个项目,显示添加按钮
if (index == controller.selectedImages.length) {
return _buildAddImageButton(context);
}
// 否则显示图片
return _buildImageItem(index);
},
);
});
}
Widget _buildAddImageButton(BuildContext context) {
return InkWell(
onTap: () => _showImageSourceBottomSheet(context),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300, width: 1),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.add_photo_alternate,
size: 24.sp,
color: Colors.grey.shade600,
),
SizedBox(height: 4.h),
Text(
'添加图片',
style: TextStyle(color: Colors.grey.shade600, fontSize: 12.sp),
),
],
),
),
);
}
Widget _buildImageItem(int index) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade300),
),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.file(
File(controller.selectedImages[index].path),
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
Positioned(
top: 0,
right: 0,
child: GestureDetector(
onTap: () => controller.removeImage(index),
child: Container(
decoration: const BoxDecoration(
color: Colors.black54,
shape: BoxShape.circle,
),
padding: EdgeInsets.all(4.w),
child: Icon(Icons.close, color: Colors.white, size: 16.sp),
),
),
),
],
),
);
}
Widget _bottomButton() {
return Container(
width: 375.w,
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h),
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.r),
topRight: Radius.circular(12.r),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
padding: EdgeInsets.symmetric(vertical: 12.h),
),
onPressed: () {
Get.back();
},
child: Text(
'取消',
style: TextStyle(color: Colors.grey, fontSize: 16.sp),
),
),
),
SizedBox(width: 10.w),
Expanded(
child: Obx(
() => ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF418CFC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
padding: EdgeInsets.symmetric(vertical: 12.h),
),
onPressed: controller.isLoading.value
? null
: () {
if (controller.descriptionController.text.isEmpty) {
Get.snackbar(
'提示',
'问题描述不能为空',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.black87,
colorText: Colors.white,
);
return;
}
controller.saveProblem();
},
child: controller.isLoading.value
? SizedBox(
width: 20.w,
height: 20.h,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: const AlwaysStoppedAnimation<Color>(
Colors.white,
),
),
)
: Text(
'确定',
style: TextStyle(color: Colors.white, fontSize: 16.sp),
),
),
),
),
],
),
);
}
}