提交 26d783a7 authored 作者: yueweilu's avatar yueweilu

sqlite

上级 7d0e3e5b
...@@ -16,6 +16,11 @@ class Global { ...@@ -16,6 +16,11 @@ class Global {
// InAppLocalhostServer(documentRoot: '$documentRoot/',shared: true); // InAppLocalhostServer(documentRoot: '$documentRoot/',shared: true);
// await localhostServer.start(); // await localhostServer.start();
// print('本地服务器已成功启动,根目录为: $documentRoot'); // print('本地服务器已成功启动,根目录为: $documentRoot');
SqlManager.init();
WidgetsBinding.instance?.addObserver(AppLifecycleObserver());
await Future.wait([ await Future.wait([
// 配置存储 // 配置存储
...@@ -32,4 +37,12 @@ class Global { ...@@ -32,4 +37,12 @@ class Global {
}); });
} }
}
class AppLifecycleObserver extends WidgetsBindingObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused || state == AppLifecycleState.detached) {
SqlManager.closeDatabase(); // 应用进入后台时关闭数据库连接
}
}
} }
\ No newline at end of file
...@@ -26,8 +26,11 @@ void main() { ...@@ -26,8 +26,11 @@ void main() {
// print('2222222---------$name'); // print('2222222---------$name');
// final result = EncryptUtil.aesDecrypt(name); // final result = EncryptUtil.aesDecrypt(name);
// Console.log('解密--------------------------$result'); // Console.log('解密--------------------------$result');
runApp(const MyApp()); runApp(const MyApp());
//FlutterNativeSplash.remove(); //FlutterNativeSplash.remove();
}); });
}); });
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
......
...@@ -175,6 +175,21 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -175,6 +175,21 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
/// 获取tab分类数据 /// 获取tab分类数据
void _getTabs() async { void _getTabs() async {
Map<String, dynamic> data = {
'types': 1,
'book_id': 123,
'chapter_id': 456,
// 'is_open': 1,
// 'color': 'blue',
// 'content': 'This is a note content',
// 'del': 0,
// 'positioning': 'top',
// 'note': 'This is a note',
};
await SqlManager.insertData(data);
categories = await LibraryAPI.categories(); categories = await LibraryAPI.categories();
tabController.dispose(); tabController.dispose();
tabController = TabController(length:categories.length, vsync: this); tabController = TabController(length:categories.length, vsync: this);
......
...@@ -57,6 +57,10 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -57,6 +57,10 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 网络状态 // 网络状态
bool netStatus = false; bool netStatus = false;
// 当前html名称 0-318.html
late String currentHtmlName = '';
///------------------------------------------ 页面 生命周期-------------------------------------------------------- ///------------------------------------------ 页面 生命周期--------------------------------------------------------
@override @override
void onInit() { void onInit() {
...@@ -73,19 +77,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -73,19 +77,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
_getChapters(); _getChapters();
netStatus = await Tools.checkCurrentNetStatus(); netStatus = await Tools.checkCurrentNetStatus();
// // 判断是否有离线文件 如果有使用离线阅读 // // 判断是否有离线文件 如果有使用离线阅读
// final exist = await _isExistFile(bookId); readLocalHtml('');
// // 没有网并且有离线文件 离线阅读 readChapter(type: 1);
// String path = await _getDirectory();
// String finalPath = '$path/174/0-318.html';
// final content = await readHtmlFileContent(finalPath);
// Console.log('原始内容-----------------$content');
// String htmlStr = EncryptUtil.aesDecrypt(content!);
// Console.log('解密-----------------$htmlStr');
// if (netStatus && exist){
// Console.log('-------------使用本地文件-------------------');
// webViewController.loadData(data: htmlStr??'');
// }
super.onReady(); super.onReady();
} }
...@@ -102,6 +95,21 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -102,6 +95,21 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
} }
///------------------------------------------ 页面 生命周期-------------------------------------------------------- ///------------------------------------------ 页面 生命周期--------------------------------------------------------
void chooseTool(ToolModel selectedModel){
for (var model in tools) {
// 如果当前遍历到的工具是选中的,并且不是点击的工具,则取消选中
if (model.selected && model != selectedModel) {
model.selected = false;
}
// 如果当前遍历到的工具是点击的工具,切换选中状态
else if (model == selectedModel) {
model.selected = !model.selected;
}
}
toolModel = selectedModel;
update();
}
void setShow(bool value) { void setShow(bool value) {
_show = !value; _show = !value;
update(); update();
...@@ -364,22 +372,6 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -364,22 +372,6 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
void chooseTool(ToolModel selectedModel){
for (var model in tools) {
// 如果当前遍历到的工具是选中的,并且不是点击的工具,则取消选中
if (model.selected && model != selectedModel) {
model.selected = false;
}
// 如果当前遍历到的工具是点击的工具,切换选中状态
else if (model == selectedModel) {
model.selected = !model.selected;
}
}
toolModel = selectedModel;
update();
}
// AnimationController get controller => _controller; // AnimationController get controller => _controller;
void _onCommentFocusChanged() { void _onCommentFocusChanged() {
...@@ -412,45 +404,14 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -412,45 +404,14 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
/// 获取目录信息 ///------------------------------------------离线逻辑--------------------------------------------------------
void _getChapters() async {
chapters = await LibraryAPI.chapters(bookId: bookId);
update();
}
/// 添加阅读时长
void _addReadTime({required type}) async{
final result = await LibraryAPI.addReadTime(bookId: bookId, readTypes: type);
}
/// 获取离线文件路径
void getBookDown() async{
final exit = await _isExistFile(bookId);
// 存在离线文件
if (exit){
}
else{
final result = await LibraryAPI.getbookDownloadParam(bookId: bookId);
Console.log('----------_getBookDown------------------${result.download}');
// final String savePath = await _getDirectory();
// LibraryAPI.downBookByUrl(url: result.download!,savePath: '$savePath$bookId.zip',onReceiveProgress: (int received,int total){
// if (total !=-1){
// double progress = (received / total) * 100;
// Console.log('Download progress: $progress%');
// }
// });
extractZipFileFromCache(result.download!);
}
}
// 下载文件 // 下载文件
Future<void> extractZipFileFromCache(String url) async { Future<void> extractZipFileFromCache(String url) async {
// 从缓存中获取 ZIP 文件 // 从缓存中获取 ZIP 文件
var file = await DefaultCacheManager().getSingleFile(url); var file = await DefaultCacheManager().getSingleFile(url);
if (file != null) { if (file != null) {
Toast.show('离线成功');
// 读取 ZIP 文件内容 // 读取 ZIP 文件内容
Uint8List bytes = await file.readAsBytes(); Uint8List bytes = await file.readAsBytes();
// 解压缩 ZIP 文件 // 解压缩 ZIP 文件
...@@ -468,12 +429,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -468,12 +429,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
print('解压缩文件:$fileName,保存路径:$filePath'); print('解压缩文件:$fileName,保存路径:$filePath');
} }
} }
} else { } else {
print('未找到缓存中的文件或文件不存在'); print('未找到缓存中的文件或文件不存在');
} }
} }
// 判断是否存在离线文件 // 判断是否存在离线文件
Future<bool> _isExistFile(String bookId) async { Future<bool> _isExistFile(String bookId) async {
String directoryPath = await _getDirectory(); String directoryPath = await _getDirectory();
...@@ -493,6 +454,48 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -493,6 +454,48 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
} }
// 本地阅读 读取上一章节 或 下一章节
// 0 上一章节
// 1 下一章节
Future<String> readChapter({required int type}) async {
Console.log('---------------获取所有html---------------------------------');
String docPath = await _getDirectory();
String filePath = '$docPath/$bookId';
Directory directory = Directory(filePath);
// 获取目录下的所有文件
List<FileSystemEntity> files = directory.listSync(recursive: true);
int findIndex = int.parse(currentHtmlName.split('-').first);
currentHtmlName;
if(type == 0){
findIndex--;
if(findIndex <0){
// 已到最前
return '-1';
}
}
else{
findIndex++;
if(findIndex >files.length -1){
// 已到最后
return '1';
}
}
// 打印所有 HTML 文件路径
for (var file in files) {
if (file is File && file.path.toLowerCase().endsWith('.html')) {
String fileName = path.basename(file.path);
if (int.parse(fileName.split('-').first) == 2){
print('HTML File--------------------------------${file.path}');
return file.path;
}
}
}
return '0';
}
// 读取html内容 // 读取html内容
Future<String?> readHtmlFileContent(String filePath) async { Future<String?> readHtmlFileContent(String filePath) async {
try { try {
...@@ -514,6 +517,40 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -514,6 +517,40 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
return directory!.path; return directory!.path;
} }
/// 获取目录信息
void _getChapters() async {
chapters = await LibraryAPI.chapters(bookId: bookId);
update();
}
/// 添加阅读时长
void _addReadTime({required type}) async{
final result = await LibraryAPI.addReadTime(bookId: bookId, readTypes: type);
}
/// 获取离线文件路径
void getBookDown() async{
final exit = await _isExistFile(bookId);
// 存在离线文件
if (exit){
}
else{
final result = await LibraryAPI.getbookDownloadParam(bookId: bookId);
Console.log('----------_getBookDown------------------${result.download}');
// final String savePath = await _getDirectory();
// LibraryAPI.downBookByUrl(url: result.download!,savePath: '$savePath$bookId.zip',onReceiveProgress: (int received,int total){
// if (total !=-1){
// double progress = (received / total) * 100;
// Console.log('Download progress: $progress%');
// }
// });
extractZipFileFromCache(result.download!);
}
}
///------------------------------------------ app 生命周期-------------------------------------------------------- ///------------------------------------------ app 生命周期--------------------------------------------------------
// 当应用程序从后台切换到前台并变为活动状态时调用。这通常在用户从其他应用程序返回到你的应用程序时发生 // 当应用程序从后台切换到前台并变为活动状态时调用。这通常在用户从其他应用程序返回到你的应用程序时发生
......
...@@ -34,6 +34,7 @@ import '../../widgets/index.dart'; ...@@ -34,6 +34,7 @@ import '../../widgets/index.dart';
import '../book_category/index.dart'; import '../book_category/index.dart';
import '../user_discuss_des/index.dart'; import '../user_discuss_des/index.dart';
import '../user_notes_des/index.dart'; import '../user_notes_des/index.dart';
import 'package:path/path.dart' as path;
part 'view.dart'; part 'view.dart';
part 'controller.dart'; part 'controller.dart';
......
...@@ -64,8 +64,8 @@ class _ReadPageState extends State<ReadPage> { ...@@ -64,8 +64,8 @@ class _ReadPageState extends State<ReadPage> {
children: [ children: [
InAppWebView( InAppWebView(
initialUrlRequest: URLRequest( initialUrlRequest: URLRequest(
// url: Uri.parse('http://150.158.138.40:9200/read.html'), url: Uri.parse('http://150.158.138.40:9200/read.html'),
url: Uri.parse("/storage/emulated/0/Android/data/com.zijin.book.flutter_book/files/174/7-325.html"), // url: Uri.parse("/storage/emulated/0/Android/data/com.zijin.book.flutter_book/files/174/7-325.html"),
), ),
contextMenu: ContextMenu( contextMenu: ContextMenu(
options: ContextMenuOptions(hideDefaultSystemContextMenuItems: true), options: ContextMenuOptions(hideDefaultSystemContextMenuItems: true),
......
...@@ -11,6 +11,8 @@ const String kLocalPassword = 'local_password'; ...@@ -11,6 +11,8 @@ const String kLocalPassword = 'local_password';
const String kLocalUserInfo = 'local_user_info'; const String kLocalUserInfo = 'local_user_info';
const String kSearchHistory = 'search_history'; const String kSearchHistory = 'search_history';
const String kFailOrder = 'failOrder'; const String kFailOrder = 'failOrder';
const String kNoteTable = 'members_book_notes';
const String kReadTable = 'read_history';
......
...@@ -28,6 +28,8 @@ import 'package:flutter_oss_aliyun/flutter_oss_aliyun.dart'; ...@@ -28,6 +28,8 @@ import 'package:flutter_oss_aliyun/flutter_oss_aliyun.dart';
import '../models/index.dart'; import '../models/index.dart';
import '../widgets/index.dart'; import '../widgets/index.dart';
import 'package:sqflite/sqflite.dart';
part 'constants.dart'; part 'constants.dart';
part 'screen.dart'; part 'screen.dart';
...@@ -42,4 +44,5 @@ part 'toast_utils.dart'; ...@@ -42,4 +44,5 @@ part 'toast_utils.dart';
part 'clear_cache_util.dart'; part 'clear_cache_util.dart';
part 'access.dart'; part 'access.dart';
part 'assets_picker.dart'; part 'assets_picker.dart';
part 'oss.dart'; part 'oss.dart';
\ No newline at end of file part 'sql.dart';
\ No newline at end of file
part of utils;
class SqlManager {
static const _version = 1;
static const _name= "zi_jing_app_flutter.db";
static Database? _database;
///初始化
static init() async {
// open the database
var databasesPath = await getDatabasesPath();
// var databasesPath = await Tools.getDirectory();
String dbName = _name;
Console.log('databasesPath---------$databasesPath');
if(databasesPath != null) {
String path = databasesPath + dbName;
if (Platform.isIOS) {
path = "$databasesPath/$dbName";
}
_database = await openDatabase(path, version: _version,
onCreate: (Database db, int version) async {
// When creating the db, create the table
// await db.execute("CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)");
// 笔记表
await db.execute("CREATE TABLE $kNoteTable ("
"id INTEGER PRIMARY KEY, "
"types INTEGER, "
"book_id INTEGER, "
"chapter_id INTEGER, "
"is_open INTEGER, "
"color TEXT, "
"content TEXT, "
"upload INTEGER, "
"positioning TEXT, "
"note TEXT)"
);
// // 阅读章节表
await db.execute("CREATE TABLE $kReadTable ("
"id INTEGER PRIMARY KEY, "
"book_id INTEGER, "
"chapter_id INTEGER)"
);
});
}
}
// 关闭数据库
static Future<void> closeDatabase() async {
await _database?.close();
}
// 查询所有没有上传的数据
static Future<List<Map<String, dynamic>>> queryNoUploadData() async {
List<Map<String, dynamic>> results = await _database!.query(
'members_book_notes',
where: 'upload = ?',
whereArgs: [0],
);
return results.isNotEmpty ? results : [];
}
// 将所有 upload 为 0 的数据的 upload 字段值更新为 1
static Future<void> updateUploadStatus() async {
await _database!.update(
'members_book_notes',
{'upload': 1},
where: 'upload = ?',
whereArgs: [0],
);
}
// 根据 book_id 查询当前读到的 章节
static Future<int> queryDataByBookId(int bookId) async {
List<Map<String, dynamic>> results = await _database!.query(
'read_history',
where: 'book_id = ?',
whereArgs: [bookId],
);
return results.isNotEmpty ? results.first['chapter_id'] : 0;
}
// 根据 book_id 写入当前读到的 章节
static Future<int?> updateReadHistoryBookId(int bookId ,int chapterId) async {
final result = await _database?.update(
'members_book_notes',
{'chapter_id':chapterId},
where: 'book_id = ?',
whereArgs: [bookId],
);
return result;
}
// 插入数据
static Future<void> insertData(Map<String, dynamic> data) async {
final result = await _database?.insert(
'members_book_notes',
data,
conflictAlgorithm: ConflictAlgorithm.replace,
);
Console.log('插入数据-------------------------------$result');
}
// 查询所有数据
static Future<List<Map<String, dynamic>>?> queryAllData() async {
return await _database?.query('members_book_notes');
}
// 根据 ID 查询数据
static Future<Map<String, dynamic>?> queryDataById(int id) async {
List<Map<String, dynamic>> results = await _database!.query(
'members_book_notes',
where: 'id = ?',
whereArgs: [id],
);
return results.isNotEmpty ? results.first : null;
}
// 更新数据
static Future<void> updateData(int id, Map<String, dynamic> newData) async {
await _database?.update(
'members_book_notes',
newData,
where: 'id = ?',
whereArgs: [id],
);
}
// 删除数据
static Future<void> deleteData(int id) async {
await _database?.delete(
'members_book_notes',
where: 'id = ?',
whereArgs: [id],
);
}
}
...@@ -75,6 +75,27 @@ abstract class Tools { ...@@ -75,6 +75,27 @@ abstract class Tools {
// // I am not connected to any network. // // I am not connected to any network.
// } // }
} }
// static void readChapter({required int type}) async {
// Console.log('---------------获取所有html---------------------------------');
// String docPath = await getDirectory();
// String filePath = '$docPath/$1';
// Directory directory = Directory(filePath);
// // 获取目录下的所有文件
// List<FileSystemEntity> files = directory.listSync(recursive: true);
//
// // 打印所有 HTML 文件路径
// for (var file in files) {
// if (file is File && file.path.toLowerCase().endsWith('.html')) {
// Console.log('HTML File: ${file.path}');
// }
// }
// Console.log('---------------获取所有html---------------------------------');
// // 先找到对应文件
// if(type == 0){
//
// }
// }
} }
......
...@@ -867,7 +867,7 @@ packages: ...@@ -867,7 +867,7 @@ packages:
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
sqflite: sqflite:
dependency: transitive dependency: "direct main"
description: description:
name: sqflite name: sqflite
sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
......
...@@ -113,6 +113,8 @@ dependencies: ...@@ -113,6 +113,8 @@ dependencies:
archive: ^3.1.2 archive: ^3.1.2
# 判断当前网络情况 # 判断当前网络情况
connectivity_plus: ^5.0.2 connectivity_plus: ^5.0.2
# 数据库
sqflite: ^2.3.2
dev_dependencies: dev_dependencies:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论