feat:更新上传记录表单

This commit is contained in:
2025-11-18 23:18:24 +08:00
parent b6995d8dd1
commit 7ede1c2d89
4 changed files with 101 additions and 102 deletions

View File

@@ -6,9 +6,7 @@ import 'package:food_hub_app/utils/minio_utils.dart';
import 'package:food_hub_app/widgets/common/form.dart';
import 'package:food_hub_app/widgets/common/image.dart';
import 'package:food_hub_app/widgets/common/index.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:intl/intl.dart';
import 'dart:io';
import 'package:provider/provider.dart';
@@ -24,7 +22,6 @@ class _RecordFormPageState extends State<RecordFormPage> {
final _focusNode = FocusNode();
static const String _nameField = 'name';
static const String _dateField = 'date';
File? imageFile;
@override
void dispose() {
@@ -56,7 +53,7 @@ class _RecordFormPageState extends State<RecordFormPage> {
}
Widget _buildFormBuilder() {
final foodProvider = context.watch<FoodProvider>();
final provider = context.watch<FoodProvider>();
return FormBuilder(
key: _formKey,
@@ -66,101 +63,85 @@ class _RecordFormPageState extends State<RecordFormPage> {
children: [
buildFormLabel('菜谱名称', required: true),
const SizedBox(height: 8),
_buildNameTextField(),
FormBuilderTextField(
name: _nameField,
focusNode: _focusNode,
onChanged: (value) {
setState(() {
provider.recordFormItem.name = value!;
});
},
decoration: buildInputDecoration(
context: context,
hintText: '请输入菜谱名称',
prefixIcon: const Icon(
Icons.title,
size: 20,
color: Color(0xFF86909C),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入菜谱名称';
}
return null;
},
),
const SizedBox(height: 10),
buildFormLabel('完成时间', required: true),
const SizedBox(height: 8),
_buildDateTextField(),
FormBuilderTextField(
name: _dateField,
readOnly: true,
decoration: buildInputDecoration(
context: context,
hintText: '请选择完成时间',
prefixIcon: const Icon(
Icons.calendar_month,
size: 20,
color: Color(0xFF86909C),
),
),
onTap: () => _onSelectDate(provider),
validator: (value) {
if (value == null || value.isEmpty) {
return '请选择完成时间';
}
return null;
},
),
const SizedBox(height: 10),
buildFormLabel('上传图片', required: true),
const SizedBox(height: 10),
_buildImageUploadArea(),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (provider.recordFormItem.imageUrl.isEmpty)
buildImageUploadButton(onPickImage: () => _pickImage(provider))
else
buildImagePreviewItem(
context: context,
imageUrl:
'${MinIOHelper().imageBaseUrl}${provider.recordFormItem.imageUrl}',
onRemoveImage: () => _removeImage(provider),
),
],
),
const SizedBox(height: 10),
buildFormButtonGroup(
context: context,
onConfirm: () => _submitForm(),
onConfirm: () => _submitForm(provider),
),
],
),
);
}
/// 菜谱名称输入框
Widget _buildNameTextField() {
return FormBuilderTextField(
name: _nameField,
focusNode: _focusNode,
decoration: buildInputDecoration(
context: context,
hintText: '请输入菜谱名称',
prefixIcon: const Icon(Icons.title, size: 20, color: Color(0xFF86909C)),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入菜谱名称';
}
return null;
},
);
}
/// 完成时间选择框
Widget _buildDateTextField() {
return FormBuilderTextField(
name: _dateField,
readOnly: true,
decoration: buildInputDecoration(
context: context,
hintText: '请选择完成时间',
prefixIcon: const Icon(
Icons.calendar_month,
size: 20,
color: Color(0xFF86909C),
),
),
onTap: () => _onSelectDate(),
validator: (value) {
if (value == null || value.isEmpty) {
return '请选择完成时间';
}
return null;
},
);
}
/// 图片上传区域(预览+上传按钮)
Widget _buildImageUploadArea() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (imageFile != null)
_buildImagePreviewItem()
else
buildImageUploadButton(onPickImage: _pickImage),
],
);
}
Widget _buildImagePreviewItem() {
return Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
children: [
buildFileImage(context, imageFile!),
buildDeleteImage(onRemoveImage: _removeImage),
],
),
),
);
}
/// 选择日期
Future<void> _onSelectDate() async {
Future<void> _onSelectDate(FoodProvider provider) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.now(),
@@ -169,14 +150,16 @@ class _RecordFormPageState extends State<RecordFormPage> {
);
if (picked != null) {
_formKey.currentState?.fields[_dateField]?.didChange(
DateFormat('yyyy-MM-dd').format(picked),
);
final String date = DateFormat('yyyy-MM-dd').format(picked);
_formKey.currentState?.fields[_dateField]?.didChange(date);
setState(() {
provider.recordFormItem.date = date;
});
}
}
/// 选择图片(限制单张)
Future<void> _pickImage() async {
Future<void> _pickImage(FoodProvider provider) async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'jpeg', 'png'],
@@ -187,22 +170,22 @@ class _RecordFormPageState extends State<RecordFormPage> {
PlatformFile file = result.files.first;
final fileName = await MinIOHelper().uploadFile(file: file);
setState(() {
// imageFile = File(image.path);
provider.recordFormItem.imageUrl = fileName;
});
}
}
/// 移除图片
void _removeImage() {
void _removeImage(FoodProvider provider) {
setState(() {
imageFile = null;
provider.recordFormItem.imageUrl = '';
});
}
/// 提交表单
void _submitForm() {
void _submitForm(FoodProvider provider) {
if (_formKey.currentState?.saveAndValidate() ?? false) {
if (imageFile == null) {
if (provider.recordFormItem.imageUrl.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请上传图片'),
@@ -213,18 +196,7 @@ class _RecordFormPageState extends State<RecordFormPage> {
return;
}
final formData = {
..._formKey.currentState!.value,
'imageUrl': imageFile?.path,
};
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('提交成功!'),
behavior: SnackBarBehavior.floating,
),
);
print('表单数据: $formData');
print(provider.recordFormItem.imageUrl);
}
}
}