提交 e9ef4778 authored 作者: maodou's avatar maodou

Merge remote-tracking branch 'origin/test' into test

......@@ -110,6 +110,26 @@ abstract class AccountAPI {
return false;
}
/// 6、验证验证码
static Future checkCode({
required String phone,
required String code,
}) async {
final result = await HttpService.to.post(
'/v1/members/login/checkPhoneCode',
params: {
'phone': phone,
'code': code
},
excludeToken: true,
showLoading: true,
);
if (result.data is Map && result.data['is_success'] == 1){
return true;
}
return false;
}
......
......@@ -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;
}
}
library answer;
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import '../../utils/index.dart';
part 'view.dart';
\ No newline at end of file
part of answer;
class AnswerPage extends StatefulWidget {
final Map<String,String> params;
const AnswerPage({
Key? key,
required this.params
}) : super(key: key);
@override
State<AnswerPage> createState() => _AnswerPageState();
}
class _AnswerPageState extends State<AnswerPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('知识测评'),
),
body: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse(widget.params['url']??''),
),
onLoadStop: (controller, url) {
String str = '${widget.params['book_id']},${widget.params['chapter_id']},${widget.params['token']},${widget.params['position']}';
Console.log('知识测评--------传给前端的参数--------------------------------$str');
controller.evaluateJavascript(source: 'callbackInFlutterComponent("$str");');
},
onConsoleMessage: (controller, consoleMessage) {
// 接收从 WebView 发送的消息
Console.log("知识测评-------Received message from WebView-----------------------------: ${consoleMessage.message}");
},
)
);
}
}
......@@ -84,6 +84,12 @@ class ForgetPwdController extends GetxController {
else{
Toast.show('发送失败');
}
}
Future<bool> checkCode() async {
final result = await AccountAPI.checkCode(phone: phoneInput.text, code: codeInput.text);
return result;
}
}
\ No newline at end of file
......@@ -72,8 +72,14 @@ class _ForgetPwdPageState extends State<ForgetPwdPage> {
CustomGradientButton(
text: '下一步',
isEnabled: controller.enable,
onPressed: () {
onPressed: () async {
final result = await controller.checkCode();
if (result){
context.pushNamed(Routes.resetPwd,queryParameters: {'phone': controller.phoneInput.text,'code': controller.codeInput.text});
}
else{
Toast.show('验证码错误');
}
},
)
],
......
......@@ -6,6 +6,8 @@ class HelpCenterContentController extends GetxController {
HelpCenterContentController(this.id);
late InAppWebViewController webViewController;
@override
void onReady() {
_getHelpCenterContent(id);
......@@ -15,6 +17,7 @@ class HelpCenterContentController extends GetxController {
/// 获取帮助中心内容
void _getHelpCenterContent(String id) async {
helpCenterContentModel = await MineAPI.helpCenterContent(id);
webViewController.loadData(data: helpCenterContentModel.helpContent??'');
update();
}
}
......@@ -20,14 +20,14 @@ class _HelpCenterContentPageState extends State<HelpCenterContentPage> {
Widget build(BuildContext context) {
return GetBuilder<HelpCenterContentController>(
init: HelpCenterContentController(widget.id),
builder: (controller) => Scaffold(
builder: (helpController) => Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(widget.title),
),
body: InAppWebView(
onWebViewCreated: (InAppWebViewController wcontroller){
wcontroller.loadData(data: controller.helpCenterContentModel.helpContent ?? '',);
onWebViewCreated: (InAppWebViewController controller){
helpController.webViewController = controller;
},
),
......
......@@ -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,6 +745,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
update();
}
/// 添加阅读时长
void _addReadTime({required type}) async{
final result = await LibraryAPI.addReadTime(bookId: bookId, readTypes: type);
......@@ -757,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;
......
......@@ -151,13 +151,31 @@ class _ReadPageState extends State<ReadPage> {
readController.titleInput.text = args.first.toString();
});
controller.addJavaScriptHandler(handlerName: 'answerCallBack', callback: (args){
controller.addJavaScriptHandler(handlerName: 'answerResultCallBack', callback: (args){
Console.log('监听答题回调------------------------------------------------$args');
});
String chapterId = args.first[0].toString();
String position = args.first[1].toString();
String type = args.first[2].toString();
String url = '';
// 未答题
if(type == '0'){
url = kAnswer;
}
else {
url = kAnswerResult;
}
Map<String,String> params = {
'chapter_id':chapterId,
'position':position,
'url':url,
'book_id':readController.bookId,
'token':UserStore.to.token
};
Console.log('监听答题回调---------------给页面传参---------------------------------$params');
context.pushNamed(Routes.answer,queryParameters: params);
controller.addJavaScriptHandler(handlerName: 'answerResultCallBack', callback: (args){
Console.log('监听答题结果回调------------------------------------------------$args');
// 跳转知识测评界面
});
......
......@@ -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;
}
}
......@@ -7,8 +7,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import '../../models/index.dart';
import '../../routes/index.dart';
import '../../theme.dart';
import '../../utils/index.dart';
import '../../widgets/index.dart';
......
......@@ -23,7 +23,12 @@ class _StudyHistoryPageState extends State<StudyHistoryPage> {
onLoading: controller.onLoading,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return BuildDayItem(historyModel: controller.histories[index],);
return BuildDayItem(
historyModel: controller.histories[index],
onTap: (CourseModel courseModel){
context.pushNamed(Routes.bookDetail,queryParameters: {'book_id':courseModel.bookId.toString()});
},
);
},
itemCount: controller.histories.length,
),
......
......@@ -2,9 +2,11 @@ part of study_history;
class BuildDayItem extends StatelessWidget {
final StudyHistoryModel historyModel;
final void Function(CourseModel courseModel) onTap;
const BuildDayItem({
Key? key,
required this.historyModel
required this.historyModel,
required this.onTap
}) : super(key: key);
@override
......@@ -43,7 +45,11 @@ class BuildDayItem extends StatelessWidget {
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder:(BuildContext context, int index){
return _buildItem(historyModel.courses[index]);
return GestureDetector(
onTap: (){
onTap(historyModel.courses[index]);
},
child: _buildItem(historyModel.courses[index]));
},
itemCount: historyModel.courses.length,
)
......@@ -54,6 +60,7 @@ class BuildDayItem extends StatelessWidget {
Widget _buildItem(CourseModel courseModel){
return Container(
color: Colors.white,
margin: EdgeInsets.only(left: 10.w,right: 10.w),
child: Column(
children: [
......
......@@ -3,6 +3,7 @@ library routes;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_book/pages/ad/index.dart';
import 'package:flutter_book/pages/answer/index.dart';
import 'package:flutter_book/pages/book_detail/index.dart';
import 'package:flutter_book/pages/book_pay/index.dart';
import 'package:flutter_book/pages/book_score/index.dart';
......
......@@ -9,7 +9,10 @@ abstract class Routes {
static const ad = 'ad';
static const adDetail = 'ad_detail';
static const web = 'read_web';
static const answer = 'answer';
// 支付界面
static const bookPay = 'book_pay';
......@@ -639,6 +642,17 @@ abstract class Routes {
)
)
),
GoRoute( // 知识测评
path: '/$answer',
name: answer,
pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(),
key: state.pageKey,
child: AnswerPage(
params: state.uri.queryParameters,
)
)
),
]
);
......
......@@ -29,6 +29,7 @@ class HttpService extends GetxService {
headers['appSecret'] = AppConfig.appSecret;
headers['timestamp'] = (DateTime.now().millisecondsSinceEpoch~/1000).toString();
headers['url'] = kServerUrl + url.toString();
headers['token'] = UserStore.to.token;
if (Get.isRegistered<UserStore>() &&
UserStore.to.hasToken && !excludeToken) {
......@@ -44,7 +45,6 @@ class HttpService extends GetxService {
else {
headers['Sign'] = SignTool.createSign(headers);
}
// Console.log(headers);
return headers;
}
......
......@@ -23,6 +23,8 @@ const String kUserWrongDes = 'http://150.158.138.40:9200/evaluating_wrong.html';
const String kReadBook = 'http://150.158.138.40:9200/read.html';
// 答题页
const String kAnswer = 'http://150.158.138.40:9200/evaluating.html';
// 答题结果页
const String kAnswerResult = 'http://150.158.138.40:9200/evaluating_result.html';
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论