基础功能

This commit is contained in:
DelLevin-Home
2026-03-05 10:06:32 +08:00
commit adad6372a3
55 changed files with 6036 additions and 0 deletions

60
lib/utils/app_router.dart Normal file
View 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
View 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
View 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],
);
}
}

View 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
View 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
View 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],
);
}
}