feat:增加菜谱后端接口

This commit is contained in:
2025-07-16 19:59:35 +08:00
parent c8f93f15a1
commit eec0e9f7d3
14 changed files with 327 additions and 205 deletions

View File

@@ -1,13 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/api/session.dart';
import 'package:food_hub_app/models/recipe.dart';
import 'package:food_hub_app/models/session.dart';
import 'package:food_hub_app/utils/sp_util.dart';
import 'package:food_hub_app/widgets/common/index.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
class LoginPage extends StatefulWidget {
@@ -20,7 +17,8 @@ class LoginPage extends StatefulWidget {
class _LoginPage extends State<LoginPage> {
final GlobalKey _formKey = GlobalKey<FormState>();
late String _username, _password;
String _username = "", _password = "";
bool _isRemember = false;
bool _isObscure = true;
Color _eyeColor = Colors.grey;
final List _loginMethod = [
@@ -29,39 +27,51 @@ class _LoginPage extends State<LoginPage> {
{"title": "wechat", "icon": Icons.wechat},
];
@override
void initState() {
super.initState();
_loadRememberState();
}
Future<void> _loadRememberState() async {
bool? isRemember = await SPUtil.getBool('isRemember');
if (isRemember) {
setState(() {
_isRemember = true;
_username = SPUtil.getString('username');
_password = SPUtil.getString('password');
});
}
}
void handleRememberState() {
if (_isRemember) {
SPUtil.set('isRemember', true);
SPUtil.set('username', _username);
SPUtil.set('password', _password);
} else {
SPUtil.set('isRemember', false);
SPUtil.remove('username');
SPUtil.remove('password');
}
}
void handleTokenState(String token) {
SPUtil.set('token', token);
}
void loginClick(BuildContext context) async {
SPUtil.clear();
Session session = await loginApi("Cxx0822", "19940822Cxx");
SPUtil.set('token', session.saToken.tokenValue);
Recipe recipe = await queryRecipeByIdApi(614660173221957);
List<Recipe> recipeList = await queryRecipeByUserApi(691110779121733);
// SPUtil.set("token", session?.saToken?.tokenValue);
// Navigator.pushNamed(context, '/home');
return;
// 表单校验通过才会继续执行
if ((_formKey.currentState as FormState).validate()) {
(_formKey.currentState as FormState).save();
TDMessage.showMessage(
context: context,
visible: true,
icon: true,
content: "登录成功",
theme: MessageTheme.success,
duration: 3000,
);
Session session = await loginApi(_username, _password);
showSuccessToast('登录成功');
handleRememberState();
handleTokenState(session.saToken.tokenValue);
Navigator.pushNamed(context, '/home');
} else {
TDMessage.showMessage(
context: context,
visible: true,
icon: true,
content: "请先输入信息",
theme: MessageTheme.error,
duration: 3000,
);
showErrorToast('请先输入信息');
}
}
@@ -135,6 +145,8 @@ class _LoginPage extends State<LoginPage> {
const SizedBox(height: 10),
FormBuilderTextField(
name: 'username',
initialValue: _username,
keyboardType: TextInputType.text,
decoration: formInputDecoration(
hintText: "请输入账号",
prefixIcon: Icons.person,
@@ -154,8 +166,9 @@ class _LoginPage extends State<LoginPage> {
const SizedBox(height: 10),
FormBuilderTextField(
name: 'password',
initialValue: _password,
keyboardType: TextInputType.visiblePassword,
obscureText: _isObscure,
// 是否显示文字
onSaved: (v) => _password = v!,
validator: FormBuilderValidators.required(),
decoration: InputDecoration(
@@ -168,7 +181,6 @@ class _LoginPage extends State<LoginPage> {
suffixIcon: IconButton(
icon: Icon(Icons.remove_red_eye, color: _eyeColor),
onPressed: () {
// 修改 state 内部变量, 且需要界面内容更新, 需要使用 setState()
setState(() {
_isObscure = !_isObscure;
_eyeColor =
@@ -188,9 +200,11 @@ class _LoginPage extends State<LoginPage> {
return Row(
children: [
Checkbox(
value: false,
value: _isRemember,
onChanged: (bool? value) {
print("记住密码: $value");
setState(() {
_isRemember = value ?? false;
});
},
),
const Text('记住密码', style: TextStyle(color: Colors.grey, fontSize: 14)),

View File

@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:food_hub_app/api/recipe.dart';
import 'package:food_hub_app/models/recipe.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_timeline.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
import '../models/recipe.dart';
class RecordPage extends StatefulWidget {
const RecordPage({super.key});
@@ -15,33 +16,62 @@ class RecordPage extends StatefulWidget {
class _RecordPageState extends State<RecordPage>
with SingleTickerProviderStateMixin {
final List<Recipe> recipeList = [];
List<Recipe> _recipeList = [];
final List<Record> recordList = [];
final List<Record> _recordList = [];
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_month)),
const TDTab(text: '时间轴', icon: Icon(Icons.timeline)),
];
@override
void initState() {
super.initState();
_getRecipeList();
_tabController.addListener(_handleTabChange);
}
@override
void dispose() {
_tabController.removeListener(_handleTabChange);
_tabController.dispose();
super.dispose();
}
void _handleTabChange() {
if (_tabController.indexIsChanging) {
return;
}
// 根据当前选中的索引执行对应接口请求
switch (_tabController.index) {
case 0:
_getRecipeList();
break;
case 1:
print("2");
break;
case 2:
print("3");
break;
}
}
Future<void> _getRecipeList() async {
final result = await queryRecipeApi(RecipeQuery(category: ""));
setState(() {
_recipeList = result;
});
}
@override
Widget build(BuildContext context) {
return Padding(
@@ -60,9 +90,9 @@ class _RecordPageState extends State<RecordPage>
child: TabBarView(
controller: _tabController,
children: [
RecipeList(recipeList: recipeList),
RecipeList(recipeList: _recipeList),
RecipeCalendar(),
RecipeTimeline(recordList: recordList),
RecipeTimeline(recordList: _recordList),
],
),
),