generated from dellevin/template
基础功能
This commit is contained in:
60
lib/utils/app_router.dart
Normal file
60
lib/utils/app_router.dart
Normal file
@@ -0,0 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/data_models.dart';
|
||||
import '../pages/movie_form_page.dart';
|
||||
import '../pages/book_form_page.dart';
|
||||
import '../pages/note_form_page.dart';
|
||||
import '../pages/movie_detail_page.dart';
|
||||
import '../pages/book_detail_page.dart';
|
||||
import '../pages/note_detail_page.dart';
|
||||
|
||||
/// 路由生成器
|
||||
class AppRouter {
|
||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case '/movie-form':
|
||||
final movie = settings.arguments as Movie?;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => MovieFormPage(movie: movie),
|
||||
);
|
||||
|
||||
case '/book-form':
|
||||
final book = settings.arguments as Book?;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => BookFormPage(book: book),
|
||||
);
|
||||
|
||||
case '/note-form':
|
||||
final note = settings.arguments as Note?;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => NoteFormPage(note: note),
|
||||
);
|
||||
|
||||
case '/movie-detail':
|
||||
final movie = settings.arguments as Movie;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => MovieDetailPage(movie: movie),
|
||||
);
|
||||
|
||||
case '/book-detail':
|
||||
final book = settings.arguments as Book;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => BookDetailPage(book: book),
|
||||
);
|
||||
|
||||
case '/note-detail':
|
||||
final note = settings.arguments as Note;
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => NoteDetailPage(note: note),
|
||||
);
|
||||
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => Scaffold(
|
||||
body: Center(
|
||||
child: Text('未找到页面:${settings.name}'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
lib/utils/app_theme.dart
Normal file
66
lib/utils/app_theme.dart
Normal file
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppTheme {
|
||||
// 主色调
|
||||
static const Color primaryColor = Color(0xFF6200EE);
|
||||
static const Color secondaryColor = Color(0xFF03DAC6);
|
||||
|
||||
// 状态颜色
|
||||
static const Color watchedColor = Color(0xFF4CAF50); // 已看 - 绿色
|
||||
static const Color wantToWatchColor = Color(0xFFFF9800); // 想看 - 橙色
|
||||
static const Color watchingColor = Color(0xFF2196F3); // 在看 - 蓝色
|
||||
|
||||
static const Color readColor = Color(0xFF4CAF50); // 读完 - 绿色
|
||||
static const Color wantToReadColor = Color(0xFFFF9800); // 准备读 - 橙色
|
||||
static const Color readingColor = Color(0xFF2196F3); // 在读 - 蓝色
|
||||
|
||||
// 亮色主题
|
||||
static final ThemeData lightTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: primaryColor,
|
||||
brightness: Brightness.light,
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
elevation: 8,
|
||||
selectedItemColor: primaryColor,
|
||||
unselectedItemColor: Colors.grey,
|
||||
),
|
||||
);
|
||||
|
||||
// 暗色主题
|
||||
static final ThemeData darkTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.dark,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: primaryColor,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
centerTitle: false,
|
||||
elevation: 0,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
elevation: 8,
|
||||
selectedItemColor: secondaryColor,
|
||||
unselectedItemColor: Colors.grey,
|
||||
),
|
||||
);
|
||||
}
|
||||
81
lib/utils/book_dao.dart
Normal file
81
lib/utils/book_dao.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import '../models/data_models.dart';
|
||||
import 'database_helper.dart';
|
||||
|
||||
/// 书籍数据访问对象
|
||||
class BookDao {
|
||||
final DatabaseHelper _dbHelper = DatabaseHelper.instance;
|
||||
|
||||
// 获取所有书籍记录
|
||||
Future<List<Book>> getAllBooks() async {
|
||||
final db = await _dbHelper.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query('books');
|
||||
|
||||
return List.generate(maps.length, (i) {
|
||||
return Book(
|
||||
id: maps[i]['id'].toString(),
|
||||
title: maps[i]['title'],
|
||||
author: maps[i]['author'],
|
||||
cover: maps[i]['cover'],
|
||||
rating: maps[i]['rating']?.toDouble(),
|
||||
status: maps[i]['status'],
|
||||
readDate: maps[i]['read_date'] != null
|
||||
? DateTime.parse(maps[i]['read_date'])
|
||||
: null,
|
||||
note: maps[i]['note'],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 根据状态筛选书籍记录
|
||||
Future<List<Book>> getBooksByStatus(String status) async {
|
||||
final db = await _dbHelper.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
'books',
|
||||
where: 'status = ?',
|
||||
whereArgs: [status],
|
||||
);
|
||||
|
||||
return List.generate(maps.length, (i) {
|
||||
return Book(
|
||||
id: maps[i]['id'].toString(),
|
||||
title: maps[i]['title'],
|
||||
author: maps[i]['author'],
|
||||
cover: maps[i]['cover'],
|
||||
rating: maps[i]['rating']?.toDouble(),
|
||||
status: maps[i]['status'],
|
||||
readDate: maps[i]['read_date'] != null
|
||||
? DateTime.parse(maps[i]['read_date'])
|
||||
: null,
|
||||
note: maps[i]['note'],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 添加书籍记录
|
||||
Future<int> insertBook(Book book) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.insert('books', book.toJson());
|
||||
}
|
||||
|
||||
// 更新书籍记录
|
||||
Future<int> updateBook(Book book) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.update(
|
||||
'books',
|
||||
book.toJson(),
|
||||
where: 'id = ?',
|
||||
whereArgs: [book.id],
|
||||
);
|
||||
}
|
||||
|
||||
// 删除书籍记录
|
||||
Future<int> deleteBook(String id) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.delete(
|
||||
'books',
|
||||
where: 'id = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
}
|
||||
}
|
||||
81
lib/utils/database_helper.dart
Normal file
81
lib/utils/database_helper.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
/// 数据库帮助类 - 管理数据库的创建和版本控制
|
||||
class DatabaseHelper {
|
||||
static final DatabaseHelper instance = DatabaseHelper._init();
|
||||
static Database? _database;
|
||||
|
||||
DatabaseHelper._init();
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDB('mooknote.db');
|
||||
return _database!;
|
||||
}
|
||||
|
||||
Future<Database> _initDB(String filePath) async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = join(dbPath, filePath);
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 1,
|
||||
onCreate: _createDB,
|
||||
);
|
||||
}
|
||||
|
||||
// 创建数据库表
|
||||
Future<void> _createDB(Database db, int version) async {
|
||||
const idType = 'INTEGER PRIMARY KEY AUTOINCREMENT';
|
||||
const textType = 'TEXT NOT NULL';
|
||||
const integerType = 'INTEGER NOT NULL';
|
||||
const booleanType = 'INTEGER NOT NULL';
|
||||
|
||||
// 影视表
|
||||
await db.execute('''
|
||||
CREATE TABLE movies (
|
||||
id $idType,
|
||||
title $textType,
|
||||
poster TEXT,
|
||||
rating REAL,
|
||||
year INTEGER,
|
||||
status $textType,
|
||||
watch_date TEXT,
|
||||
note TEXT
|
||||
)
|
||||
''');
|
||||
|
||||
// 书籍表
|
||||
await db.execute('''
|
||||
CREATE TABLE books (
|
||||
id $idType,
|
||||
title $textType,
|
||||
author TEXT,
|
||||
cover TEXT,
|
||||
rating REAL,
|
||||
status $textType,
|
||||
read_date TEXT,
|
||||
note TEXT
|
||||
)
|
||||
''');
|
||||
|
||||
// 笔记表
|
||||
await db.execute('''
|
||||
CREATE TABLE notes (
|
||||
id $idType,
|
||||
title $textType,
|
||||
content $textType,
|
||||
tags TEXT,
|
||||
created_at $textType,
|
||||
updated_at $textType
|
||||
)
|
||||
''');
|
||||
}
|
||||
|
||||
// 关闭数据库
|
||||
Future close() async {
|
||||
final db = await instance.database;
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
81
lib/utils/movie_dao.dart
Normal file
81
lib/utils/movie_dao.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import '../models/data_models.dart';
|
||||
import 'database_helper.dart';
|
||||
|
||||
/// 影视数据访问对象
|
||||
class MovieDao {
|
||||
final DatabaseHelper _dbHelper = DatabaseHelper.instance;
|
||||
|
||||
// 获取所有影视记录
|
||||
Future<List<Movie>> getAllMovies() async {
|
||||
final db = await _dbHelper.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query('movies');
|
||||
|
||||
return List.generate(maps.length, (i) {
|
||||
return Movie(
|
||||
id: maps[i]['id'].toString(),
|
||||
title: maps[i]['title'],
|
||||
poster: maps[i]['poster'],
|
||||
rating: maps[i]['rating']?.toDouble(),
|
||||
year: maps[i]['year'],
|
||||
status: maps[i]['status'],
|
||||
watchDate: maps[i]['watch_date'] != null
|
||||
? DateTime.parse(maps[i]['watch_date'])
|
||||
: null,
|
||||
note: maps[i]['note'],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 根据状态筛选影视记录
|
||||
Future<List<Movie>> getMoviesByStatus(String status) async {
|
||||
final db = await _dbHelper.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
'movies',
|
||||
where: 'status = ?',
|
||||
whereArgs: [status],
|
||||
);
|
||||
|
||||
return List.generate(maps.length, (i) {
|
||||
return Movie(
|
||||
id: maps[i]['id'].toString(),
|
||||
title: maps[i]['title'],
|
||||
poster: maps[i]['poster'],
|
||||
rating: maps[i]['rating']?.toDouble(),
|
||||
year: maps[i]['year'],
|
||||
status: maps[i]['status'],
|
||||
watchDate: maps[i]['watch_date'] != null
|
||||
? DateTime.parse(maps[i]['watch_date'])
|
||||
: null,
|
||||
note: maps[i]['note'],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 添加影视记录
|
||||
Future<int> insertMovie(Movie movie) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.insert('movies', movie.toJson());
|
||||
}
|
||||
|
||||
// 更新影视记录
|
||||
Future<int> updateMovie(Movie movie) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.update(
|
||||
'movies',
|
||||
movie.toJson(),
|
||||
where: 'id = ?',
|
||||
whereArgs: [movie.id],
|
||||
);
|
||||
}
|
||||
|
||||
// 删除影视记录
|
||||
Future<int> deleteMovie(String id) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.delete(
|
||||
'movies',
|
||||
where: 'id = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
}
|
||||
}
|
||||
69
lib/utils/note_dao.dart
Normal file
69
lib/utils/note_dao.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import '../models/data_models.dart';
|
||||
import 'database_helper.dart';
|
||||
|
||||
/// 笔记数据访问对象
|
||||
class NoteDao {
|
||||
final DatabaseHelper _dbHelper = DatabaseHelper.instance;
|
||||
|
||||
// 获取所有笔记
|
||||
Future<List<Note>> getAllNotes() async {
|
||||
final db = await _dbHelper.database;
|
||||
final List<Map<String, dynamic>> maps = await db.query(
|
||||
'notes',
|
||||
orderBy: 'updated_at DESC',
|
||||
);
|
||||
|
||||
return List.generate(maps.length, (i) {
|
||||
return Note(
|
||||
id: maps[i]['id'].toString(),
|
||||
title: maps[i]['title'],
|
||||
content: maps[i]['content'],
|
||||
tags: maps[i]['tags'] != null
|
||||
? List<String>.from(maps[i]['tags'].split(','))
|
||||
: [],
|
||||
createdAt: DateTime.parse(maps[i]['created_at']),
|
||||
updatedAt: DateTime.parse(maps[i]['updated_at']),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 添加笔记
|
||||
Future<int> insertNote(Note note) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.insert('notes', {
|
||||
'id': note.id,
|
||||
'title': note.title,
|
||||
'content': note.content,
|
||||
'tags': note.tags.join(','),
|
||||
'created_at': note.createdAt.toIso8601String(),
|
||||
'updated_at': note.updatedAt.toIso8601String(),
|
||||
});
|
||||
}
|
||||
|
||||
// 更新笔记
|
||||
Future<int> updateNote(Note note) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.update(
|
||||
'notes',
|
||||
{
|
||||
'title': note.title,
|
||||
'content': note.content,
|
||||
'tags': note.tags.join(','),
|
||||
'updated_at': note.updatedAt.toIso8601String(),
|
||||
},
|
||||
where: 'id = ?',
|
||||
whereArgs: [note.id],
|
||||
);
|
||||
}
|
||||
|
||||
// 删除笔记
|
||||
Future<int> deleteNote(String id) async {
|
||||
final db = await _dbHelper.database;
|
||||
return await db.delete(
|
||||
'notes',
|
||||
where: 'id = ?',
|
||||
whereArgs: [id],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user