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

搜索全文

上级 bb4f6e5f
......@@ -318,4 +318,27 @@ abstract class LibraryAPI {
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 {
}
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
// 是否展示搜索结果
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
......@@ -112,6 +127,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
titleInput.dispose();
contentInput.dispose();
flutterTts.stop();
searchInput.dispose();
super.onClose();
}
///------------------------------------------ 页面 生命周期--------------------------------------------------------
......@@ -729,8 +745,6 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
update();
}
/// 搜索全文
/// 添加阅读时长
void _addReadTime({required type}) async{
......@@ -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 生命周期--------------------------------------------------------
......
......@@ -18,6 +18,11 @@ class DiscussController extends GetxController {
int _page = 1;
bool _noMore = false;
final int _searchLimit = 10;
int _searchPage = 1;
bool _searchNoMore = false;
// 展示回复输入框
bool showReply = false;
// 当前要回复的模型
......@@ -25,6 +30,9 @@ class DiscussController extends GetxController {
// 是否展示搜索结果
bool showSearch = false;
// 搜全文
List<SearchAllModel> searchALlResults = [];
@override
void onReady() {
......@@ -53,6 +61,7 @@ class DiscussController extends GetxController {
update();
}
Future<bool> submit() async {
Map<String,dynamic> contentMap = {
......@@ -82,6 +91,52 @@ class DiscussController extends GetxController {
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 {
if (isRefresh) _page = 1;
......@@ -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 {
controlFinishRefresh: true,
);
late TextEditingController searchInput = TextEditingController();
final int _limit = 10;
int _page = 1;
bool _noMore = false;
......@@ -19,6 +21,13 @@ class NoteController extends GetxController {
// 是否展示搜索结果
bool showSearch = false;
final int _searchLimit = 10;
int _searchPage = 1;
bool _searchNoMore = false;
// 搜全文
List<SearchAllModel> searchALlResults = [];
@override
void onReady() {
......@@ -29,6 +38,7 @@ class NoteController extends GetxController {
@override
void onClose() {
refreshController.dispose();
searchInput.dispose();
super.onClose();
}
......@@ -37,6 +47,50 @@ class NoteController extends GetxController {
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 {
if (isRefresh) _page = 1;
......
......@@ -56,7 +56,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
child: ClipRRect(
borderRadius: BorderRadius.circular(17.5.w),
child: CustomInputSearch(
// controller: controller.searchInput,
controller: widget.controller.searchInput,
readOnly: false,
hintText: '搜索全文---目录',
onTap: () {
......@@ -64,6 +64,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
},
onEditingComplete: () {
widget.controller.setShowSearch(true);
widget.controller.onRefreshSearch();
Tools.unfocus();
},
),
......@@ -82,11 +83,15 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
):const SizedBox(),
],
),
widget.controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
widget.controller.showSearch? Expanded(
child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
},
searchALlResults: widget.controller.searchALlResults
,)):
widget.controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.controller.bookDetailModel,),
widget.controller.showSearch?const SizedBox():Expanded(
child: ListView.builder(
......
......@@ -65,6 +65,7 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
},
onEditingComplete: () {
controller.setShowSearch(true);
controller.onRefreshSearch();
Tools.unfocus();
},
),
......@@ -83,11 +84,15 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
):const SizedBox(),
],
),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
controller.showSearch? Expanded(
child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
},
searchALlResults: controller.searchALlResults,
)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded(
child: Stack(
......
......@@ -55,7 +55,7 @@ class _ReadNotePageState extends State<ReadNotePage> {
child: ClipRRect(
borderRadius: BorderRadius.circular(17.5.w),
child: CustomInputSearch(
// controller: controller.searchInput,
controller: controller.searchInput,
readOnly: false,
hintText: '搜索全文---笔记',
onTap: () {
......@@ -63,6 +63,7 @@ class _ReadNotePageState extends State<ReadNotePage> {
},
onEditingComplete: () {
controller.setShowSearch(true);
controller.onRefreshSearch();
Tools.unfocus();
},
),
......@@ -81,11 +82,14 @@ class _ReadNotePageState extends State<ReadNotePage> {
):const SizedBox(),
],
),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
controller.showSearch? Expanded(child: BuildSearchAll(
onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
},
searchALlResults: controller.searchALlResults
)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded(
child: MediaQuery.removePadding(
......
......@@ -2,9 +2,12 @@ part of web;
class BuildSearchAll extends StatefulWidget {
final void Function()? onTap;
final List<SearchAllModel> searchALlResults;
const BuildSearchAll({
Key? key,
this.onTap
this.onTap,
required this.searchALlResults
}) : super(key: key);
@override
......@@ -16,26 +19,83 @@ class _BuildSearchAllState extends State<BuildSearchAll> {
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (BuildContext context, int index){
SearchAllModel model = widget.searchALlResults[index];
return GestureDetector(
onTap: (){
if(widget.onTap !=null){
widget.onTap!();
}
},
child: Container(
color: Colors.red,
height: 110,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('章节名称$index'),
Text('章节内容$index'),
Container(
// 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论