feat:更新图片url路径
This commit is contained in:
@@ -5,5 +5,10 @@ class AppConfig {
|
|||||||
// http://14.103.235.151:81/food-service
|
// http://14.103.235.151:81/food-service
|
||||||
// static const String baseApiUrl = "http://14.103.235.151:81/food-service";
|
// static const String baseApiUrl = "http://14.103.235.151:81/food-service";
|
||||||
// static const String baseApiUrl = "http://192.168.1.3:8100";
|
// static const String baseApiUrl = "http://192.168.1.3:8100";
|
||||||
static const String baseApiUrl = "https://cxx0822.iepose.cn/food-api";
|
// static const String baseApiUrl = "https://cxx0822.iepose.cn/food-api";
|
||||||
|
static const String baseApiUrl = "http://127.0.0.1:8083";
|
||||||
|
static const String rustfsIp = '14.103.235.151';
|
||||||
|
static const String rustfsFileUrl = 'http://14.103.235.151:9100';
|
||||||
|
static const String bucketName = 'food';
|
||||||
|
static const String imageBaseUrl = '$rustfsFileUrl/$bucketName/';
|
||||||
}
|
}
|
||||||
@@ -87,44 +87,37 @@ Widget buildBottomSheetBody(BuildContext context) {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.book, color: colors.primary),
|
leading: Icon(Icons.book, color: colors.primary),
|
||||||
title: const Text('新增菜谱'),
|
title: const Text('新增菜谱'),
|
||||||
onTap: () {
|
onTap: () => _handleAddRecipe(context, provider),
|
||||||
Navigator.pop(context);
|
|
||||||
_handleAddRecipe(context);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.note_add, color: colors.primary),
|
leading: Icon(Icons.note_add, color: colors.primary),
|
||||||
title: const Text('新增记录'),
|
title: const Text('新增记录'),
|
||||||
onTap: () {
|
onTap: () => _handleAddRecord(context, provider),
|
||||||
provider.resetRecordForm();
|
|
||||||
Navigator.pop(context);
|
|
||||||
Navigator.pushNamed(context, "/recordForm");
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.group, color: colors.primary),
|
leading: Icon(Icons.group, color: colors.primary),
|
||||||
title: const Text('发布朋友圈'),
|
title: const Text('发布朋友圈'),
|
||||||
onTap: () {
|
onTap: () => _handleAddMoment(context, provider),
|
||||||
Navigator.pop(context);
|
|
||||||
_handleAddRecord(context);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理添加菜谱
|
void _handleAddRecipe(BuildContext context, FoodProvider provider) {
|
||||||
void _handleAddRecipe(BuildContext context) {
|
// provider.resetRecordForm();
|
||||||
// 这里添加跳转或处理添加菜谱的逻辑
|
// Navigator.pop(context);
|
||||||
ScaffoldMessenger.of(
|
// Navigator.pushNamed(context, "/recordForm");
|
||||||
context,
|
|
||||||
).showSnackBar(const SnackBar(content: Text('添加菜谱功能')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理添加记录
|
void _handleAddRecord(BuildContext context, FoodProvider provider) {
|
||||||
void _handleAddRecord(BuildContext context) {
|
provider.resetRecordForm();
|
||||||
// 这里添加跳转或处理添加记录的逻辑
|
provider.isEditing = false;
|
||||||
ScaffoldMessenger.of(
|
Navigator.pop(context);
|
||||||
context,
|
Navigator.pushNamed(context, "/recordForm");
|
||||||
).showSnackBar(const SnackBar(content: Text('添加记录功能')));
|
}
|
||||||
|
|
||||||
|
void _handleAddMoment(BuildContext context, FoodProvider provider) {
|
||||||
|
// provider.resetRecordForm();
|
||||||
|
// Navigator.pop(context);
|
||||||
|
// Navigator.pushNamed(context, "/recordForm");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,6 +235,26 @@ class RecipeDetail {
|
|||||||
_$RecipeDetailFromJson(json);
|
_$RecipeDetailFromJson(json);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$RecipeDetailToJson(this);
|
Map<String, dynamic> toJson() => _$RecipeDetailToJson(this);
|
||||||
|
|
||||||
|
static RecipeDetail getEmpty() {
|
||||||
|
return RecipeDetail(
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
category: '',
|
||||||
|
recommendRate: 0,
|
||||||
|
remark: '',
|
||||||
|
isShare: false,
|
||||||
|
userId: 0,
|
||||||
|
username: '',
|
||||||
|
avatar: '',
|
||||||
|
materialList: [],
|
||||||
|
stepList: [],
|
||||||
|
recordList: [],
|
||||||
|
likeList: [],
|
||||||
|
favouriteList: [],
|
||||||
|
commentList: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ViewType { recipe, calendar, timeline }
|
enum ViewType { recipe, calendar, timeline }
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import 'package:food_hub_app/models/recipe.dart';
|
|||||||
class FoodProvider with ChangeNotifier {
|
class FoodProvider with ChangeNotifier {
|
||||||
late FoodRecord _recordFormItem;
|
late FoodRecord _recordFormItem;
|
||||||
|
|
||||||
|
late bool isEditing;
|
||||||
|
|
||||||
FoodRecord get recordFormItem => _recordFormItem;
|
FoodRecord get recordFormItem => _recordFormItem;
|
||||||
|
|
||||||
void resetRecordForm() {
|
void resetRecordForm() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:food_hub_app/config/app_config.dart';
|
||||||
|
|
||||||
import 'package:minio/io.dart';
|
import 'package:minio/io.dart';
|
||||||
import 'package:minio/minio.dart';
|
import 'package:minio/minio.dart';
|
||||||
@@ -10,13 +11,9 @@ class MinIOHelper {
|
|||||||
|
|
||||||
factory MinIOHelper() => _instance;
|
factory MinIOHelper() => _instance;
|
||||||
|
|
||||||
final String rustfsIp = '14.103.235.151';
|
|
||||||
final String rustfsFileUrl = 'http://14.103.235.151:9100';
|
|
||||||
final String bucketName = 'food';
|
|
||||||
|
|
||||||
MinIOHelper._internal() {
|
MinIOHelper._internal() {
|
||||||
_minio = Minio(
|
_minio = Minio(
|
||||||
endPoint: rustfsIp,
|
endPoint: AppConfig.rustfsIp,
|
||||||
port: 9100,
|
port: 9100,
|
||||||
accessKey: "tHSFfcDW8qpCzKa2Xg6Y",
|
accessKey: "tHSFfcDW8qpCzKa2Xg6Y",
|
||||||
secretKey: "oq79EeYJ4jdczRp2IHUMCnbKtSw58NgDlG3sOkvX",
|
secretKey: "oq79EeYJ4jdczRp2IHUMCnbKtSw58NgDlG3sOkvX",
|
||||||
@@ -26,8 +23,6 @@ class MinIOHelper {
|
|||||||
|
|
||||||
late Minio _minio;
|
late Minio _minio;
|
||||||
|
|
||||||
String get imageBaseUrl => '$rustfsFileUrl/$bucketName/';
|
|
||||||
|
|
||||||
Future<String> uploadFile({
|
Future<String> uploadFile({
|
||||||
required PlatformFile file,
|
required PlatformFile file,
|
||||||
Function(double)? onProgress,
|
Function(double)? onProgress,
|
||||||
@@ -36,7 +31,7 @@ class MinIOHelper {
|
|||||||
String hashName = await _generateMD5HashName(file.path!);
|
String hashName = await _generateMD5HashName(file.path!);
|
||||||
String fileName = '$hashName${_getFileExtension(file.name)}';
|
String fileName = '$hashName${_getFileExtension(file.name)}';
|
||||||
|
|
||||||
await _minio.fPutObject(bucketName, fileName, file.path!);
|
await _minio.fPutObject(AppConfig.bucketName, fileName, file.path!);
|
||||||
return fileName;
|
return fileName;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('文件上传失败: $e');
|
throw Exception('文件上传失败: $e');
|
||||||
|
|||||||
@@ -11,23 +11,7 @@ class RecipeDetailPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RecipeDetailState extends State<RecipeDetailPage> {
|
class _RecipeDetailState extends State<RecipeDetailPage> {
|
||||||
RecipeDetail recipe = RecipeDetail(
|
RecipeDetail recipe = RecipeDetail.getEmpty();
|
||||||
id: 0,
|
|
||||||
name: '',
|
|
||||||
category: '',
|
|
||||||
recommendRate: 0,
|
|
||||||
remark: '',
|
|
||||||
isShare: false,
|
|
||||||
userId: 0,
|
|
||||||
username: '',
|
|
||||||
avatar: '',
|
|
||||||
materialList: [],
|
|
||||||
stepList: [],
|
|
||||||
recordList: [],
|
|
||||||
likeList: [],
|
|
||||||
favouriteList: [],
|
|
||||||
commentList: [],
|
|
||||||
);
|
|
||||||
|
|
||||||
// 定义三个分类列表
|
// 定义三个分类列表
|
||||||
List<RecipeMaterial> mainMaterialList = []; // 主料
|
List<RecipeMaterial> mainMaterialList = []; // 主料
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||||
|
import 'package:food_hub_app/config/app_config.dart';
|
||||||
import 'package:food_hub_app/provider/food_provider.dart';
|
import 'package:food_hub_app/provider/food_provider.dart';
|
||||||
import 'package:food_hub_app/utils/minio_utils.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/form.dart';
|
||||||
@@ -32,10 +33,14 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final colors = Theme.of(context).colorScheme;
|
final colors = Theme.of(context).colorScheme;
|
||||||
|
final provider = context.watch<FoodProvider>();
|
||||||
|
|
||||||
|
final String title = provider.isEditing ? '编辑记录' : '新增记录';
|
||||||
|
print(provider.recordFormItem.imageUrl);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('新增记录', style: TextStyle(color: Colors.white)),
|
title: Text(title, style: TextStyle(color: Colors.white)),
|
||||||
backgroundColor: colors.primary,
|
backgroundColor: colors.primary,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||||
@@ -57,7 +62,6 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
|
|
||||||
return FormBuilder(
|
return FormBuilder(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -65,6 +69,8 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
FormBuilderTextField(
|
FormBuilderTextField(
|
||||||
name: _nameField,
|
name: _nameField,
|
||||||
|
initialValue: provider.recordFormItem.name,
|
||||||
|
enabled: !provider.isEditing,
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -94,6 +100,7 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
FormBuilderTextField(
|
FormBuilderTextField(
|
||||||
name: _dateField,
|
name: _dateField,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
|
initialValue: provider.recordFormItem.date,
|
||||||
decoration: buildInputDecoration(
|
decoration: buildInputDecoration(
|
||||||
context: context,
|
context: context,
|
||||||
hintText: '请选择完成时间',
|
hintText: '请选择完成时间',
|
||||||
@@ -124,7 +131,7 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
buildImagePreviewItem(
|
buildImagePreviewItem(
|
||||||
context: context,
|
context: context,
|
||||||
imageUrl:
|
imageUrl:
|
||||||
'${MinIOHelper().imageBaseUrl}${provider.recordFormItem.imageUrl}',
|
'${AppConfig.imageBaseUrl}${provider.recordFormItem.imageUrl}',
|
||||||
onRemoveImage: () => _removeImage(provider),
|
onRemoveImage: () => _removeImage(provider),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -186,16 +193,12 @@ class _RecordFormPageState extends State<RecordFormPage> {
|
|||||||
void _submitForm(FoodProvider provider) {
|
void _submitForm(FoodProvider provider) {
|
||||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||||
if (provider.recordFormItem.imageUrl.isEmpty) {
|
if (provider.recordFormItem.imageUrl.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showErrorToast('请上传图片');
|
||||||
const SnackBar(
|
|
||||||
content: Text('请上传图片'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
behavior: SnackBarBehavior.floating,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(provider.recordFormItem.name);
|
||||||
|
print(provider.recordFormItem.date);
|
||||||
print(provider.recordFormItem.imageUrl);
|
print(provider.recordFormItem.imageUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,20 +107,23 @@ Widget buildFileImage(BuildContext context, File imageFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildNetworkImage(BuildContext context, String url) {
|
Widget buildNetworkImage(BuildContext context, String url) {
|
||||||
return ClipRRect(
|
return AspectRatio(
|
||||||
borderRadius: BorderRadius.circular(8),
|
aspectRatio: 1.5,
|
||||||
child: GestureDetector(
|
child: ClipRRect(
|
||||||
onTap: () {
|
borderRadius: BorderRadius.circular(8),
|
||||||
showFullScreenImage(context, NetworkImage(url));
|
child: GestureDetector(
|
||||||
},
|
onTap: () {
|
||||||
child: Image.network(
|
showFullScreenImage(context, NetworkImage(url));
|
||||||
url,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
loadingBuilder: (context, child, loadingProgress) {
|
|
||||||
if (loadingProgress == null) return child;
|
|
||||||
return buildImageLoadingIndicator(loadingProgress);
|
|
||||||
},
|
},
|
||||||
errorBuilder: (context, error, stackTrace) => _buildErrorImage(),
|
child: Image.network(
|
||||||
|
url,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
loadingBuilder: (context, child, loadingProgress) {
|
||||||
|
if (loadingProgress == null) return child;
|
||||||
|
return buildImageLoadingIndicator(loadingProgress);
|
||||||
|
},
|
||||||
|
errorBuilder: (context, error, stackTrace) => _buildErrorImage(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ void showSuccessToast(String message) {
|
|||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: message,
|
msg: message,
|
||||||
toastLength: Toast.LENGTH_SHORT,
|
toastLength: Toast.LENGTH_SHORT,
|
||||||
gravity: ToastGravity.CENTER,
|
gravity: ToastGravity.TOP,
|
||||||
timeInSecForIosWeb: 1,
|
timeInSecForIosWeb: 1,
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
@@ -166,7 +166,7 @@ void showErrorToast(String message) {
|
|||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: message,
|
msg: message,
|
||||||
toastLength: Toast.LENGTH_SHORT,
|
toastLength: Toast.LENGTH_SHORT,
|
||||||
gravity: ToastGravity.CENTER,
|
gravity: ToastGravity.TOP,
|
||||||
timeInSecForIosWeb: 1,
|
timeInSecForIosWeb: 1,
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class MomentCard extends StatelessWidget {
|
|||||||
size: TDAvatarSize.medium,
|
size: TDAvatarSize.medium,
|
||||||
type: TDAvatarType.normal,
|
type: TDAvatarType.normal,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
avatarUrl: '${AppConfig.baseApiUrl}/${moment.avatar}',
|
avatarUrl: '${AppConfig.imageBaseUrl}/${moment.avatar}',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ class MomentCard extends StatelessWidget {
|
|||||||
// 生成图片URL列表(用于预览时切换)
|
// 生成图片URL列表(用于预览时切换)
|
||||||
final List<String> imageUrls =
|
final List<String> imageUrls =
|
||||||
moment.imageList
|
moment.imageList
|
||||||
.map((path) => '${AppConfig.baseApiUrl}/$path')
|
.map((path) => '${AppConfig.imageBaseUrl}$path')
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
void imageTapClick(int index) {
|
void imageTapClick(int index) {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:food_hub_app/apis/recipe.dart';
|
import 'package:food_hub_app/apis/recipe.dart';
|
||||||
import 'package:food_hub_app/models/recipe.dart';
|
import 'package:food_hub_app/models/recipe.dart';
|
||||||
|
import 'package:food_hub_app/provider/food_provider.dart';
|
||||||
import 'package:food_hub_app/utils/date_util.dart';
|
import 'package:food_hub_app/utils/date_util.dart';
|
||||||
import 'package:food_hub_app/utils/index.dart';
|
import 'package:food_hub_app/utils/index.dart';
|
||||||
import 'package:food_hub_app/widgets/common/index.dart';
|
import 'package:food_hub_app/widgets/common/index.dart';
|
||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class RecipeCalendar extends StatefulWidget {
|
class RecipeCalendar extends StatefulWidget {
|
||||||
const RecipeCalendar({super.key});
|
const RecipeCalendar({super.key});
|
||||||
@@ -23,10 +25,10 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
refreshRecord();
|
_refreshRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshRecord() async {
|
Future<void> _refreshRecord() async {
|
||||||
final result = await queryRecordApi(
|
final result = await queryRecordApi(
|
||||||
getFirstDayOfMonth(_focusedDay),
|
getFirstDayOfMonth(_focusedDay),
|
||||||
getLastDayOfMonth(_focusedDay),
|
getLastDayOfMonth(_focusedDay),
|
||||||
@@ -40,11 +42,11 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
_selectedDay = _focusedDay;
|
_selectedDay = _focusedDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshSelectRecord();
|
_refreshSelectRecord();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshSelectRecord() {
|
void _refreshSelectRecord() {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectRecordList =
|
selectRecordList =
|
||||||
recordList
|
recordList
|
||||||
@@ -53,7 +55,7 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TableCalendar recipeCalendar() {
|
TableCalendar _recipeCalendar() {
|
||||||
return TableCalendar(
|
return TableCalendar(
|
||||||
locale: 'zh_CN',
|
locale: 'zh_CN',
|
||||||
headerStyle: const HeaderStyle(
|
headerStyle: const HeaderStyle(
|
||||||
@@ -69,13 +71,13 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_selectedDay = selectedDay;
|
_selectedDay = selectedDay;
|
||||||
_focusedDay = focusedDay;
|
_focusedDay = focusedDay;
|
||||||
refreshSelectRecord();
|
_refreshSelectRecord();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPageChanged: (focusedDay) {
|
onPageChanged: (focusedDay) {
|
||||||
_focusedDay = focusedDay;
|
_focusedDay = focusedDay;
|
||||||
refreshRecord();
|
_refreshRecord();
|
||||||
},
|
},
|
||||||
// 自定义日期单元格构建器
|
// 自定义日期单元格构建器
|
||||||
calendarBuilders: CalendarBuilders(
|
calendarBuilders: CalendarBuilders(
|
||||||
@@ -89,7 +91,7 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget dailyItem(BuildContext context) {
|
Widget _dailyItem(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -102,14 +104,49 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
physics: NeverScrollableScrollPhysics(),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
itemCount: selectRecordList.length,
|
itemCount: selectRecordList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return recipeRecordItem(context, selectRecordList[index]);
|
return _buildRecordItem(context, selectRecordList[index]);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget recipeRecordItem(BuildContext context, FoodRecord record) {
|
Widget _buildRecordItemAvatar(String name, Color color) {
|
||||||
|
return CircleAvatar(
|
||||||
|
radius: 20,
|
||||||
|
backgroundColor: color,
|
||||||
|
child: Text(
|
||||||
|
name,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRecordItemBody(String name, String category) {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(name, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Text(category, style: TextStyle(color: Colors.grey)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleEditRecord(BuildContext context, FoodRecord record) {
|
||||||
|
final provider = context.read<FoodProvider>();
|
||||||
|
|
||||||
|
provider.initRecordForm(record);
|
||||||
|
provider.isEditing = true;
|
||||||
|
Navigator.pushNamed(context, "/recordForm");
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRecordItem(BuildContext context, FoodRecord record) {
|
||||||
final colors = Theme.of(context).colorScheme;
|
final colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
@@ -119,37 +156,13 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(10),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
_buildRecordItemAvatar(record.category[0], colors.primary),
|
||||||
radius: 20,
|
|
||||||
backgroundColor: colors.primary,
|
|
||||||
child: Text(
|
|
||||||
record.category[0],
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(child: _buildRecordItemBody(record.name, record.category)),
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
record.name,
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
Text(record.category, style: TextStyle(color: Colors.grey)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
circleIconButton(
|
circleIconButton(
|
||||||
context: context,
|
context: context,
|
||||||
icon: Icons.chevron_right,
|
icon: Icons.chevron_right,
|
||||||
onPressed: () => {},
|
onPressed: () => _handleEditRecord(context, record),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -205,8 +218,10 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
buildCard(context: context, child: recipeCalendar()),
|
buildCard(context: context, child: _recipeCalendar()),
|
||||||
Expanded(child: buildCard(context: context, child: dailyItem(context))),
|
Expanded(
|
||||||
|
child: buildCard(context: context, child: _dailyItem(context)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,6 @@ class RecipeCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final String firstImageUrl = recipe.recordList.first.imageUrl;
|
final String firstImageUrl = recipe.recordList.first.imageUrl;
|
||||||
|
|
||||||
Widget buildRecipeImage() {
|
|
||||||
return AspectRatio(
|
|
||||||
aspectRatio: 1.5,
|
|
||||||
child: buildNetworkImage(
|
|
||||||
context,
|
|
||||||
'${AppConfig.baseApiUrl}/$firstImageUrl',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildRecipeContent(BuildContext context) {
|
Widget buildRecipeContent(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -96,12 +86,15 @@ class RecipeCard extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
buildRecipeImage(),
|
buildNetworkImage(
|
||||||
|
context,
|
||||||
|
'${AppConfig.imageBaseUrl}/$firstImageUrl',
|
||||||
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => navigatorToRecipeDetail(context),
|
onTap: () => navigatorToRecipeDetail(context),
|
||||||
child: buildRecipeContent(context)
|
child: buildRecipeContent(context),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,17 +31,7 @@ class _RecipeTimeline extends State<RecipeTimeline> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildTimelineCard(BuildContext context, FoodRecord record) {
|
Widget buildTimelineCard(BuildContext context, FoodRecord record) {
|
||||||
final imageUrls = ['${AppConfig.baseApiUrl}/${record.imageUrl}'];
|
final imageUrl = '${AppConfig.imageBaseUrl}${record.imageUrl}';
|
||||||
|
|
||||||
void imageTapClick() {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder:
|
|
||||||
(context) => ImagePreviewPage(images: imageUrls, initialIndex: 0),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildCard(
|
return buildCard(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -50,7 +40,10 @@ class _RecipeTimeline extends State<RecipeTimeline> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.date_range, color: Theme.of(context).colorScheme.primary),
|
Icon(
|
||||||
|
Icons.date_range,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
record.date,
|
record.date,
|
||||||
@@ -65,13 +58,7 @@ class _RecipeTimeline extends State<RecipeTimeline> {
|
|||||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
GestureDetector(
|
buildNetworkImage(context, imageUrl),
|
||||||
onTap: () => imageTapClick(),
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1.5,
|
|
||||||
child: buildNetworkImage(context, imageUrls.first),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user