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