From b53fe04e54b0a116a00418d0a4b7b4a044352c53 Mon Sep 17 00:00:00 2001 From: LingandRX Date: Thu, 8 May 2025 21:06:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(category):=20=E6=B7=BB=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增分类列表页面和分类详情页面 - 实现分类数据的加载、刷新和展示 - 添加分类相关的数据模型、提供者和仓库 - 优化数据库操作,统一表名和查询条件 --- lib/database/item_category_table.dart | 2 +- lib/main.dart | 27 ++++-- lib/models/item_category_model.dart | 10 +-- lib/provider/item_category_provider.dart | 39 +++++++++ lib/repository/item_category_repository.dart | 40 ++++++--- .../category_screens/category_screen.dart | 86 ++++++++++++------- .../detail_category_screen.dart | 26 ++++++ 7 files changed, 171 insertions(+), 59 deletions(-) create mode 100644 lib/provider/item_category_provider.dart create mode 100644 lib/screens/category_screens/detail_category_screen.dart diff --git a/lib/database/item_category_table.dart b/lib/database/item_category_table.dart index f330da7..59be383 100644 --- a/lib/database/item_category_table.dart +++ b/lib/database/item_category_table.dart @@ -9,5 +9,5 @@ CREATE TABLE item_category ( '''; const String insertDefaultCategory = ''' -INSERT INTO item_category (name, description) VALUES ('默认分类', '系统默认分类'); +INSERT INTO item_category (id, name, description) VALUES (0, '默认分类', '系统默认分类'); '''; diff --git a/lib/main.dart b/lib/main.dart index eb915f1..4ef7687 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,22 +1,35 @@ import 'package:flutter/material.dart'; +import 'package:item_tracker/provider/item_category_provider.dart'; import 'package:item_tracker/provider/item_provider.dart'; import 'package:item_tracker/repository/item_repository.dart'; +import 'package:item_tracker/repository/item_category_repository.dart'; import 'package:item_tracker/screens/home_screen.dart'; import 'package:provider/provider.dart'; import 'database/sqlite_helper.dart'; void main() async { + WidgetsFlutterBinding.ensureInitialized(); final dbHelper = DatabaseHelper(); - final repository = ItemRepository(dbHelper: dbHelper); + await dbHelper.database; + + final itemRepository = ItemRepository(dbHelper: dbHelper); + final itemCategoryRepository = ItemCategoryRepository(dbHelper: dbHelper); - WidgetsFlutterBinding.ensureInitialized(); - await DatabaseHelper().database; print('数据库初始化完成'); + runApp( - ChangeNotifierProvider( - create: (_) => ItemProvider(repository: repository), - child: MyApp(),), + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => ItemProvider(repository: itemRepository), + ), + ChangeNotifierProvider( + create: (_) => ItemCategoryProvider(repository: itemCategoryRepository), + ), + ], + child: MyApp(), + ), ); } @@ -31,4 +44,4 @@ class MyApp extends StatelessWidget { home: HomeScreen(), // 修改为 HomeScreen ); } -} \ No newline at end of file +} diff --git a/lib/models/item_category_model.dart b/lib/models/item_category_model.dart index 997db5e..da19743 100644 --- a/lib/models/item_category_model.dart +++ b/lib/models/item_category_model.dart @@ -16,11 +16,11 @@ class ItemCategory { // fromMap — 数据库 map -> Dart 对象 factory ItemCategory.fromMap(Map map) { return ItemCategory( - id: map['id'] as int?, - name: map['name'] as String, - description: map['description'] as String?, - createdAt: map['created_at'] as String?, - updatedAt: map['updated_at'] as String?, + id: map['id'], + name: map['name'], + description: map['description'], + createdAt: map['created_at'], + updatedAt: map['updated_at'], ); } diff --git a/lib/provider/item_category_provider.dart b/lib/provider/item_category_provider.dart new file mode 100644 index 0000000..641e4a2 --- /dev/null +++ b/lib/provider/item_category_provider.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +import 'package:item_tracker/models/item_category_model.dart'; +import 'package:item_tracker/repository/item_category_repository.dart'; + +class ItemCategoryProvider extends ChangeNotifier { + List _categories = []; + + List get categories => _categories; + + final ItemCategoryRepository repository; + + ItemCategoryProvider({required this.repository}); + + Future loadCategories() async { + _categories = await repository.getAll(); + notifyListeners(); + } + + Future addCategory(ItemCategory) async { + await repository.insert(ItemCategory); + await loadCategories(); + } + + Future updateCategory(ItemCategory) async { + await repository.update(ItemCategory); + await loadCategories(); + } + + Future deleteCategory(ItemCategory) async { + await repository.delete(ItemCategory.id!); + await loadCategories(); + } + + Future getCategoryById(int id) async { + final data = await repository.getById(id); + return data; + } +} diff --git a/lib/repository/item_category_repository.dart b/lib/repository/item_category_repository.dart index 9a49cea..237ba95 100644 --- a/lib/repository/item_category_repository.dart +++ b/lib/repository/item_category_repository.dart @@ -1,16 +1,24 @@ +import 'package:item_tracker/database/sqlite_helper.dart'; import 'package:sqflite/sqflite.dart'; import '../models/item_category_model.dart'; class ItemCategoryRepository { - final Database db; + static const String _tableName = 'item_category'; + static const String _whereId = 'id = ?'; - ItemCategoryRepository(this.db); + final DatabaseHelper dbHelper; + + ItemCategoryRepository({required this.dbHelper}); + + // 统一 Database getter + Future get _db async => await dbHelper.database; // 插入 (Create) Future insert(ItemCategory category) async { - return await db.insert( - 'item_category', + final db = await _db; + return db.insert( + _tableName, category.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); @@ -18,15 +26,17 @@ class ItemCategoryRepository { // 查询全部 (Read All) Future> getAll() async { - final List> maps = await db.query('item_category'); + final db = await _db; + final maps = await db.query(_tableName); return maps.map((map) => ItemCategory.fromMap(map)).toList(); } // 查询单个 (Read One by id) Future getById(int id) async { - final List> maps = await db.query( - 'item_category', - where: 'id = ?', + final db = await _db; + final maps = await db.query( + _tableName, + where: _whereId, whereArgs: [id], limit: 1, ); @@ -38,19 +48,21 @@ class ItemCategoryRepository { // 更新 (Update) Future update(ItemCategory category) async { - return await db.update( - 'item_category', + final db = await _db; + return db.update( + _tableName, category.toMap(), - where: 'id = ?', + where: _whereId, whereArgs: [category.id], ); } // 删除 (Delete) Future delete(int id) async { - return await db.delete( - 'item_category', - where: 'id = ?', + final db = await _db; + return db.delete( + _tableName, + where: _whereId, whereArgs: [id], ); } diff --git a/lib/screens/category_screens/category_screen.dart b/lib/screens/category_screens/category_screen.dart index ee9b456..d8d96ae 100644 --- a/lib/screens/category_screens/category_screen.dart +++ b/lib/screens/category_screens/category_screen.dart @@ -1,42 +1,64 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../provider/item_category_provider.dart'; +import 'detail_category_screen.dart'; + +class CategoryScreen extends StatefulWidget { + @override + _CategoryScreenState createState() => _CategoryScreenState(); +} + +class _CategoryScreenState extends State { + late ItemCategoryProvider _itemCategoryProvider; + + @override + void initState() { + super.initState(); + Future.microtask(() { + _itemCategoryProvider = + Provider.of(context, listen: false); + _itemCategoryProvider.loadCategories(); + }); + } + + Future _refreshData() async { + await _itemCategoryProvider.loadCategories(); // 刷新数据 + } -class CategoryScreen extends StatelessWidget { @override Widget build(BuildContext context) { - const items = 20; - return Scaffold( appBar: AppBar( - title: Text('分类'), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: List.generate( - items, - (index) => ItemWidget(text: 'Item $index'), - ), - ), - ), - ); - }, + title: Text('分类列表'), ), + body: Consumer(builder: (context, provider, _) { + final categories = provider.categories; + + if (categories.isEmpty) { + return Center(child: Text("暂无分类")); + } + + return RefreshIndicator( + onRefresh: _refreshData, + child: ListView( + children: categories.map((category) { + return ListTile( + title: Text(category.name), + subtitle: Text(category.description ?? ""), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + DetailCategoryScreen(category: category), + ), + ); + }, + ); + }).toList(), + )); + }), ); } } - -class ItemWidget extends StatelessWidget { - const ItemWidget({super.key, required this.text}); - - final String text; - - @override - Widget build(BuildContext context) { - return Card(child: SizedBox(height: 100, child: Center(child: Text(text)))); - } -} diff --git a/lib/screens/category_screens/detail_category_screen.dart b/lib/screens/category_screens/detail_category_screen.dart new file mode 100644 index 0000000..adfa721 --- /dev/null +++ b/lib/screens/category_screens/detail_category_screen.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:item_tracker/models/item_category_model.dart'; + +class DetailCategoryScreen extends StatelessWidget { + final ItemCategory category; + + DetailCategoryScreen({required this.category}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('分类详情'), + ), + body: Center( + child: Column( + children: [ + Text('${category.name}'), + Text('${category.description}') + ], + ), + ), + ); + } + +} \ No newline at end of file