提交 7c329c54 authored 作者: maodou's avatar maodou

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

# Conflicts: # lib/pages/book_detail/widgets/book.dart
...@@ -5,6 +5,7 @@ import 'package:flutter_book/apis/index.dart'; ...@@ -5,6 +5,7 @@ import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/theme.dart'; import 'package:flutter_book/theme.dart';
import 'package:flutter_book/utils/index.dart'; import 'package:flutter_book/utils/index.dart';
import 'package:flutter_book/widgets/index.dart'; import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_star/custom_rating.dart'; import 'package:flutter_star/custom_rating.dart';
import 'package:flutter_star/star.dart'; import 'package:flutter_star/star.dart';
......
...@@ -85,10 +85,18 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid ...@@ -85,10 +85,18 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid
controller: controller.tabController, controller: controller.tabController,
children: [ children: [
BookCategoryPage(chapters: controller.chapters,bookId: controller.bookId,bookDetails: controller.bookDetails,), BookCategoryPage(chapters: controller.chapters,bookId: controller.bookId,bookDetails: controller.bookDetails,),
Container( // Container(
padding: EdgeInsets.only(left: 15.w,right: 15.w,top:12.w), // padding: EdgeInsets.only(left: 15.w,right: 15.w,top:12.w),
color: Colors.white, // color: Colors.white,
child: Text(controller.bookDetails.content??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c3),), // child: Text(controller.bookDetails.content??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c3),),
// ),
InAppWebView(
contextMenu: ContextMenu(
options: ContextMenuOptions(hideDefaultSystemContextMenuItems: true),
),
onWebViewCreated: (InAppWebViewController wcontroller){
wcontroller.loadData(data: controller.bookDetails.content??'',);
},
), ),
BookInfoPage(model:controller.bookDetails,) BookInfoPage(model:controller.bookDetails,)
], ],
......
...@@ -80,7 +80,7 @@ class BookInfoPage extends StatelessWidget { ...@@ -80,7 +80,7 @@ class BookInfoPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: List.generate(model.ratingList!.length, (index){ children: List.generate(model.ratingList!.length, (index){
return _buildProgrss(5- index.toDouble(), model.ratingList![index].toDouble()/model.ratingCount!); return _buildProgrss(5- index.toDouble(), model.ratingCount == 0?0:model.ratingList![index].toDouble()/model.ratingCount!);
}).toList() }).toList()
), ),
Text('${model.ratingCount}个评分',style: TextStyle(fontSize: 9.w,height: 1.4,color: Colours.c9),) Text('${model.ratingCount}个评分',style: TextStyle(fontSize: 9.w,height: 1.4,color: Colours.c9),)
...@@ -112,7 +112,7 @@ class BookInfoPage extends StatelessWidget { ...@@ -112,7 +112,7 @@ class BookInfoPage extends StatelessWidget {
Container( Container(
// color: Colors.cyan, // color: Colors.cyan,
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
width: 50, width: 60.w,
child: Text(item['name'].toString(),style: const TextStyle(fontSize: 15,height: 2.1,color: Colours.c3),), child: Text(item['name'].toString(),style: const TextStyle(fontSize: 15,height: 2.1,color: Colours.c3),),
), ),
Gaps.hGaps20, Gaps.hGaps20,
......
...@@ -94,15 +94,15 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -94,15 +94,15 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
'content': 'This is a note content', 'content': 'This is a note content',
'upload': 0, 'upload': 0,
'positioning': 'top', 'positioning': 'top',
'note': 'This is a note', 'note_content': 'This is a note',
'node_id': 0, 'node_id': 0,
}; };
await SqlManager.insertData(data); await SqlManager.insertData(data);
final result = await Tools.checkCurrentNetStatus(); final result = await Tools.checkCurrentNetStatus();
// 有网络的时候上传 笔记 // 有网络 并且是登录状态 的时候上传 笔记
if (result){ if (result && UserStore.to.isLogin){
upload(); upload();
} }
super.onReady(); super.onReady();
...@@ -245,6 +245,39 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -245,6 +245,39 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
List<Map<String, dynamic>> data = await SqlManager.queryNoUploadData(); List<Map<String, dynamic>> data = await SqlManager.queryNoUploadData();
Console.log('查询到的数据----------------------------------------------------$data'); Console.log('查询到的数据----------------------------------------------------$data');
if(data.isNotEmpty){
for (Map<String, dynamic> temp in data){
// 如果是笔记
if (temp['type'] == '3'){
// 存储url的数组
List<String> finalAudios = [];
// 存储url的数组
List<String> finalImages = [];
Map<String,dynamic> contentMap = jsonDecode(temp['note_content']);
List<String> audios = contentMap['audio'];
if(audios.isNotEmpty){
for(String path in audios){
final url = await uploadSource(path: path);
finalAudios.add(url);
}
}
List<String> images = contentMap['image'];
if(images.isNotEmpty){
for(String path in images){
final url = await uploadSource(path: path);
finalImages.add(url);
}
}
Map<String,dynamic> finalContentMap = {
'text':contentMap['text'],
'audio': finalAudios,
'image': finalImages
};
temp['note_content'] = finalContentMap;
}
}
final result = await LibraryAPI.uploadOffline(node: jsonEncode(data)); final result = await LibraryAPI.uploadOffline(node: jsonEncode(data));
// 上传成功后 更新数据库中的字段 // 上传成功后 更新数据库中的字段
if (result) { if (result) {
...@@ -252,6 +285,20 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -252,6 +285,20 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
} }
} }
}
// 上传文件
Future<String> uploadSource({
required String path
}) async {
// String result = await CommonAPI.upload(path:path,fileTypes: 'comment');
// return result;
OssTool tool = OssTool('zxts-comment-file');
final response = await tool.putObjectFile(path);
Console.log('------response--------------------------${response.realUri}');
return response.realUri.toString();
}
/// 获取图书列表数据 /// 获取图书列表数据
Future<void> _getBooks([bool isRefresh = false]) async { Future<void> _getBooks([bool isRefresh = false]) async {
......
...@@ -15,6 +15,7 @@ import 'package:ionicons/ionicons.dart'; ...@@ -15,6 +15,7 @@ import 'package:ionicons/ionicons.dart';
import '../../models/index.dart'; import '../../models/index.dart';
import '../../routes/index.dart'; import '../../routes/index.dart';
import '../../store/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
import '../course/index.dart'; import '../course/index.dart';
import '../study/index.dart'; import '../study/index.dart';
......
...@@ -112,6 +112,7 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -112,6 +112,7 @@ class _LibraryPageState extends State<LibraryPage> {
controller: controller, controller: controller,
sureTap: (){ sureTap: (){
controller.setShow(controller.show); controller.setShow(controller.show);
controller.sureFilter();
}, },
resetTap: (){ resetTap: (){
......
...@@ -210,13 +210,13 @@ class _LoginPageState extends State<LoginPage> { ...@@ -210,13 +210,13 @@ class _LoginPageState extends State<LoginPage> {
GestureDetector( GestureDetector(
child: Text('《用户协议》',style: TextStyle(color: Colours.cBlue,fontSize:14.w,height: 1.4)), child: Text('《用户协议》',style: TextStyle(color: Colours.cBlue,fontSize:14.w,height: 1.4)),
onTap: (){ onTap: (){
context.pushNamed(Routes.terms); context.pushNamed(Routes.terms,queryParameters: {'url':'$kServerUrl$kUserAgreement','title':'用户协议'});
}, },
), ),
GestureDetector( GestureDetector(
child: Text('《隐私政策》',style: TextStyle(color: Colours.cBlue,fontSize:14.w,height: 1.4)), child: Text('《隐私政策》',style: TextStyle(color: Colours.cBlue,fontSize:14.w,height: 1.4)),
onTap: (){ onTap: (){
context.pushNamed(Routes.terms); context.pushNamed(Routes.terms,queryParameters: {'url':'$kServerUrl$kUserPriAgreement','title':'隐私政策'});
}, },
), ),
], ],
......
...@@ -63,6 +63,9 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -63,6 +63,9 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 朗读组件 // 朗读组件
late FlutterTts flutterTts; late FlutterTts flutterTts;
// 是否展示搜索结果
bool showSearch = false;
///------------------------------------------ 页面 生命周期-------------------------------------------------------- ///------------------------------------------ 页面 生命周期--------------------------------------------------------
@override @override
...@@ -133,6 +136,11 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -133,6 +136,11 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
update(); update();
} }
void setShowSearch(bool show){
showSearch = show;
update();
}
// 选择了某个章节 // 选择了某个章节
void selectChapter(ChapterModel model) { void selectChapter(ChapterModel model) {
chapterName = model.name??''; chapterName = model.name??'';
...@@ -378,6 +386,10 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -378,6 +386,10 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 图片链接数组 // 图片链接数组
List<String> images = []; List<String> images = [];
final status = await Tools.checkCurrentNetStatus();
// 有网情况下 先直传oss 获取到url
if (status){
// 循环上传图片获取地址 // 循环上传图片获取地址
for(String path in discussInputImages){ for(String path in discussInputImages){
final url = await upload(path: path); final url = await upload(path: path);
...@@ -389,6 +401,19 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -389,6 +401,19 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
final url = await upload(path: model.path); final url = await upload(path: model.path);
audios.add(url); audios.add(url);
} }
}
// 没有网的情况下 存储到本地数据库
else{
for(String path in discussInputImages){
images.add(path);
}
// 循环上传音频获取地址
for(AudioModel model in discussInputAudios){
audios.add(model.path);
}
}
Map<String,dynamic> contentMap = { Map<String,dynamic> contentMap = {
'text':contentInput.text, 'text':contentInput.text,
...@@ -396,12 +421,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -396,12 +421,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
'image':images 'image':images
}; };
// 话题 // 话题 只有有网的时候才能发起话题
if (chatType == 0){ if (chatType == 0){
final result = await addDiscuss(contentMap); final result = await addDiscuss(contentMap);
return result; return result;
} }
// 笔记 // 笔记 有网没有网都能发起笔记
else if (chatType == 1){ else if (chatType == 1){
final result = addNote(contentMap); final result = addNote(contentMap);
return result; return result;
...@@ -411,8 +436,11 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -411,8 +436,11 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 添加笔记 // 添加笔记
Future<bool> addNote(Map<String,dynamic> contentMap) async { Future<bool> addNote(Map<String,dynamic> contentMap) async {
final status = await Tools.checkCurrentNetStatus();
final result = await LibraryAPI.addNote( bool result ;
// 有网直接上传接口
if (status){
result = await LibraryAPI.addNote(
bookId: bookId, bookId: bookId,
chapterId: chapterId, chapterId: chapterId,
content: noteTitle, content: noteTitle,
...@@ -420,6 +448,25 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -420,6 +448,25 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
positioning: notePosition, positioning: notePosition,
noteContent: jsonEncode(contentMap) noteContent: jsonEncode(contentMap)
); );
}
// 没有网存储本地数据库
else{
Map<String, dynamic> data = {
'types': 3,
'book_id': int.parse(bookId),
'chapter_id': int.parse(chapterId),
'is_open': isPublic?1:0,
'color': '#FF0000',
'content': noteTitle,
'upload': 0,
'positioning': notePosition,
'note_content': jsonEncode(contentMap),
'node_id': 0,
};
result = await SqlManager.insertData(data);
}
if(result){ if(result){
Toast.show('笔记发表成功'); Toast.show('笔记发表成功');
} }
......
...@@ -11,10 +11,20 @@ class DiscussController extends GetxController { ...@@ -11,10 +11,20 @@ class DiscussController extends GetxController {
controlFinishRefresh: true, controlFinishRefresh: true,
); );
late TextEditingController searchInput = TextEditingController();
late TextEditingController replyInput = TextEditingController();
final int _limit = 10; final int _limit = 10;
int _page = 1; int _page = 1;
bool _noMore = false; bool _noMore = false;
// 展示回复输入框
bool showReply = false;
// 当前要回复的模型
late DiscussModel discussModel;
// 是否展示搜索结果
bool showSearch = false;
@override @override
void onReady() { void onReady() {
...@@ -25,9 +35,52 @@ class DiscussController extends GetxController { ...@@ -25,9 +35,52 @@ class DiscussController extends GetxController {
@override @override
void onClose() { void onClose() {
refreshController.dispose(); refreshController.dispose();
searchInput.dispose();
super.onClose(); super.onClose();
} }
void setShow() {
showReply = !showReply;
update();
}
void setDiscussModel(DiscussModel model){
discussModel = model;
}
void setShowSearch(bool show){
showSearch = show;
update();
}
Future<bool> submit() async {
Map<String,dynamic> contentMap = {
'text':replyInput.text,
'audio':[],
'image':[]
};
final result = await LibraryAPI.addDiscuss(
bookId: bookDetailModel.bookId.toString(),
chapterId: chapterId,
commentId: discussModel.id.toString(),
quoteContent: '',
title: '',
content: jsonEncode(contentMap)
);
if(result){
Toast.show('话题发表成功');
}
else{
Toast.show('话题发表失败');
}
// 重置所有信息
// reset();
// setShowChat(false);
return result;
}
/// 获取讨论详情 /// 获取讨论详情
Future<void> _getDiscuss([bool isRefresh = false]) async { Future<void> _getDiscuss([bool isRefresh = false]) async {
......
...@@ -47,3 +47,4 @@ part 'note_controller.dart'; ...@@ -47,3 +47,4 @@ part 'note_controller.dart';
part 'discuss_controller.dart'; part 'discuss_controller.dart';
part 'widgets/input_discuss.dart'; part 'widgets/input_discuss.dart';
part 'widgets/item.dart'; part 'widgets/item.dart';
part 'widgets/search_all.dart';
...@@ -16,6 +16,9 @@ class NoteController extends GetxController { ...@@ -16,6 +16,9 @@ class NoteController extends GetxController {
int _page = 1; int _page = 1;
bool _noMore = false; bool _noMore = false;
// 是否展示搜索结果
bool showSearch = false;
@override @override
void onReady() { void onReady() {
...@@ -29,6 +32,10 @@ class NoteController extends GetxController { ...@@ -29,6 +32,10 @@ class NoteController extends GetxController {
super.onClose(); super.onClose();
} }
void setShowSearch(bool show){
showSearch = show;
update();
}
/// 获取笔记列表 /// 获取笔记列表
Future<void> _getNotes([bool isRefresh = false]) async { Future<void> _getNotes([bool isRefresh = false]) async {
......
...@@ -67,6 +67,11 @@ class _ReadPageState extends State<ReadPage> { ...@@ -67,6 +67,11 @@ class _ReadPageState extends State<ReadPage> {
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"),
), ),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
clearCache: true
)
),
contextMenu: ContextMenu( contextMenu: ContextMenu(
options: ContextMenuOptions(hideDefaultSystemContextMenuItems: true), options: ContextMenuOptions(hideDefaultSystemContextMenuItems: true),
), ),
...@@ -278,11 +283,18 @@ class _ReadPageState extends State<ReadPage> { ...@@ -278,11 +283,18 @@ class _ReadPageState extends State<ReadPage> {
Widget detail(ReadController controller,ToolModel model){ Widget detail(ReadController controller,ToolModel model){
if(model.tag == 0){ if(model.tag == 0){
return ReadCategoryPage(controller: controller, return ReadCategoryPage(controller: controller,
// 点 x 事件
onTap: (){ onTap: (){
controller.chooseTool(model); controller.chooseTool(model);
}, },
// 点 搜索全部 列表 某一项 事件
onTapSearchItem: (){
controller.chooseTool(model);
// TODO:重新加载阅读界面 参数:chapter_id text
Console.log('-----------目录点击搜索条目---------------------');
},
onTapChapter: (ChapterModel chapterModel){ onTapChapter: (ChapterModel chapterModel){
print('-----------选择的章节-------------${chapterModel.name}--------'); Console.log('-----------选择的章节-------------${chapterModel.name}--------');
// 配置选择的章节 // 配置选择的章节
controller.selectChapter(chapterModel); controller.selectChapter(chapterModel);
// 取消选中 tool // 取消选中 tool
...@@ -293,14 +305,36 @@ class _ReadPageState extends State<ReadPage> { ...@@ -293,14 +305,36 @@ class _ReadPageState extends State<ReadPage> {
); );
} }
else if(model.tag == 1){ else if(model.tag == 1){
return ReadNotePage(onTap: (){ return ReadNotePage(
// 点 x 事件
onTap: (){
controller.chooseTool(model);
},
// 点 搜索全部 列表 某一项 事件
onTapSearchItem: (){
controller.chooseTool(model); controller.chooseTool(model);
},bookDetailModel: controller.bookDetailModel,chapterId: controller.chapterId,); // TODO:重新加载阅读界面 参数:chapter_id text
Console.log('-----------笔记点击搜索条目---------------------');
},
bookDetailModel: controller.bookDetailModel,
chapterId: controller.chapterId,
);
} }
else if(model.tag == 2){ else if(model.tag == 2){
return ReadDiscussPage(onTap: (){ return ReadDiscussPage(
// 点 x 事件
onTap: (){
controller.chooseTool(model); controller.chooseTool(model);
},bookDetailModel: controller.bookDetailModel,chapterId:controller.chapterId,); },
// 点 搜索全部 列表 某一项 事件
onTapSearchItem: (){
controller.chooseTool(model);
// TODO:重新加载阅读界面 参数:chapter_id text
Console.log('-----------讨论点击搜索条目---------------------');
},
bookDetailModel: controller.bookDetailModel,
chapterId:controller.chapterId,
);
} }
return const SizedBox(); return const SizedBox();
} }
......
...@@ -3,12 +3,15 @@ part of web; ...@@ -3,12 +3,15 @@ part of web;
class ReadCategoryPage extends StatefulWidget { class ReadCategoryPage extends StatefulWidget {
final ReadController controller; final ReadController controller;
final void Function()? onTap; final void Function()? onTap;
// 点击 搜索全文 中的列表事件
final void Function()? onTapSearchItem;
final Function(ChapterModel chapterModel) onTapChapter; final Function(ChapterModel chapterModel) onTapChapter;
const ReadCategoryPage({ const ReadCategoryPage({
Key? key, Key? key,
required this.controller, required this.controller,
required this.onTap, required this.onTap,
required this.onTapChapter required this.onTapChapter,
this.onTapSearchItem
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -33,7 +36,10 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -33,7 +36,10 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
child: Image.asset('assets/images/close.png'), child: Image.asset('assets/images/close.png'),
) )
), ),
Container( Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF9F9F9), color: const Color(0xFFF9F9F9),
...@@ -50,20 +56,39 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -50,20 +56,39 @@ 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: searchController, // controller: controller.searchInput,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称分类', hintText: '搜索全文---目录',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
onEditingComplete: () { onEditingComplete: () {
widget.controller.setShowSearch(true);
Tools.unfocus();
}, },
), ),
), ),
), ),
BuildBook(bookDetailModel: widget.controller.bookDetailModel,), ),
Expanded( widget.controller.showSearch?GestureDetector(
onTap: () {
widget.controller.setShowSearch(false);
Tools.unfocus();
},
child: Container(
margin: EdgeInsets.only(right: 15.w),
child: Text('取消'),
)
):const SizedBox(),
],
),
widget.controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
widget.controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.controller.bookDetailModel,),
widget.controller.showSearch?const SizedBox():Expanded(
child: ListView.builder( child: ListView.builder(
itemBuilder:(BuildContext context, int index){ itemBuilder:(BuildContext context, int index){
return BuildItem(model: widget.controller.chapters[index],onTapChapter:(ChapterModel chapterModel){ return BuildItem(model: widget.controller.chapters[index],onTapChapter:(ChapterModel chapterModel){
......
part of web; part of web;
class ReadDiscussPage extends StatefulWidget { class ReadDiscussPage extends StatefulWidget {
// 点 x 事件
final void Function()? onTap; final void Function()? onTap;
// 点击 搜索全文 中的列表事件
final void Function()? onTapSearchItem;
final BookDetailModel bookDetailModel; final BookDetailModel bookDetailModel;
// 当前的章节id // 当前的章节id
final String chapterId; final String chapterId;
...@@ -9,7 +12,8 @@ class ReadDiscussPage extends StatefulWidget { ...@@ -9,7 +12,8 @@ class ReadDiscussPage extends StatefulWidget {
Key? key, Key? key,
required this.onTap, required this.onTap,
required this.bookDetailModel, required this.bookDetailModel,
required this.chapterId required this.chapterId,
this.onTapSearchItem
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -17,7 +21,6 @@ class ReadDiscussPage extends StatefulWidget { ...@@ -17,7 +21,6 @@ class ReadDiscussPage extends StatefulWidget {
} }
class _ReadDiscussPageState extends State<ReadDiscussPage> { class _ReadDiscussPageState extends State<ReadDiscussPage> {
late TextEditingController searchController = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<DiscussController>( return GetBuilder<DiscussController>(
...@@ -34,7 +37,10 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -34,7 +37,10 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
child: Image.asset('assets/images/close.png') child: Image.asset('assets/images/close.png')
) )
), ),
Container( Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF9F9F9), color: const Color(0xFFF9F9F9),
...@@ -51,27 +57,104 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -51,27 +57,104 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(17.5.w), borderRadius: BorderRadius.circular(17.5.w),
child: CustomInputSearch( child: CustomInputSearch(
controller: searchController, controller: controller.searchInput,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称讨论', hintText: '搜索全文---讨论',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
onEditingComplete: () { onEditingComplete: () {
controller.setShowSearch(true);
Tools.unfocus();
}, },
), ),
), ),
), ),
BuildBook(bookDetailModel: widget.bookDetailModel,), ),
Expanded( controller.showSearch?GestureDetector(
child: ListView.builder( onTap: () {
controller.setShowSearch(false);
Tools.unfocus();
},
child: Container(
margin: EdgeInsets.only(right: 15.w),
child: Text('取消'),
)
):const SizedBox(),
],
),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded(
child: Stack(
children: [
ListView.builder(
itemBuilder: (BuildContext context,int index){ itemBuilder: (BuildContext context,int index){
DiscussModel model = controller.discuss[index]; DiscussModel model = controller.discuss[index];
return BuildDiscuss(model: model,); return BuildDiscuss(model: model,controller: controller,);
}, },
itemCount: controller.discuss.length, itemCount: controller.discuss.length,
), ),
Visibility(
visible: controller.showReply,
child: Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom -49 ,
left: 0,
right: 0,
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: TextField(
autofocus: true,
maxLines: null,
controller: controller.replyInput,
decoration: InputDecoration(
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
hintText: '请输入内容',
hintStyle:TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9,),
filled: true,
fillColor: Colours.cF8,
),
),
),
Gaps.hGaps10,
GestureDetector(
onTap: (){
controller.submit();
controller.setShow();
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.w),
color: AppTheme.primary,
gradient: LinearGradient(
colors: [const Color(0xFFD53676).withOpacity(0.9),AppTheme.primary] , // 不可点击时的颜色,透明度为0.7
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
padding: EdgeInsets.symmetric(horizontal:13.5.w,vertical: 4.w),
child: Text('发表',style: TextStyle(fontSize: 14.w,fontWeight: Fonts.medium,color: Colors.white),),
),
)
],
),
),
),
),
)
],
)
) )
], ],
......
...@@ -2,6 +2,8 @@ part of web; ...@@ -2,6 +2,8 @@ part of web;
class ReadNotePage extends StatefulWidget { class ReadNotePage extends StatefulWidget {
final BookDetailModel bookDetailModel; final BookDetailModel bookDetailModel;
// 点击 搜索全文 中的列表事件
final void Function()? onTapSearchItem;
// 当前的章节id // 当前的章节id
final String chapterId; final String chapterId;
final void Function()? onTap; final void Function()? onTap;
...@@ -9,7 +11,8 @@ class ReadNotePage extends StatefulWidget { ...@@ -9,7 +11,8 @@ class ReadNotePage extends StatefulWidget {
Key? key, Key? key,
required this.onTap, required this.onTap,
required this.bookDetailModel, required this.bookDetailModel,
required this.chapterId required this.chapterId,
this.onTapSearchItem
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -32,7 +35,10 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -32,7 +35,10 @@ class _ReadNotePageState extends State<ReadNotePage> {
child: Image.asset('assets/images/close.png') child: Image.asset('assets/images/close.png')
) )
), ),
Container( Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF9F9F9), color: const Color(0xFFF9F9F9),
...@@ -49,20 +55,39 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -49,20 +55,39 @@ 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: searchController, // controller: controller.searchInput,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称笔记', hintText: '搜索全文---笔记',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
onEditingComplete: () { onEditingComplete: () {
controller.setShowSearch(true);
Tools.unfocus();
}, },
), ),
), ),
), ),
BuildBook(bookDetailModel: widget.bookDetailModel,), ),
Expanded( controller.showSearch?GestureDetector(
onTap: () {
controller.setShowSearch(false);
Tools.unfocus();
},
child: Container(
margin: EdgeInsets.only(right: 15.w),
child: Text('取消'),
)
):const SizedBox(),
],
),
controller.showSearch? Expanded(child: BuildSearchAll(onTap: (){
if (widget.onTapSearchItem !=null) {
widget.onTapSearchItem!();
}
},)):
controller.showSearch?const SizedBox():BuildBook(bookDetailModel: widget.bookDetailModel,),
controller.showSearch?const SizedBox():Expanded(
child: MediaQuery.removePadding( child: MediaQuery.removePadding(
context: context, context: context,
removeTop: true, removeTop: true,
......
part of web;
class BuildSearchAll extends StatefulWidget {
final void Function()? onTap;
const BuildSearchAll({
Key? key,
this.onTap
}) : super(key: key);
@override
State<BuildSearchAll> createState() => _BuildSearchAllState();
}
class _BuildSearchAllState extends State<BuildSearchAll> {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (BuildContext context, int 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'),
],
),
),
);
},
itemCount: 3,
);
}
}
...@@ -58,7 +58,7 @@ class _AboutPageState extends State<AboutPage> { ...@@ -58,7 +58,7 @@ class _AboutPageState extends State<AboutPage> {
GestureDetector( GestureDetector(
child: Text('《用户协议》',textAlign: TextAlign.right,style: TextStyle(fontSize: 10.w,color: Color(0xFF2A82D9)),), child: Text('《用户协议》',textAlign: TextAlign.right,style: TextStyle(fontSize: 10.w,color: Color(0xFF2A82D9)),),
onTap: (){ onTap: (){
context.pushNamed(Routes.terms); context.pushNamed(Routes.terms,queryParameters: {'url':'$kServerUrl$kUserAgreement','title':'用户协议'});
}, },
), ),
Gaps.vGaps15, Gaps.vGaps15,
...@@ -67,7 +67,7 @@ class _AboutPageState extends State<AboutPage> { ...@@ -67,7 +67,7 @@ class _AboutPageState extends State<AboutPage> {
GestureDetector( GestureDetector(
child: Text('《隐私协议》',textAlign: TextAlign.left,style: TextStyle(fontSize: 10.w,color: Color(0xFF2A82D9))), child: Text('《隐私协议》',textAlign: TextAlign.left,style: TextStyle(fontSize: 10.w,color: Color(0xFF2A82D9))),
onTap:(){ onTap:(){
context.pushNamed(Routes.terms); context.pushNamed(Routes.terms,queryParameters: {'url':'$kServerUrl$kUserPriAgreement','title':'隐私政策'});
} , } ,
) )
], ],
......
...@@ -70,7 +70,7 @@ class _CoinRechargePageState extends State<CoinRechargePage> with AutomaticKeepA ...@@ -70,7 +70,7 @@ class _CoinRechargePageState extends State<CoinRechargePage> with AutomaticKeepA
Gaps.vGaps15, Gaps.vGaps15,
GestureDetector( GestureDetector(
onTap: (){ onTap: (){
context.pushNamed(Routes.terms); context.pushNamed(Routes.terms,queryParameters: {'url':'$kServerUrl$kUserRechargeAgreement','title':'用户充值协议'});
}, },
child: RichText(text: TextSpan( child: RichText(text: TextSpan(
children: [ children: [
......
...@@ -10,6 +10,7 @@ import '../../apis/index.dart'; ...@@ -10,6 +10,7 @@ import '../../apis/index.dart';
import '../../models/index.dart'; import '../../models/index.dart';
import '../../theme.dart'; import '../../theme.dart';
import '../../utils/index.dart'; import '../../utils/index.dart';
import '../read_web/index.dart';
part 'view.dart'; part 'view.dart';
......
part of user_discuss_des; part of user_discuss_des;
class BuildDiscuss extends StatelessWidget { class BuildDiscuss extends StatefulWidget {
final DiscussModel model; final DiscussModel model;
final DiscussController? controller;
const BuildDiscuss({ const BuildDiscuss({
Key? key, Key? key,
required this.model required this.model,
this.controller
}) : super(key: key); }) : super(key: key);
@override
State<BuildDiscuss> createState() => _BuildDiscussState();
}
class _BuildDiscussState extends State<BuildDiscuss> {
final FocusNode _focusNode = FocusNode();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
...@@ -34,7 +43,7 @@ class BuildDiscuss extends StatelessWidget { ...@@ -34,7 +43,7 @@ class BuildDiscuss extends StatelessWidget {
height: 1.5.w, height: 1.5.w,
color: Colours.c3, color: Colours.c3,
)), )),
TextSpan(text: model.title,style: TextStyle( TextSpan(text: widget.model.title,style: TextStyle(
fontSize: 14.w, fontSize: 14.w,
height: 1.5.w, height: 1.5.w,
color: Colours.c3, color: Colours.c3,
...@@ -47,10 +56,10 @@ class BuildDiscuss extends StatelessWidget { ...@@ -47,10 +56,10 @@ class BuildDiscuss extends StatelessWidget {
height: 0.5.w, height: 0.5.w,
color: Colours.cF2, color: Colours.cF2,
), ),
_buildItem(model), _buildItem(widget.model),
Container( Container(
margin:EdgeInsets.only(left: 15.w), margin:EdgeInsets.only(left: 15.w),
child: _buildListView(model.commentAll != null ? model.commentAll!:[]) child: _buildListView(widget.model.commentAll != null ? widget.model.commentAll!:[])
), ),
Gaps.vGaps13, Gaps.vGaps13,
Container( Container(
...@@ -60,8 +69,8 @@ class BuildDiscuss extends StatelessWidget { ...@@ -60,8 +69,8 @@ class BuildDiscuss extends StatelessWidget {
child:Column( child:Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(model.chapterName??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),), Text(widget.model.chapterName??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
Text('内容:${model.quoteContent??''}',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),), Text('内容:${widget.model.quoteContent??''}',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
], ],
) )
) )
...@@ -70,7 +79,6 @@ class BuildDiscuss extends StatelessWidget { ...@@ -70,7 +79,6 @@ class BuildDiscuss extends StatelessWidget {
); );
} }
Widget _buildItem(DiscussModel model,{int type =0}){ Widget _buildItem(DiscussModel model,{int type =0}){
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -138,11 +146,18 @@ class BuildDiscuss extends StatelessWidget { ...@@ -138,11 +146,18 @@ class BuildDiscuss extends StatelessWidget {
Gaps.hGaps15, Gaps.hGaps15,
Row( Row(
children: [ children: [
SizedBox( GestureDetector(
height: 15.w, onTap:(){
width: 15.w, // _showKeyboard(context);
// color: Colors.yellow, widget.controller?.setShow();
child: Image.asset('assets/images/discuss_big.png'), widget.controller?.setDiscussModel(model);
},
child: Container(
height: 25.w,
width: 25.w,
color: Colors.yellow,
child: Image.asset('assets/images/reply.png'),
),
), ),
Text(model.replyNum.toString(),style: TextStyle(fontSize:12.w,height: 1.5,color: Colours.c9)) Text(model.replyNum.toString(),style: TextStyle(fontSize:12.w,height: 1.5,color: Colours.c9))
], ],
...@@ -168,7 +183,6 @@ class BuildDiscuss extends StatelessWidget { ...@@ -168,7 +183,6 @@ class BuildDiscuss extends StatelessWidget {
); );
} }
// 图片 // 图片
Widget _buildImageGridView(){ Widget _buildImageGridView(){
return GridView.builder( return GridView.builder(
...@@ -182,52 +196,47 @@ class BuildDiscuss extends StatelessWidget { ...@@ -182,52 +196,47 @@ class BuildDiscuss extends StatelessWidget {
childAspectRatio: 1 childAspectRatio: 1
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
MediaModel? mediaModel = model.content?.image?[index]; MediaModel? mediaModel = widget.model.content?.image?[index];
return CustomImage.network(url: model?.content?.image?[index].content??'',fit: BoxFit.cover,); return CustomImage.network(url: widget.model?.content?.image?[index].content??'',fit: BoxFit.cover,);
// return Container( // return Container(
// color: Colors.red, // color: Colors.red,
// ); // );
}, },
itemCount: model.content?.image?.length, itemCount: widget.model.content?.image?.length,
// itemCount: 2, // itemCount: 2,
); );
} }
// Widget _buildAudioListView(){ void _showKeyboard(BuildContext context) {
// return ListView.builder( _focusNode.requestFocus();
// physics: const NeverScrollableScrollPhysics(), FocusScope.of(context).requestFocus(_focusNode);
// shrinkWrap: true, Overlay.of(context)?.insert(
// itemBuilder: (BuildContext context, int index) { OverlayEntry(
// MediaModel mediaModel = model.noteContent!.audio![index]; builder: (context) => Positioned(
// return Container( bottom: MediaQuery.of(context).viewInsets.bottom,
// height: 20.w, left: 0,
// margin: EdgeInsets.only(right: 130.w), right: 0,
// child: Container( child: Container(
// margin: EdgeInsets.only(top: 5.w), color: Colors.white,
// padding: EdgeInsets.only(right:20.w,left: 10.w), child: Padding(
// decoration: BoxDecoration( padding: const EdgeInsets.all(8.0),
// borderRadius: BorderRadius.circular(10.w), child: TextField(
// color: Colours.cF9, focusNode: _focusNode,
// ), decoration: InputDecoration(
// child: Row( hintText: '在这里回复',
// // mainAxisSize: MainAxisSize.min, filled: true,
// mainAxisAlignment:MainAxisAlignment.spaceBetween, fillColor: Colors.grey[200],
// children: [ border: OutlineInputBorder(
// GestureDetector( borderRadius: BorderRadius.circular(10.0),
// onTap: (){ ),
// if (onTapAudio !=null) onTapAudio!(mediaModel); ),
// }, ),
// child: Image.asset('assets/images/audio.png') ),
// ), ),
// Text('0:00/${mediaModel.duration}',style: TextStyle(fontSize: 10.w,height: 1.4,color: Colours.c9),) ),
// ], ),
// ), );
// ), }
// );
// },
// itemCount: model.noteContent?.audio?.length,
// );
// }
} }
...@@ -3,17 +3,23 @@ part of user_terms; ...@@ -3,17 +3,23 @@ part of user_terms;
class TermsPage extends StatelessWidget { class TermsPage extends StatelessWidget {
const TermsPage({Key? key}) : super(key: key); final String url ;
final String title ;
const TermsPage({
Key? key,
required this.url,
required this.title
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('用户协议'), title: Text(title),
), ),
body: InAppWebView( body: InAppWebView(
initialUrlRequest: URLRequest( initialUrlRequest: URLRequest(
url: Uri.parse('https://www.baidu.com/'), url: Uri.parse(url),
), ),
) )
); );
......
...@@ -223,7 +223,10 @@ abstract class Routes { ...@@ -223,7 +223,10 @@ abstract class Routes {
pageBuilder: (context, state) =>CupertinoPage( pageBuilder: (context, state) =>CupertinoPage(
name: state.uri.toString(), name: state.uri.toString(),
key: state.pageKey, key: state.pageKey,
child: const TermsPage() child: TermsPage(
url: state.uri.queryParameters['url'].toString(),
title: state.uri.queryParameters['title'].toString(),
)
) )
), ),
GoRoute( GoRoute(
...@@ -271,7 +274,8 @@ abstract class Routes { ...@@ -271,7 +274,8 @@ abstract class Routes {
child: BookDetailPage( child: BookDetailPage(
bookId: state.uri.queryParameters['book_id'].toString(), bookId: state.uri.queryParameters['book_id'].toString(),
) )
) ),
redirect: (context, state) => _RouteRedirect.auth(),
), ),
GoRoute( GoRoute(
path: '/$bookScore', path: '/$bookScore',
...@@ -613,7 +617,7 @@ abstract class Routes { ...@@ -613,7 +617,7 @@ abstract class Routes {
} }
abstract class _RouteRedirect { abstract class _RouteRedirect {
static String? auth(BuildContext context, GoRouterState state) { static String? auth() {
if (UserStore.to.isLogin) return null; if (UserStore.to.isLogin) return null;
return '/${Routes.login}'; return '/${Routes.login}';
} }
......
...@@ -13,7 +13,9 @@ const String kSearchHistory = 'search_history'; ...@@ -13,7 +13,9 @@ const String kSearchHistory = 'search_history';
const String kFailOrder = 'failOrder'; const String kFailOrder = 'failOrder';
const String kNoteTable = 'members_book_notes'; const String kNoteTable = 'members_book_notes';
const String kReadTable = 'read_history'; const String kReadTable = 'read_history';
const String kUserAgreement = '/html/agreement/ser_agreement.html';
const String kUserPriAgreement = '/html/agreement/pri_agreement.html';
const String kUserRechargeAgreement = '/html/agreement/rec_agreement.html';
......
...@@ -38,7 +38,7 @@ class SqlManager { ...@@ -38,7 +38,7 @@ class SqlManager {
"content TEXT, " "content TEXT, "
"upload INTEGER, " "upload INTEGER, "
"positioning TEXT, " "positioning TEXT, "
"note TEXT)" "note_content TEXT)"
); );
// // 阅读章节表 // // 阅读章节表
await db.execute("CREATE TABLE $kReadTable (" await db.execute("CREATE TABLE $kReadTable ("
...@@ -100,12 +100,16 @@ class SqlManager { ...@@ -100,12 +100,16 @@ class SqlManager {
// 插入数据 // 插入数据
static Future<void> insertData(Map<String, dynamic> data) async { static Future<bool> insertData(Map<String, dynamic> data) async {
final result = await _database?.insert( final result = await _database?.insert(
'members_book_notes', 'members_book_notes',
data, data,
conflictAlgorithm: ConflictAlgorithm.replace, conflictAlgorithm: ConflictAlgorithm.replace,
); );
if (result !=null){
return true;
}
return false;
Console.log('插入数据-------------------------------$result'); Console.log('插入数据-------------------------------$result');
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论