Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
book-app
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
book-app
Commits
36f5cc28
提交
36f5cc28
authored
2月 23, 2024
作者:
yueweilu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
离线逻辑
上级
4f37ba39
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
171 行增加
和
40 行删除
+171
-40
library.dart
lib/apis/library.dart
+16
-0
global.dart
lib/global.dart
+0
-2
controller.dart
lib/pages/book_detail/controller.dart
+2
-0
controller.dart
lib/pages/library/controller.dart
+35
-15
index.dart
lib/pages/library/index.dart
+2
-0
controller.dart
lib/pages/read_web/controller.dart
+105
-19
view.dart
lib/pages/read_web/view.dart
+5
-0
sql.dart
lib/utils/sql.dart
+6
-4
没有找到文件。
lib/apis/library.dart
浏览文件 @
36f5cc28
...
...
@@ -302,5 +302,20 @@ abstract class LibraryAPI {
return
false
;
}
/// 15、批量上传离线笔记、高亮、划线的内容
static
Future
<
bool
>
uploadOffline
({
required
String
node
,
})
async
{
final
result
=
await
HttpService
.
to
.
post
(
'/v1/book/Information/addOfflineNotes'
,
params:
{
'nodes_list'
:
node
,
},
);
if
(
result
.
data
is
Map
&&
result
.
data
[
'is_success'
]
==
1
){
return
true
;
}
return
false
;
}
}
\ No newline at end of file
lib/global.dart
浏览文件 @
36f5cc28
...
...
@@ -18,8 +18,6 @@ class Global {
// print('本地服务器已成功启动,根目录为: $documentRoot');
SqlManager
.
init
();
WidgetsBinding
.
instance
?.
addObserver
(
AppLifecycleObserver
());
await
Future
.
wait
([
...
...
lib/pages/book_detail/controller.dart
浏览文件 @
36f5cc28
...
...
@@ -56,6 +56,8 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt
/// 获取图书详细信息
void
getBookDetails
()
async
{
bookDetails
=
await
LibraryAPI
.
details
(
bookId:
bookId
);
// 将阅读最后章节写入到数据库
SqlManager
.
updateReadHistoryByBookId
(
int
.
parse
(
bookId
),
bookDetails
.
chapterId
!.
toInt
());
update
();
}
/// 收藏 与 取消收藏
...
...
lib/pages/library/controller.dart
浏览文件 @
36f5cc28
...
...
@@ -73,16 +73,38 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
vsync:
this
,
duration:
const
Duration
(
milliseconds:
100
),
);
super
.
onInit
();
}
@override
void
onReady
()
{
void
onReady
()
async
{
// 获取标签数据
_getLabels
();
_getAds
();
onRefresh
();
Map
<
String
,
dynamic
>
data
=
{
'types'
:
1
,
'book_id'
:
175
,
'chapter_id'
:
334
,
'is_open'
:
1
,
'color'
:
'blue'
,
'content'
:
'This is a note content'
,
'upload'
:
0
,
'positioning'
:
'top'
,
'note'
:
'This is a note'
,
'node_id'
:
0
,
};
await
SqlManager
.
insertData
(
data
);
final
result
=
await
Tools
.
checkCurrentNetStatus
();
// 有网络的时候上传 笔记
if
(
result
){
upload
();
}
super
.
onReady
();
}
...
...
@@ -176,20 +198,6 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
/// 获取tab分类数据
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
();
tabController
.
dispose
();
tabController
=
TabController
(
length:
categories
.
length
,
vsync:
this
);
...
...
@@ -232,6 +240,18 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
}
}
/// 批量上传离线笔记、高亮、划线的内容
void
upload
()
async
{
List
<
Map
<
String
,
dynamic
>>
data
=
await
SqlManager
.
queryNoUploadData
();
Console
.
log
(
'查询到的数据----------------------------------------------------
$data
'
);
final
result
=
await
LibraryAPI
.
uploadOffline
(
node:
jsonEncode
(
data
));
// 上传成功后 更新数据库中的字段
if
(
result
)
{
SqlManager
.
updateUploadStatus
();
}
}
/// 获取图书列表数据
Future
<
void
>
_getBooks
([
bool
isRefresh
=
false
])
async
{
...
...
lib/pages/library/index.dart
浏览文件 @
36f5cc28
library
library
;
import
'dart:convert'
;
import
'package:azlistview/azlistview.dart'
;
import
'package:easy_refresh/easy_refresh.dart'
;
import
'package:flutter/material.dart'
;
...
...
lib/pages/read_web/controller.dart
浏览文件 @
36f5cc28
...
...
@@ -75,10 +75,25 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 上报开始阅读时间
_addReadTime
(
type:
'open'
);
_getChapters
();
netStatus
=
await
Tools
.
checkCurrentNetStatus
();
// // 判断是否有离线文件 如果有使用离线阅读
readLocalHtml
(
''
);
readChapter
(
type:
1
);
final
exist
=
await
_isExistFile
(
bookId
);
if
(
netStatus
&&
exist
){
// 1、从数据库中获取读到那个章节
chapterId
=
await
SqlManager
.
queryReadHistoryByBookId
(
int
.
parse
(
bookId
));
chapterName
=
getChapterName
(
chapterId
);
// 2、通过 chapterId 获取 对应离线的 html路径
String
toReadHtmlPath
=
await
getLocalReadHtml
(
chapterId
);
// 3、开始读书
read
(
toReadHtmlPath
);
// 获取当前 文件名称
currentHtmlName
=
path
.
basename
(
toReadHtmlPath
);
update
();
}
super
.
onReady
();
}
...
...
@@ -141,6 +156,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
}
// 初始化录音组件
Future
<
void
>
openTheRecorder
()
async
{
// 获取权限
...
...
@@ -198,7 +215,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
startRecording
=
false
;
final
path
=
await
_mRecorder
.
stopRecorder
();
var
duration
=
await
audioPlayer
.
setFilePath
(
path
!);
print
(
'-----duration---------------------
$duration
------'
);
Console
.
log
(
'-----duration---------------------
$duration
------'
);
AudioModel
audioModel
=
AudioModel
(
path:
path
,
duration:
Tools
.
formatDuration
(
duration
!));
discussInputAudios
.
add
(
audioModel
);
update
();
...
...
@@ -209,7 +226,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
String
twoDigits
(
int
n
)
=>
n
.
toString
().
padLeft
(
2
,
'0'
);
String
twoDigitMinutes
=
twoDigits
(
duration
.
inMinutes
.
remainder
(
60
));
String
twoDigitSeconds
=
twoDigits
(
duration
.
inSeconds
.
remainder
(
60
));
return
'
${duration.inHours}
:
$twoDigitMinutes
:
$
{twoDigitSeconds}
'
;
return
'
${duration.inHours}
:
$twoDigitMinutes
:
$
twoDigitSeconds
'
;
}
...
...
@@ -276,7 +293,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// return result;
OssTool
tool
=
OssTool
(
'zxts-comment-file'
);
final
response
=
await
tool
.
putObjectFile
(
path
);
print
(
'------response--------------------------
${response.realUri}
'
);
Console
.
log
(
'------response--------------------------
${response.realUri}
'
);
return
response
.
realUri
.
toString
();
}
...
...
@@ -426,12 +443,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
File
(
filePath
)
..
createSync
(
recursive:
true
)
..
writeAsBytesSync
(
file
.
content
as
List
<
int
>);
print
(
'解压缩文件:
$fileName
,保存路径:
$filePath
'
);
(
'解压缩文件:
$fileName
,保存路径:
$filePath
'
);
}
}
}
else
{
print
(
'未找到缓存中的文件或文件不存在'
);
Console
.
log
(
'未找到缓存中的文件或文件不存在'
);
}
}
...
...
@@ -441,12 +458,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
Directory
directory
=
Directory
(
directoryPath
);
bool
directoryExists
=
await
directory
.
exists
();
if
(
directoryExists
)
{
print
(
'存在名为 "
$bookId
" 的文件夹'
);
Console
.
log
(
'存在名为 "
$bookId
" 的文件夹'
);
existDownFile
=
await
Directory
(
'
${directory.path}
/
$bookId
'
).
exists
();
}
else
{
print
(
'不存在名为 "
$bookId
" 的文件夹'
);
Console
.
log
(
'不存在名为 "
$bookId
" 的文件夹'
);
existDownFile
=
false
;
}
update
();
...
...
@@ -454,10 +471,46 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
}
Future
<
String
>
getLocalReadHtml
(
String
chapterId
)
async
{
String
docPath
=
await
_getDirectory
();
String
filePath
=
'
$docPath
/
$bookId
'
;
Directory
directory
=
Directory
(
filePath
);
// 获取目录下的所有文件
List
<
FileSystemEntity
>
files
=
directory
.
listSync
(
recursive:
true
);
for
(
var
file
in
files
)
{
if
(
file
is
File
&&
file
.
path
.
toLowerCase
().
endsWith
(
'.html'
))
{
String
fileName
=
path
.
basenameWithoutExtension
(
file
.
path
);
if
(
fileName
.
split
(
'-'
).
last
==
chapterId
){
return
file
.
path
;
}
}
}
return
''
;
}
// 开始阅读离线
void
read
(
String
toReadHtmlPath
)
async
{
// 3、获取 离线文件的内容
final
content
=
await
readHtmlFileContent
(
toReadHtmlPath
);
// 4、解密离线的内容
String
htmlStr
=
EncryptUtil
.
aesDecrypt
(
content
!);
// 5、将离线内容写入临时文件
String
directoryPath
=
path
.
dirname
(
toReadHtmlPath
);
String
writeFilePath
=
'
$directoryPath
/read.html'
;
// 6、创建临时文件
File
file
=
File
(
writeFilePath
);
// 7、将HTML内容写入文件
await
file
.
writeAsString
(
htmlStr
);
webViewController
.
loadUrl
(
urlRequest:
URLRequest
(
url:
Uri
.
parse
(
writeFilePath
),
));
}
// 本地阅读 读取上一章节 或 下一章节
// 0 上一章节
// 1 下一章节
Future
<
String
>
readChapter
({
required
int
type
})
async
{
Future
<
void
>
readChapter
({
required
int
type
})
async
{
Console
.
log
(
'---------------获取所有html---------------------------------'
);
String
docPath
=
await
_getDirectory
();
...
...
@@ -467,33 +520,45 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
List
<
FileSystemEntity
>
files
=
directory
.
listSync
(
recursive:
true
);
int
findIndex
=
int
.
parse
(
currentHtmlName
.
split
(
'-'
).
first
);
currentHtmlName
;
if
(
type
==
0
){
findIndex
--;
if
(
findIndex
<
0
){
Toast
.
show
(
'前面已没有章节'
);
// 已到最前
return
'-1'
;
return
;
}
}
else
{
findIndex
++;
if
(
findIndex
>
files
.
length
-
1
){
// 已到最后
return
'1'
;
return
;
}
}
String
toReadHtmlPath
=
''
;
// 打印所有 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
){
String
fileName
=
path
.
basename
WithoutExtension
(
file
.
path
);
if
(
int
.
parse
(
fileName
.
split
(
'-'
).
first
)
==
findIndex
){
print
(
'HTML File--------------------------------
${file.path}
'
);
return
file
.
path
;
toReadHtmlPath
=
file
.
path
;
chapterId
=
fileName
.
split
(
'-'
).
last
;
chapterName
=
getChapterName
(
chapterId
);
break
;
}
}
}
return
'0'
;
// 开始读书
read
(
toReadHtmlPath
);
update
();
}
// 读取html内容
...
...
@@ -504,12 +569,30 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
return
fileContent
;
}
catch
(
e
){
print
(
'Error reading file:
$e
'
);
Console
.
log
(
'Error reading file:
$e
'
);
return
''
;
}
}
// 通过 chapter_id 获取 chapter_name
String
getChapterName
(
String
chapterId
){
for
(
ChapterModel
model
in
chapters
){
if
(
'
${model.id}
'
==
chapterId
){
return
model
.
name
??
''
;
}
if
(
model
.
children
!=
null
){
for
(
ChapterModel
subModel
in
model
.
children
!){
if
(
'
${subModel.id}
'
==
chapterId
){
return
subModel
.
name
??
''
;
}
}
}
}
return
''
;
}
//获取存储目录
Future
<
String
>
_getDirectory
()
async
{
// getTemporaryDirectory
...
...
@@ -517,6 +600,8 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
return
directory
!.
path
;
}
/// 获取目录信息
void
_getChapters
()
async
{
chapters
=
await
LibraryAPI
.
chapters
(
bookId:
bookId
);
...
...
@@ -526,6 +611,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
/// 添加阅读时长
void
_addReadTime
({
required
type
})
async
{
final
result
=
await
LibraryAPI
.
addReadTime
(
bookId:
bookId
,
readTypes:
type
);
Console
.
log
(
'-------------
$result
-------------------'
);
}
/// 获取离线文件路径
void
getBookDown
()
async
{
...
...
lib/pages/read_web/view.dart
浏览文件 @
36f5cc28
...
...
@@ -120,6 +120,11 @@ class _ReadPageState extends State<ReadPage> {
readController
.
titleInput
.
text
=
args
.
first
.
toString
();
});
// 监听 上一节 下一节
controller
.
addJavaScriptHandler
(
handlerName:
'readCallBack'
,
callback:
(
args
){
});
},
),
// AnimatedPositioned(
...
...
lib/utils/sql.dart
浏览文件 @
36f5cc28
...
...
@@ -32,6 +32,7 @@ class SqlManager {
"types INTEGER, "
"book_id INTEGER, "
"chapter_id INTEGER, "
"node_id INTEGER, "
"is_open INTEGER, "
"color TEXT, "
"content TEXT, "
...
...
@@ -65,15 +66,16 @@ class SqlManager {
}
// 将所有 upload 为 0 的数据的 upload 字段值更新为 1
static
Future
<
void
>
updateUploadStatus
()
async
{
await
_database
!.
update
(
final
result
=
await
_database
!.
update
(
'members_book_notes'
,
{
'upload'
:
1
},
where:
'upload = ?'
,
whereArgs:
[
0
],
);
Console
.
log
(
'更新数据-------------------------------
$result
'
);
}
// 根据 book_id 查询当前读到的 章节
static
Future
<
int
>
queryData
ByBookId
(
int
bookId
)
async
{
static
Future
<
String
>
queryReadHistory
ByBookId
(
int
bookId
)
async
{
List
<
Map
<
String
,
dynamic
>>
results
=
await
_database
!.
query
(
'read_history'
,
where:
'book_id = ?'
,
...
...
@@ -83,9 +85,9 @@ class SqlManager {
}
// 根据 book_id 写入当前读到的 章节
static
Future
<
int
?>
updateReadHistor
yBookId
(
int
bookId
,
int
chapterId
)
async
{
static
Future
<
int
>
updateReadHistoryB
yBookId
(
int
bookId
,
int
chapterId
)
async
{
final
result
=
await
_database
?
.
update
(
final
result
=
await
_database
!
.
update
(
'members_book_notes'
,
{
'chapter_id'
:
chapterId
},
where:
'book_id = ?'
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论