feat:更新日历组件

This commit is contained in:
2025-07-11 16:48:04 +08:00
parent b56b822e01
commit 55ca36cba2
7 changed files with 103 additions and 106 deletions

View File

@@ -66,7 +66,7 @@ class _MainPage extends State<MainPage> {
appBar: AppBar(
centerTitle: true,
title: Text('Food Hub'),
backgroundColor: Colors.white,
backgroundColor: Colors.green,
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
@@ -96,6 +96,7 @@ class _MainPage extends State<MainPage> {
currentIndex: _currentIndex,
iconSize: 25,
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.white,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "记录"),
BottomNavigationBarItem(

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/widgets/recipe/recipe_calendar.dart';
import 'package:food_hub_app/widgets/recipe/recipe_list.dart';
import 'package:food_hub_app/widgets/recipe/recipe_segment.dart';
import 'package:food_hub_app/widgets/recipe/recipe_timeline.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import 'models/recipe.dart';
@@ -13,48 +13,64 @@ class RecordPage extends StatefulWidget {
State<StatefulWidget> createState() => _RecordPageState();
}
class _RecordPageState extends State<RecordPage> {
ViewType _selectedViewType = ViewType.recipe;
class _RecordPageState extends State<RecordPage>
with SingleTickerProviderStateMixin {
final List<Recipe> recipeList = [
Recipe("韭菜炒鸡蛋", "家常菜", "2025-05-04", "https://picsum.photos/200", 10, 2, 4),
Recipe("红烧肉", "家常菜", "2025-05-05", "https://picsum.photos/200", 12, 4, 7),
];
late final TabController _tabController = TabController(
length: 3,
vsync: this,
);
@override
void initState() {
super.initState();
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
// 定义标签列表
final List<TDTab> tabs = [
const TDTab(text: '菜谱', icon: Icon(Icons.book)),
const TDTab(text: '日历', icon: Icon(Icons.calendar_today)),
const TDTab(text: '时间轴', icon: Icon(Icons.timeline)),
];
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10),
padding: EdgeInsets.all(0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
RecipeSegment(
selectedViewType: _selectedViewType,
onViewTypeChanged: (value) {
setState(() {
_selectedViewType = value;
});
},
// 标签栏
TDTabBar(
tabs: tabs,
controller: _tabController,
backgroundColor: Colors.white,
showIndicator: true,
),
Expanded(
child: Padding(
padding: EdgeInsets.all(5),
child: TabBarView(
controller: _tabController,
children: [
RecipeList(recipeList: recipeList),
RecipeCalendar(),
RecipeTimeline(recipeList: recipeList),
],
),
),
),
const SizedBox(height: 10),
const Divider(height: 1),
const SizedBox(height: 10),
// 内容区域
Expanded(child: _buildContent()),
],
),
);
}
Widget _buildContent() {
switch (_selectedViewType) {
case ViewType.recipe:
return RecipeList(recipeList: recipeList);
case ViewType.calendar:
return RecipeCalendar();
case ViewType.timeline:
return RecipeTimeline(recipeList: recipeList);
}
}
}

View File

@@ -13,6 +13,7 @@ class LoginPage extends StatefulWidget {
class _LoginPage extends State<LoginPage> {
final GlobalKey _formKey = GlobalKey<FormState>();
late String _username, _password;
bool _isObscure = true;
Color _eyeColor = Colors.grey;
@@ -52,9 +53,6 @@ class _LoginPage extends State<LoginPage> {
buildUsernameTextField(),
const SizedBox(height: 20),
buildPasswordTextField(context),
// 紧凑排列:记住密码在上,忘记密码在下,间距缩小
const SizedBox(height: 8), // 缩小密码框与记住密码的间距
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
@@ -102,10 +100,13 @@ class _LoginPage extends State<LoginPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
formLabelText(labelText: "账号:"),
const SizedBox(height: 5),
const SizedBox(height: 10),
FormBuilderTextField(
name: 'username',
decoration: formInputDecoration(hintText: "请输入账号", prefixIcon: Icons.person),
decoration: formInputDecoration(
hintText: "请输入账号",
prefixIcon: Icons.person,
),
validator: FormBuilderValidators.required(),
onSaved: (v) => _username = v!,
),
@@ -118,7 +119,7 @@ class _LoginPage extends State<LoginPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
formLabelText(labelText: "密码:"),
const SizedBox(height: 5),
const SizedBox(height: 10),
FormBuilderTextField(
name: 'password',
obscureText: _isObscure,
@@ -139,14 +140,14 @@ class _LoginPage extends State<LoginPage> {
setState(() {
_isObscure = !_isObscure;
_eyeColor =
(_isObscure
? Colors.grey
: Theme.of(context).iconTheme.color)!;
(_isObscure
? Colors.grey
: Theme.of(context).iconTheme.color)!;
});
},
),
),
)
),
],
);
}
@@ -185,23 +186,20 @@ class _LoginPage extends State<LoginPage> {
child: SizedBox(
height: 45,
width: double.infinity,
child: TDButton(
child: TDButton(
text: '登录',
size: TDButtonSize.large,
type: TDButtonType.fill,
shape: TDButtonShape.rectangle,
theme: TDButtonTheme.primary,
onTap: () => loginClick(context)
)
onTap: () => loginClick(context),
),
),
);
}
Widget buildOtherLoginText() {
return TDDivider(
text: '其他方式登录',
alignment: TextAlignment.center,
);
return TDDivider(text: '其他方式登录', alignment: TextAlignment.center);
}
Widget buildOtherMethod(context) {

View File

@@ -1,9 +1,19 @@
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
class RecipeCalendar extends StatelessWidget {
class RecipeCalendar extends StatefulWidget {
const RecipeCalendar({super.key});
@override
State<RecipeCalendar> createState() => _RecipeCalendarState();
}
class _RecipeCalendarState extends State<RecipeCalendar> {
// 当前选中的日期
DateTime _selectedDay = DateTime.now();
// 当前显示的月份
DateTime _focusedDay = DateTime.now();
@override
Widget build(BuildContext context) {
return Column(
@@ -12,11 +22,36 @@ class RecipeCalendar extends StatelessWidget {
elevation: 0,
color: Colors.white,
child: TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
locale: 'zh_CN',
headerStyle: const HeaderStyle(
formatButtonVisible: false,
titleCentered: true,
),
firstDay: DateTime.utc(2010, 1, 1),
lastDay: DateTime.utc(2100, 12, 31),
focusedDay: _focusedDay,
selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
onDaySelected: (selectedDay, focusedDay) {
if (!isSameDay(_selectedDay, selectedDay)) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
}
},
onPageChanged: (focusedDay) {
print("cxx");
_focusedDay = focusedDay;
},
),
),
// 显示选中的日期
const SizedBox(height: 16),
Text(
'选中的日期: ${_selectedDay.year}-${_selectedDay.month}-${_selectedDay.day}',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
],
);
}

View File

@@ -1,45 +0,0 @@
import 'package:custom_sliding_segmented_control/custom_sliding_segmented_control.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:food_hub_app/models/recipe.dart';
class RecipeSegment extends StatelessWidget {
final ViewType selectedViewType;
final Function(ViewType) onViewTypeChanged;
const RecipeSegment({super.key, required this.selectedViewType, required this.onViewTypeChanged});
@override
Widget build(BuildContext context) {
return CustomSlidingSegmentedControl<int>(
initialValue: 1,
children: {
1: SizedBox(
width: 50,
child: Text('菜谱', textAlign: TextAlign.center),
),
2: SizedBox(
width: 50,
child: Text('日历', textAlign: TextAlign.center),
),
3: SizedBox(
width: 50,
child: Text('时间轴', textAlign: TextAlign.center),
),
},
decoration: BoxDecoration(
color: CupertinoColors.lightBackgroundGray,
borderRadius: BorderRadius.circular(10),
),
thumbDecoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
duration: Duration(milliseconds: 300),
curve: Curves.easeInToLinear,
onValueChanged: (value) {
onViewTypeChanged(ViewType.values[value - 1]);
},
);
}
}