Boobook
这个开源项目展示了如何构建一个 Flutter 应用,其中包含
- Firebase Authentication 来处理用户认证
- Firebase Firestore 用于响应式数据库
- Riverpod 来处理状态管理
- RevenueCat 来轻松配置应用内订阅
- ISBNdb 用于通过 ISBN 码获取书籍信息
该项目还涵盖了许多其他主题
- 学习仓库模式架构
- 简单的路由,使用自制路由器(Navigator 1.0)
- 使用专门的操作系统组件(例如 CupertinoScaffold 用于 iOS,Scaffold 用于 Android)
- 通过 flutter_localizations 和 Riverpod 处理本地化
- 在所有 Flutter 应用中复用组件
应用概览
Boobook 是一个简单的图书库管理器,专为教师设计,用于管理图书借阅给学生。该应用程序由五个主要屏幕组成:借阅、图书、扫描、学生 和 设置。
首次启动时,应用程序会要求用户登录。可以通过选择“无需账户继续”来跳过此步骤,这将导致在 Firebase 中创建一个匿名用户。
借阅页面显示当前借出的图书,以及图书预计归还前的剩余时间。该时间显示为绿色表示离归还日期还远,橙色表示临近最后几天,红色表示已超过归还日期。点击某个借阅项会打开一些选项,允许您结束借阅或根据需要延长借阅时间。
打开 图书页面查看您的图书列表。彩色圆点表示图书是否可用。点击某本书可以编辑其名称或封面图片。
在 学生页面,您可以查看您的学生列表以及当前借阅数量。您可以通过点击右上角的按钮一次性打印所有会员卡。点击某个学生可以编辑其姓名或卡片图片,或者打印其会员卡。
使用 扫描页面打开您的设备摄像头,以便扫描图书。如果图书尚未在您的图书列表中,系统会提示您添加它;如果已添加,系统会提示您扫描学生卡或从列表中选择一个学生,以创建一个新的借阅记录。
最后,设置页面允许您配置一些功能:同时借阅的最大数量、默认借阅时长、会员卡上的标题。还可以进行一些外观设置,例如默认显示的语言和应用程序的主题(浅色或深色)。
功能
- 通过手动添加或扫描条形码来注册您的所有图书
- 创建您的所有学生,这将为您生成会员卡,您可以打印出来发给您的学生
- 扫描图书和会员卡,即可在几秒钟内生成借阅记录!
- Firestore 在线数据持久化
应用结构
项目文件夹结构如下:
/controllers
/models
/l10n
/presentation
/common_widgets
/routes
/theme
/views
/home
/codes
/loans
/pupils
/scan
/settings
/subscription
/sign_in
/splash
/repositories
lib 文件夹仅包含 main.dart,其中包含启动应用程序的主 Widget,以及 common_providers.dart,其中包含跨代码复用的一些 Provider。
然后,在 lib 内部,您会找到:
controllers,其中包含我们的“freezed”状态文件models,其中包含所有模型(使用 Freezed 生成)l10n,其中包含本地化的 arb 文件presentation,包含所有 UI 内容(子文件夹详见下文)repositories,其中包含用于访问数据库的仓库
presentation
presentation 分为子文件夹:
common_widgets,包含所有被多次使用的 Widgetroutes,包含应用程序的路由theme,包含布局相关内容views,包含页面。
views
views 也分为子文件夹:
home,包含用户登录后的应用程序内容sign_in,包含登录页面splash,包含启动页面,即应用程序启动时加载的第一个视图
home
home 通常按应用程序的每个部分进行子文件夹划分,通常在使用 TabScaffold 时按每个 Tab 进行划分。
存储库中缺失的文件
出于安全原因,一些文件被故意从存储库中删除
android/app/google-services.json,这是使 Firebase 在 Android 设备上运行的文件ios/Runner/GoogleService-Info.plist,这是使 Firebase 在 iOS 设备上运行的文件ios/Runner/Info.plist,我决定隐藏它,因为它明确显示了 Facebook 登录的 Facebook 应用密钥lib/config.dart,下面将详细介绍
config.dart
应用程序需要此 dart 文件才能正常工作
final isbnApiKey = "your_isbndb_api_key";
const purchasesApiKey = 'your_revenuecat_api_key';
const entitlementId = 'your_purchase_entitlement';
const privacyPolicyURL = "https://boobook.app/privacy";
const termsURL = "https://www.apple.com/legal/internet-services/itunes/dev/stdeula/";
class FirestorePath {
static String pupils = "pupils";
static String books = "books";
static String loans = "loans";
static String users = "users";
}
class StoragePath {
static String users = "users";
static String pupils = "pupils";
static String books = "books";
}
关于源代码构建方式的重要说明
此源代码引用了我 GitHub 存储库中托管的许多个人 Flutter 包。这些包是我为个人 Flutter 项目创建的,因为我在所有 Flutter 项目中大量复用代码,以避免在项目之间复制粘贴过多。如果您想理解 Boobook 的所有源代码,您需要查看代码引用的每个包。
- avatar 生成带有照片的个人资料图片,或带有首字母的备用图片
- extensions 提供了我在所有应用程序中常用的一些类扩展
- firestore_service 是一个帮助处理 Firestore 数据的类
- firebase_storage_service 是一个帮助从 Firebase Storage 上传或下载文件的类
- layout_builder 提供了我应用程序中使用的所有布局内容,包含即用型跨平台 Widget
- photo_upload 是一个即用型 Widget+Controller,用于使用
firebase_storage_service上传图片 - sign_in 是一个即用型 Widget+Controller,用于处理 Firebase Auth 的认证
- purchases 提供了使用 RevenueCat 处理应用内购买的帮助]
这些包托管在我的 GitHub 存储库中,而不是作为 pub.dev 上的官方包,因为它们仅为满足我的个人需求而构建,并且我会定期进行重要的重大更改。
未来路线图
- 生成并打印自定义条形码,以便在应用程序中处理杂志(杂志不像书籍那样有 ISBN,因此无法通过扫描条形码来处理)
- 更改设置选项卡中显示账户详情的方式
- 更好地显示订阅信息,可能在免费配额即将达到时显示一些提醒
- 避免对 localizationProvider 进行作用域限制


