提交 cf6afe7a authored 作者: yueweilu's avatar yueweilu

搜索全文

上级 bb4f6e5f
...@@ -318,4 +318,27 @@ abstract class LibraryAPI { ...@@ -318,4 +318,27 @@ abstract class LibraryAPI {
return false; return false;
} }
/// 16、 搜索全文
static Future<List<SearchAllModel>> searchAll({
int page = 1,
int limit = 10,
required String bookId,
required String key
}) async {
final result = await HttpService.to.post(
'/v1/book/Information/searchContent',
params: {
'page': page,
'page_size': limit,
'book_id': bookId,
'key': key
},
);
if (result.data is! Map && result.data['list'] is! List) return [];
return List.generate(result.data['list'].length, (index) {
return SearchAllModel.fromJson(result.data['list'][index]);
});
}
} }
\ No newline at end of file
...@@ -531,4 +531,46 @@ class OssModel { ...@@ -531,4 +531,46 @@ class OssModel {
} }
class SearchAllModel {
SearchAllModel({
this.bookId,
this.chapterId,
this.chapterName,
this.key,
this.combinedContent,});
SearchAllModel.fromJson(dynamic json) {
bookId = json['book_id'];
chapterId = json['chapter_id'];
chapterName = json['chapter_name'];
key = json['key'];
combinedContent = json['combined_content'];
}
String? bookId;
num? chapterId;
String? chapterName;
String? key;
String? combinedContent;
SearchAllModel copyWith({ String? bookId,
num? chapterId,
String? chapterName,
String? key,
String? combinedContent,
}) => SearchAllModel( bookId: bookId ?? this.bookId,
chapterId: chapterId ?? this.chapterId,
chapterName: chapterName ?? this.chapterName,
key: key ?? this.key,
combinedContent: combinedContent ?? this.combinedContent,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['book_id'] = bookId;
map['chapter_id'] = chapterId;
map['chapter_name'] = chapterName;
map['key'] = key;
map['combined_content'] = combinedContent;
return map;
}
}
...@@ -66,6 +66,21 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -66,6 +66,21 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 是否展示搜索结果 // 是否展示搜索结果
bool showSearch = false; bool showSearch = false;
final int _searchLimit = 10;
int _searchPage = 1;
bool _searchNoMore = false;
// 搜全文
List<SearchAllModel> searchALlResults = [];
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
late TextEditingController searchInput = TextEditingController();
///------------------------------------------ 页面 生命周期-------------------------------------------------------- ///------------------------------------------ 页面 生命周期--------------------------------------------------------
@override @override
...@@ -112,6 +127,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -112,6 +127,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
titleInput.dispose(); titleInput.dispose();
contentInput.dispose(); contentInput.dispose();
flutterTts.stop(); flutterTts.stop();
searchInput.dispose();
super.onClose(); super.onClose();
} }
///------------------------------------------ 页面 生命周期-------------------------------------------------------- ///------------------------------------------ 页面 生命周期--------------------------------------------------------
...@@ -729,8 +745,6 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -729,8 +745,6 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
update(); update();
} }
/// 搜索全文
/// 添加阅读时长 /// 添加阅读时长
void _addReadTime({required type}) async{ void _addReadTime({required type}) async{
...@@ -760,6 +774,50 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -760,6 +774,50 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
} }
/// 搜全文
Future<void> searchAll([bool isRefresh = false]) async {
if (isRefresh) _searchPage = 1;
// 网路请求
final result = await LibraryAPI.searchAll(
page: _searchPage,
limit: _searchLimit,
bookId: bookDetailModel.bookId.toString(),
key: searchInput.text
);
Console.log('--------------------------------');
// 如果是刷新 清理数据
if (isRefresh) searchALlResults.clear();
searchALlResults.addAll(result);
_searchPage ++;
_searchNoMore = result.length < _searchLimit;
update();
}
void onRefreshSearch() async {
try {
await searchAll(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
Console.log('--error-----------------------------$error-');
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoadingSearch() async {
if (_searchNoMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await searchAll();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
///------------------------------------------ app 生命周期-------------------------------------------------------- ///------------------------------------------ app 生命周期--------------------------------------------------------
......
...@@ -18,6 +18,11 @@ class DiscussController extends GetxController { ...@@ -18,6 +18,11 @@ class DiscussController extends GetxController {
int _page = 1; int _page = 1;
bool _noMore = false; bool _noMore = false;
final int _searchLimit = 10;
int _searchPage = 1;
bool _searchNoMore = false;
// 展示回复输入框 // 展示回复输入框
bool showReply = false; bool showReply = false;
// 当前要回复的模型 // 当前要回复的模型
...@@ -25,6 +30,9 @@ class DiscussController extends GetxController { ...@@ -25,6 +30,9 @@ class DiscussController extends GetxController {
// 是否展示搜索结果 // 是否展示搜索结果
bool showSearch = false; bool showSearch = false;
// 搜全文
List<SearchAllModel> searchALlResults = [];
@override @override
void onReady() { void onReady() {
...@@ -53,6 +61,7 @@ class DiscussController extends GetxController { ...@@ -53,6 +61,7 @@ class DiscussController extends GetxController {
update(); update();
} }
Future<bool> submit() async { Future<bool> submit() async {
Map<String,dynamic> contentMap = { Map<String,dynamic> contentMap = {
...@@ -82,6 +91,52 @@ class DiscussController extends GetxController { ...@@ -82,6 +91,52 @@ class DiscussController extends GetxController {
return result; return result;
} }
/// 搜全文
Future<void> searchAll([bool isRefresh = false]) async {
if (isRefresh) _searchPage = 1;
// 网路请求
final result = await LibraryAPI.searchAll(
page: _searchPage,
limit: _searchLimit,
bookId: bookDetailModel.bookId.toString(),
key: searchInput.text
);
testData();
Console.log('--------------------------------');
// 如果是刷新 清理数据
if (isRefresh) searchALlResults.clear();
searchALlResults.addAll(result);
_searchPage ++;
_searchNoMore = result.length < _searchLimit;
update();
}
void onRefreshSearch() async {
try {
await searchAll(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
Console.log('--error-----------------------------$error-');
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoadingSearch() async {
if (_searchNoMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await searchAll();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
/// 获取讨论详情 /// 获取讨论详情
Future<void> _getDiscuss([bool isRefresh = false]) async { Future<void> _getDiscuss([bool isRefresh = false]) async {
if (isRefresh) _page = 1; if (isRefresh) _page = 1;
...@@ -126,4 +181,14 @@ class DiscussController extends GetxController { ...@@ -126,4 +181,14 @@ class DiscussController extends GetxController {
} }
} }
void testData(){
// String? bookId, num? chapterId, String? chapterName, String? key, String? combinedContent,
searchALlResults.addAll([
SearchAllModel(bookId: '123',chapterId: 333,chapterName: '你好',key: '我是',combinedContent: '我是谁啊'),
SearchAllModel(bookId: '13',chapterId: 22,chapterName: '哈哈哈',key: '你是',combinedContent: '你是谁啊')
]);
}
} }
\ No newline at end of file
...@@ -12,6 +12,8 @@ class NoteController extends GetxController { ...@@ -12,6 +12,8 @@ class NoteController extends GetxController {
controlFinishRefresh: true, controlFinishRefresh: true,
); );
late TextEditingController searchInput = TextEditingController();
final int _limit = 10; final int _limit = 10;
int _page = 1; int _page = 1;
bool _noMore = false; bool _noMore = false;
...@@ -19,6 +21,13 @@ class NoteController extends GetxController { ...@@ -19,6 +21,13 @@ class NoteController extends GetxController {
// 是否展示搜索结果 // 是否展示搜索结果
bool showSearch = false; bool showSearch = false;
final int _searchLimit = 10;
int _searchPage = 1;
bool _searchNoMore = false;
// 搜全文
List<SearchAllModel> searchALlResults = [];
@override @override
void onReady() { void onReady() {
...@@ -29,6 +38,7 @@ class NoteController extends GetxController { ...@@ -29,6 +38,7 @@ class NoteController extends GetxController {
@override @override
void onClose() { void onClose() {
refreshController.dispose(); refreshController.dispose();
searchInput.dispose();
super.onClose(); super.onClose();
} }
...@@ -37,6 +47,50 @@ class NoteController extends GetxController { ...@@ -37,6 +47,50 @@ class NoteController extends GetxController {
update(); update();
} }
/// 搜全文
Future<void> searchAll([bool isRefresh = false]) async {
if (isRefresh) _searchPage = 1;
// 网路请求
final result = await LibraryAPI.searchAll(
page: _searchPage,
limit: _searchLimit,
bookId: bookDetailModel.bookId.toString(),
key: searchInput.text
);
Console.log('--------------------------------');
// 如果是刷新 清理数据
if (isRefresh) searchALlResults.clear();
searchALlResults.addAll(result);
_searchPage ++;
_searchNoMore = result.length < _searchLimit;
update();
}
void onRefreshSearch() async {
try {
await searchAll(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
Console.log('--error-----------------------------$error-');
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoadingSearch() async {
if (_searchNoMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await searchAll();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
/// 获取笔记列表 /// 获取笔记列表
Future<void> _getNotes([bool isRefresh = false]) async { Future<void> _getNotes([bool isRefresh = false]) async {
if (isRefresh) _page = 1; if (isRefresh) _page = 1;
......
...@@ -56,7 +56,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -56,7 +56,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(17.5.w), borderRadius: BorderRadius.circular(17.5.w),
child: CustomInputSearch( child: CustomInputSearch(
// controller: controller.searchInput, controller: widget.controller.searchInput,
readOnly: false, readOnly: false,
hintText: '搜索全文---目录', hintText: '搜索全文---目录',
onTap: () { onTap: () {
...@@ -64,6 +64,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -64,6 +64,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
}, },
onEditingComplete: () { onEditingComplete: () {
widget.controller.setShowSearch(true); widget.controller.setShowSearch(true);
widget.controller.onRefreshSearch();
Tools.unfocus(); Tools.unfocus();
}, },
), ),
...@@ -82,11 +83,15 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -82,11 +83,15 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
):const SizedBox(), ):const SizedBox(),
], ],
), ),
widget.controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){ widget.controller.showSearch? Expanded(
child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) { if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!(); widget.onTapSearchItem!();
} }
},)): },
searchALlResults: widget.controller.searchALlResults
,)):
widget.controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.controller.bookDetailModel,), widget.controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.controller.bookDetailModel,),
widget.controller.showSearch?const SizedBox():Expanded( widget.controller.showSearch?const SizedBox():Expanded(
child: ListView.builder( child: ListView.builder(
......
...@@ -65,6 +65,7 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -65,6 +65,7 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
}, },
onEditingComplete: () { onEditingComplete: () {
controller.setShowSearch(true); controller.setShowSearch(true);
controller.onRefreshSearch();
Tools.unfocus(); Tools.unfocus();
}, },
), ),
...@@ -83,11 +84,15 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -83,11 +84,15 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
):const SizedBox(), ):const SizedBox(),
], ],
), ),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){ controller.showSearch? Expanded(
child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) { if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!(); widget.onTapSearchItem!();
} }
},)): },
searchALlResults: controller.searchALlResults,
)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,), controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded( controller.showSearch?const SizedBox():Expanded(
child: Stack( child: Stack(
......
...@@ -55,7 +55,7 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -55,7 +55,7 @@ class _ReadNotePageState extends State<ReadNotePage> {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(17.5.w), borderRadius: BorderRadius.circular(17.5.w),
child: CustomInputSearch( child: CustomInputSearch(
// controller: controller.searchInput, controller: controller.searchInput,
readOnly: false, readOnly: false,
hintText: '搜索全文---笔记', hintText: '搜索全文---笔记',
onTap: () { onTap: () {
...@@ -63,6 +63,7 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -63,6 +63,7 @@ class _ReadNotePageState extends State<ReadNotePage> {
}, },
onEditingComplete: () { onEditingComplete: () {
controller.setShowSearch(true); controller.setShowSearch(true);
controller.onRefreshSearch();
Tools.unfocus(); Tools.unfocus();
}, },
), ),
...@@ -81,11 +82,14 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -81,11 +82,14 @@ class _ReadNotePageState extends State<ReadNotePage> {
):const SizedBox(), ):const SizedBox(),
], ],
), ),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){ controller.showSearch? Expanded(child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) { if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!(); widget.onTapSearchItem!();
} }
},)): },
searchALlResults: controller.searchALlResults
)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,), controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded( controller.showSearch?const SizedBox():Expanded(
child: MediaQuery.removePadding( child: MediaQuery.removePadding(
......
...@@ -2,9 +2,12 @@ part of web; ...@@ -2,9 +2,12 @@ part of web;
class BuildSearchAll extends StatefulWidget { class BuildSearchAll extends StatefulWidget {
final void Function()? onTap; final void Function()? onTap;
final List<SearchAllModel> searchALlResults;
const BuildSearchAll({ const BuildSearchAll({
Key? key, Key? key,
this.onTap this.onTap,
required this.searchALlResults
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -16,26 +19,83 @@ class _BuildSearchAllState extends State<BuildSearchAll> { ...@@ -16,26 +19,83 @@ class _BuildSearchAllState extends State<BuildSearchAll> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView.builder( return ListView.builder(
itemBuilder: (BuildContext context, int index){ itemBuilder: (BuildContext context, int index){
SearchAllModel model = widget.searchALlResults[index];
return GestureDetector( return GestureDetector(
onTap: (){ onTap: (){
if(widget.onTap !=null){ if(widget.onTap !=null){
widget.onTap!(); widget.onTap!();
} }
}, },
child: Container(
color: Colors.red,
height: 110,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('章节名称$index'), Container(
Text('章节内容$index'), // color: Colors.red,
margin: EdgeInsets.only(left: 15.w,top: 8.w),
// height: 110,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(model.chapterName??'',style: TextStyle(fontSize: 11.w,height: 2,color: Colours.c9,fontWeight: Fonts.medium),),
Gaps.vGaps5,
ColoredText(text: model.combinedContent??'', coloredSubstring: model.key??'', coloredTextStyle: TextStyle(fontSize: 13.w,height: 2,color: AppTheme.primary),),
], ],
), ),
), ),
Gaps.vGaps10,
Container(height: 0.5.w,color: Colours.cF2,)
],
)
); );
}, },
itemCount: 3, itemCount: widget.searchALlResults.length,
);
}
}
class ColoredText extends StatelessWidget {
final String text;
final String coloredSubstring;
final TextStyle coloredTextStyle;
const ColoredText({super.key,
required this.text,
required this.coloredSubstring,
required this.coloredTextStyle,
});
@override
Widget build(BuildContext context) {
return RichText(
text: TextSpan(
style: TextStyle(fontSize: 13.w,height: 2,color: Colours.c3),
children: _buildTextSpans(),
),
); );
} }
List<TextSpan> _buildTextSpans() {
final List<TextSpan> spans = [];
final int substringIndex = text.indexOf(coloredSubstring);
if (substringIndex != -1) {
spans.add(TextSpan(
text: text.substring(0, substringIndex),
));
spans.add(TextSpan(
text: coloredSubstring,
style: coloredTextStyle,
));
spans.add(TextSpan(
text: text.substring(substringIndex + coloredSubstring.length),
));
} else {
spans.add(TextSpan(text: text));
}
return spans;
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论