diff --git a/lib/layout/nav_bar.dart b/lib/layout/nav_bar.dart index 2d78513..02a5511 100644 --- a/lib/layout/nav_bar.dart +++ b/lib/layout/nav_bar.dart @@ -117,7 +117,8 @@ void _handleAddRecord(BuildContext context, FoodProvider provider) { } void _handleAddMoment(BuildContext context, FoodProvider provider) { - // provider.resetRecordForm(); - // Navigator.pop(context); - // Navigator.pushNamed(context, "/recordForm"); + provider.resetRecordForm(); + provider.isEditing = false; + Navigator.pop(context); + Navigator.pushNamed(context, "/momentForm"); } diff --git a/lib/main.dart b/lib/main.dart index 423fa2b..427e085 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:food_hub_app/provider/food_provider.dart'; import 'package:food_hub_app/utils/sp_util.dart'; import 'package:food_hub_app/views/home.dart'; import 'package:food_hub_app/views/login.dart'; +import 'package:food_hub_app/views/moment_form.dart'; import 'package:food_hub_app/views/record_form.dart'; import 'package:food_hub_app/views/recipe_detail.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; @@ -56,6 +57,7 @@ class MyApp extends StatelessWidget { '/home': (context) => HomePage(), '/recordForm': (context) => RecordFormPage(), '/recipeDetail': (context) => RecipeDetailPage(), + '/momentForm': (context) => MomentFormPage(), }, ); } diff --git a/lib/models/moment.dart b/lib/models/moment.dart index f914d00..b446749 100644 --- a/lib/models/moment.dart +++ b/lib/models/moment.dart @@ -50,6 +50,14 @@ class Moment { factory Moment.fromJson(Map json) => _$MomentFromJson(json); Map toJson() => _$MomentToJson(this); + + static Moment getEmpty() { + return Moment( + id: 0, + content: '', + imageList: [] + ); + } } @JsonSerializable() diff --git a/lib/provider/food_provider.dart b/lib/provider/food_provider.dart index 655e3d2..2b4983a 100644 --- a/lib/provider/food_provider.dart +++ b/lib/provider/food_provider.dart @@ -10,6 +10,7 @@ import 'package:food_hub_app/utils/index.dart'; class FoodProvider with ChangeNotifier { late FoodRecord recordFormItem; + late Moment momentFormItem; late bool isEditing; bool isLoading = false; @@ -50,6 +51,16 @@ class FoodProvider with ChangeNotifier { notifyListeners(); } + void resetMomentForm() { + momentFormItem = Moment.getEmpty(); + notifyListeners(); + } + + void initMomentForm(Moment moment) { + momentFormItem = moment; + notifyListeners(); + } + Future queryCategoryList() async { try { error = null; diff --git a/lib/views/moment_form.dart b/lib/views/moment_form.dart new file mode 100644 index 0000000..b79ddf1 --- /dev/null +++ b/lib/views/moment_form.dart @@ -0,0 +1,151 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:food_hub_app/provider/food_provider.dart'; +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:provider/provider.dart'; + +class MomentFormPage extends StatefulWidget { + const MomentFormPage({super.key}); + + @override + State createState() => _MomentFormPageState(); +} + +class _MomentFormPageState extends State { + final _formKey = GlobalKey(); + final _focusNode = FocusNode(); + static const String _contentField = 'content'; + + Widget _buildFormBuilder() { + final provider = context.watch(); + + return FormBuilder( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + buildFormLabel('内容', required: true), + const SizedBox(height: 8), + FormBuilderTextField( + name: _contentField, + focusNode: _focusNode, + onChanged: (value) { + setState(() { + // provider.momentFormItem.content = 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: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (provider.recordFormItem.imageUrl.isEmpty) + buildImageUploadButton(onPickImage: () => _pickImage(provider)) + else + buildImagePreviewItem( + context: context, + imageUrls: [provider.recordFormItem.imageUrl], + index: 0, + onRemoveImage: () => _removeImage(provider), + ), + ], + ), + + const SizedBox(height: 10), + buildFormButtonGroup( + context: context, + onConfirm: () => _submitForm(provider), + ), + ], + ), + ); + } + + /// 选择图片(限制单张) + Future _pickImage(FoodProvider provider) async { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['jpg', 'jpeg', 'png'], + allowMultiple: false, + ); + + if (result != null) { + PlatformFile file = result.files.first; + final fileName = await MinIOHelper().uploadFile(file: file); + setState(() { + provider.recordFormItem.imageUrl = fileName; + }); + } + } + + /// 移除图片 + void _removeImage(FoodProvider provider) { + setState(() { + provider.recordFormItem.imageUrl = ''; + }); + } + + /// 提交表单 + void _submitForm(FoodProvider provider) { + if (_formKey.currentState?.saveAndValidate() ?? false) { + if (provider.recordFormItem.imageUrl.isEmpty) { + showErrorToast('请上传图片'); + return; + } + + print(provider.recordFormItem.name); + print(provider.recordFormItem.date); + print(provider.recordFormItem.imageUrl); + } + } + + @override + Widget build(BuildContext context) { + final colors = Theme.of(context).colorScheme; + final provider = context.watch(); + + final String title = provider.isEditing ? '编辑朋友圈' : '新增朋友圈'; + + return Scaffold( + appBar: AppBar( + title: Text(title, style: TextStyle(color: Colors.white)), + backgroundColor: colors.primary, + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + onPressed: () => Navigator.pop(context), + ), + ), + backgroundColor: const Color(0xFFF5F5F5), + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(5), + child: buildCard(context: context, child: _buildFormBuilder()), + ), + ), + ); + } +}