feat(category): 添加分类功能并更新相关页面
- 新增 AddCategoryScreen 页面用于添加分类 - 更新 CategoryScreen 页面,添加浮动按钮用于导航到添加分类页面 - 修改 CategoryDropdown 组件,支持 ItemCategory 模型 - 更新 Item模型,将 location 改为字符串类型 - 修改 ItemScreen 页面,支持新的分类选择逻辑 - 更新数据库表结构,将 location 字段改为 TEXT 类型
This commit is contained in:
parent
b53fe04e54
commit
f2eb1fa265
@ -3,7 +3,7 @@ CREATE TABLE items (
|
|||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
category_id INTEGER,
|
category_id INTEGER,
|
||||||
location_id INTEGER,
|
location TEXT,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
price REAL,
|
price REAL,
|
||||||
purchase_date TEXT,
|
purchase_date TEXT,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ class Item {
|
|||||||
// 分类
|
// 分类
|
||||||
final int? categoryId;
|
final int? categoryId;
|
||||||
// 位置
|
// 位置
|
||||||
final int? locationId;
|
final String? location;
|
||||||
// 描述
|
// 描述
|
||||||
final String? description;
|
final String? description;
|
||||||
// 价格
|
// 价格
|
||||||
@ -27,7 +27,7 @@ class Item {
|
|||||||
this.id,
|
this.id,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.categoryId,
|
this.categoryId,
|
||||||
this.locationId,
|
this.location,
|
||||||
this.description,
|
this.description,
|
||||||
this.price,
|
this.price,
|
||||||
this.purchaseDate,
|
this.purchaseDate,
|
||||||
@ -41,7 +41,7 @@ class Item {
|
|||||||
return {
|
return {
|
||||||
'name': name,
|
'name': name,
|
||||||
'category_id': categoryId,
|
'category_id': categoryId,
|
||||||
'location_id': locationId,
|
'location': location,
|
||||||
'description': description,
|
'description': description,
|
||||||
'price': price,
|
'price': price,
|
||||||
'purchase_date': purchaseDate,
|
'purchase_date': purchaseDate,
|
||||||
@ -57,7 +57,7 @@ class Item {
|
|||||||
id: map['id'],
|
id: map['id'],
|
||||||
name: map['name'],
|
name: map['name'],
|
||||||
categoryId: map['category_id'],
|
categoryId: map['category_id'],
|
||||||
locationId: map['location_id'],
|
location: map['location'],
|
||||||
description: map['description'],
|
description: map['description'],
|
||||||
price: map['price'],
|
price: map['price'],
|
||||||
purchaseDate: map['purchase_date'],
|
purchaseDate: map['purchase_date'],
|
||||||
|
|||||||
73
lib/screens/category_screens/add_category_screen.dart
Normal file
73
lib/screens/category_screens/add_category_screen.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:item_tracker/provider/item_category_provider.dart';
|
||||||
|
import 'package:item_tracker/screens/category_screens/category_screen.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../models/item_category_model.dart';
|
||||||
|
|
||||||
|
class AddCategoryScreen extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_AddCategoryScreenState createState() => _AddCategoryScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddCategoryScreenState extends State<AddCategoryScreen> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final _nameController = TextEditingController();
|
||||||
|
final _descriptionController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('添加分类'),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: InputDecoration(labelText: '名称'),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return '请输入名称';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _descriptionController,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
final category = ItemCategory(
|
||||||
|
name: _nameController.text,
|
||||||
|
description: _descriptionController.text
|
||||||
|
);
|
||||||
|
|
||||||
|
Provider.of<ItemCategoryProvider>(context, listen: false).addCategory(category);
|
||||||
|
|
||||||
|
// 弹窗提示添加成功
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('添加成功'),
|
||||||
|
duration: Duration(seconds: 1),
|
||||||
|
));
|
||||||
|
|
||||||
|
Navigator.pop(context);
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('添加'),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../provider/item_category_provider.dart';
|
import '../../provider/item_category_provider.dart';
|
||||||
|
import 'add_category_screen.dart';
|
||||||
import 'detail_category_screen.dart';
|
import 'detail_category_screen.dart';
|
||||||
|
|
||||||
class CategoryScreen extends StatefulWidget {
|
class CategoryScreen extends StatefulWidget {
|
||||||
@ -59,6 +60,18 @@ class _CategoryScreenState extends State<CategoryScreen> {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
));
|
));
|
||||||
}),
|
}),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final shouldRefresh = await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => AddCategoryScreen()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.white,
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:item_tracker/models/item_category_model.dart';
|
||||||
|
import 'package:item_tracker/provider/item_category_provider.dart';
|
||||||
import 'package:item_tracker/screens/item_screens/widgets/category_dropdown.dart';
|
import 'package:item_tracker/screens/item_screens/widgets/category_dropdown.dart';
|
||||||
import 'package:item_tracker/screens/item_screens/widgets/date_picker_field.dart';
|
import 'package:item_tracker/screens/item_screens/widgets/date_picker_field.dart';
|
||||||
import 'package:item_tracker/screens/item_screens/widgets/description_field.dart';
|
import 'package:item_tracker/screens/item_screens/widgets/description_field.dart';
|
||||||
@ -56,12 +58,14 @@ class _FromTestRouteSate extends State<ItemScreen> {
|
|||||||
String _selected = '';
|
String _selected = '';
|
||||||
double? _price;
|
double? _price;
|
||||||
DateTime? _selectedDate;
|
DateTime? _selectedDate;
|
||||||
String? _selectedCategory; // 当前选中的分类
|
int? _selectedCategory; // 当前选中的分类
|
||||||
ItemIsUse? _itemIsUse = ItemIsUse.yes;
|
ItemIsUse? _itemIsUse = ItemIsUse.yes;
|
||||||
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
late ItemCategoryProvider _itemCategoryProvider;
|
||||||
|
|
||||||
// 添加自定义分类列表
|
// 添加自定义分类列表
|
||||||
List<String> _categories = ['A', 'B', 'C', 'D']; // 自定义分类
|
late List<ItemCategory> _categories; // 自定义分类
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -70,12 +74,22 @@ class _FromTestRouteSate extends State<ItemScreen> {
|
|||||||
if (item != null) {
|
if (item != null) {
|
||||||
_name = item.name;
|
_name = item.name;
|
||||||
_description = item.description!;
|
_description = item.description!;
|
||||||
|
_location = (item.location == null ? '' : item.location)!;
|
||||||
_selectedDate = item.purchaseDate;
|
_selectedDate = item.purchaseDate;
|
||||||
}
|
}
|
||||||
|
_itemCategoryProvider = Provider.of<ItemCategoryProvider>(context, listen: false);
|
||||||
|
Future.microtask(() {
|
||||||
|
_itemCategoryProvider =
|
||||||
|
Provider.of<ItemCategoryProvider>(context, listen: false);
|
||||||
|
_itemCategoryProvider.loadCategories();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final _c = _itemCategoryProvider.categories;
|
||||||
|
_categories = _c.toList();
|
||||||
|
print(_categories);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('新增物品'),
|
title: Text('新增物品'),
|
||||||
@ -130,7 +144,7 @@ class _FromTestRouteSate extends State<ItemScreen> {
|
|||||||
final newItem = Item(
|
final newItem = Item(
|
||||||
name: _name,
|
name: _name,
|
||||||
description: _description,
|
description: _description,
|
||||||
purchaseDate: _selectedDate,
|
categoryId: _selectedCategory,
|
||||||
isInUse: _itemIsUse,
|
isInUse: _itemIsUse,
|
||||||
price: _price,
|
price: _price,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:item_tracker/models/item_category_model.dart';
|
||||||
|
|
||||||
class CategoryDropdown extends StatelessWidget {
|
class CategoryDropdown extends StatelessWidget {
|
||||||
final List<String> categories;
|
final List<ItemCategory> categories;
|
||||||
final String? selectedCategory;
|
final int? selectedCategory;
|
||||||
final ValueChanged<String?> onChanged;
|
final ValueChanged<int?> onChanged;
|
||||||
|
|
||||||
CategoryDropdown({
|
CategoryDropdown({
|
||||||
required this.categories,
|
required this.categories,
|
||||||
@ -13,12 +14,12 @@ class CategoryDropdown extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DropdownButtonFormField<String>(
|
return DropdownButtonFormField<int>(
|
||||||
value: selectedCategory,
|
value: selectedCategory,
|
||||||
items: categories.map((category) {
|
items: categories.map((category) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<int>(
|
||||||
value: category,
|
value: category.id,
|
||||||
child: Text(category),
|
child: Text(category.name),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user