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

目录 笔记 讨论列表初步布局

上级 ca0ef0e6
......@@ -141,5 +141,49 @@ abstract class LibraryAPI {
return ReportModel.fromJson(result.data);
}
/// 7、阅读页的笔记列表
///
static Future<List<NoteModel>> noteList(
{int page = 1,
int limit = 10,
required String bookId,
required String chapterId}) async {
final result = await HttpService.to.post(
'/v1/book/Information/getChapterNotesList',
params: {
'page': page,
'page_size': limit,
'book_id': bookId,
'chapter_id': chapterId
},
);
if (result.data is! Map && result.data['list'] is! List) return [];
return List.generate(result.data['list'].length, (index) {
return NoteModel.fromJson(result.data['list'][index]);
});
}
/// 8、笔记详情列表
///
static Future<List<DiscussModel>> discussList(
{int page = 1,
int limit = 10,
required String bookId,
required String chapterId}) async {
final result = await HttpService.to.post(
'/v1/book/Information/getChapterCommentList',
params: {
'page': page,
'page_size': limit,
'book_id': bookId,
'chapter_id': chapterId
},
);
if (result.data is! Map && result.data['list'] is! List) return [];
return List.generate(result.data['list'].length, (index) {
return DiscussModel.fromJson(result.data['list'][index]);
});
}
}
\ No newline at end of file
......@@ -87,10 +87,10 @@ class LoginController extends GetxController {
// 定时器回调
});
/// 测试账号
if (kDebugMode) {
phoneInput.text = '13521054068';
passwordInput.text = '123456';
}
// if (kDebugMode) {
// phoneInput.text = '13521054068';
// passwordInput.text = '123456';
// }
super.onInit();
}
......
......@@ -31,7 +31,7 @@ class _SplashPageState extends State<SplashPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
// extendBodyBehindAppBar: true,
extendBodyBehindAppBar: true,
appBar: AppBar(),
body: const Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
......
part of web;
class ReadController extends FullLifeCycleController with GetSingleTickerProviderStateMixin{
// 目录
List <ChapterModel> chapters = [];
// late final PageController pageController;
//
// //默认显示
// int currentPage = 1;
late AnimationController _controller;
bool _show = false;
bool _show = true;
bool get show => _show;
void setShow(bool value) {
......@@ -15,7 +25,7 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
}
else {
/// 不显示状态栏
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
/// 收回动画
_controller.reverse();
}
......@@ -28,8 +38,10 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
@override
void onInit() {
// pageController = PageController(initialPage: currentPage);
/// 默认不显示状态栏
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
/// 初始化
_controller = AnimationController(
vsync: this,
......@@ -38,12 +50,24 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
super.onInit();
}
@override
void onReady() {
_getChapters();
super.onReady();
}
@override
void onClose() {
_controller.dispose();
super.onClose();
}
void onPageChanged(int page) {
// currentPage = page;
update(['navigation']);
}
void onResumed(){
print('onResumed');
}
......@@ -56,4 +80,12 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
void onDetached(){
print('onDetached');
}
/// 获取目录信息
void _getChapters() async {
chapters = await LibraryAPI.chapters(bookId: '110');
update();
}
}
\ No newline at end of file
part of web;
class DiscussController extends GetxController {
List<DiscussModel> discuss = [];
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
final int _limit = 10;
int _page = 1;
bool _noMore = false;
@override
void onReady() {
onRefresh();
super.onReady();
}
@override
void onClose() {
refreshController.dispose();
super.onClose();
}
/// 获取讨论详情
Future<void> _getDiscuss([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.discussList(
page: _page,
limit: _limit,
bookId: '110',
chapterId: '1'
);
// 如果是刷新 清理数据
if (isRefresh) discuss.clear();
discuss.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getDiscuss(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getDiscuss();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
}
\ No newline at end of file
library web;
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_book/utils/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '../../apis/index.dart';
import '../../models/index.dart';
import '../../widgets/index.dart';
import '../book_category/index.dart';
import '../user_discuss_des/index.dart';
import '../user_notes_des/index.dart';
part 'view.dart';
part 'controller.dart';
\ No newline at end of file
part 'controller.dart';
part 'widgets/category.dart';
part 'widgets/discuss.dart';
part 'widgets/note.dart';
part 'widgets/book.dart';
part 'note_controller.dart';
part 'discuss_controller.dart';
part of web;
class NoteController extends GetxController {
List<NoteModel> notes = [];
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
final int _limit = 10;
int _page = 1;
bool _noMore = false;
@override
void onReady() {
onRefresh();
super.onReady();
}
@override
void onClose() {
refreshController.dispose();
super.onClose();
}
/// 获取笔记列表
Future<void> _getNotes([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.noteList(
page: _page,
limit: _limit,
bookId: '110',
chapterId: '1'
);
// 如果是刷新 清理数据
if (isRefresh) notes.clear();
notes.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getNotes(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getNotes();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@ class ReadPage extends StatefulWidget {
}
class _ReadPageState extends State<ReadPage> {
int currentIndex = 0;
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
late ContextMenu contextMenu;
......@@ -20,7 +22,7 @@ class _ReadPageState extends State<ReadPage> {
return GetBuilder<ReadController>(
init: ReadController(),
builder: (readController) => Scaffold(
appBar: AppBar(title:const Text('阅读'),),
body: Container(
color: Colors.white,
child: Stack(
......@@ -37,61 +39,6 @@ class _ReadPageState extends State<ReadPage> {
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
},
// onLoadError: (InAppWebViewController controller, Uri url, int code ,String msg){
//
// },
contextMenu: ContextMenu(
menuItems: [
ContextMenuItem(title: '划线',androidId: 1,iosId: '1',action: (){
const snackBar = SnackBar(
content: Text("划线"),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}),
ContextMenuItem(title: '提问',androidId: 2,iosId: '2',action: (){
}),
ContextMenuItem(title: '笔记',androidId: 3,iosId: '3',action: (){
}),
],
onCreateContextMenu: (hitTestResult) async {
String selectedText = await webViewController?.getSelectedText() ?? "";
final snackBar = SnackBar(
content: Text(
"Selected text: '$selectedText', of type: ${hitTestResult.type.toString()}"),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
// options: ContextMenuOptions(
// hideDefaultSystemContextMenuItems: true,
// ),
onContextMenuActionItemClicked: (ContextMenuItem menuItem) async {
final snackBar = SnackBar(
content: Text(
"Menu item with ID ${menuItem.iosId} and title '${menuItem.title}' clicked!"),
duration: const Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
// switch (item.title){
// case '划线':
// Console.log('----------划线-----------');
// break;
// case '提问':
// Console.log('----------提问-----------');
// break;
// case '笔记':
// Console.log('----------笔记-----------');
// break;
//
// }
}
),
onLoadStop: (controller, url) {
controller.addJavaScriptHandler(handlerName: 'onTap', callback: (args){
readController.setShow(readController.show);
......@@ -117,17 +64,61 @@ class _ReadPageState extends State<ReadPage> {
child: Text('top View'),
),
),
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 49 + MediaQuery.of(context).viewInsets.bottom,
child: _showContent(readController,currentIndex)
),
AnimatedPositioned(
duration: readController.controller.duration!,
curve: Curves.easeInOut,
bottom: readController.show ? 0 : -100, // 负值隐藏,0 显示
bottom: readController.show ? 0 : -49 - MediaQuery.of(context).viewInsets.bottom, // 负值隐藏,0 显示
left: 0,
right: 0,
height: 100,
height: 49,
child: Container(
color: Colors.limeAccent,
alignment: Alignment.center,
child: Text('Bottom View'),
child: BottomNavigationBar(
currentIndex: currentIndex,
onTap: (index){
setState(() {
currentIndex = index;
});
// _showBottomSheet(context, index);
},
items: [
BottomNavigationBarItem(
label: '目录',
icon: Image.asset(
'assets/images/category_unselect.png',
),
activeIcon: Image.asset(
'assets/images/category_select.png',
),
),
BottomNavigationBarItem(
label: '笔记',
icon: Image.asset(
'assets/images/note_unselect.png',
),
activeIcon: Image.asset(
'assets/images/note_select.png',
)
),
BottomNavigationBarItem(
label: '讨论',
icon: Image.asset(
'assets/images/discuss_unselect.png',
),
activeIcon: Image.asset(
'assets/images/discuss_select.png',
)
),
],
)
),
),
......@@ -138,4 +129,52 @@ class _ReadPageState extends State<ReadPage> {
);
}
Widget _showContent(ReadController controller,int index) {
print('++++++++++++++++++++++++$index');
if (controller.show){
if (index == 0){
return Container(
color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container(
color: Colors.white,
child: ReadCategoryPage(controller: controller,),
),
),
// child: ReadCategoryPage(),
);
}
else if (index == 1){
return Container(
color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container(
color: Colors.white,
child: ReadNotePage(),
),
),
// child: ReadCategoryPage(),
);
}
else if (index == 2){
return Container(
color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container(
color: Colors.white,
child: ReadNotePage(),
),
),
// child: ReadCategoryPage(),
);
}
}
return const SizedBox();
}
}
part of web;
class BuildBook extends StatelessWidget {
const BuildBook({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 15.w),
child: Column(
children: [
Container(
padding: EdgeInsets.only(top: 12.w,bottom: 15.w),
// color: Colors.red,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomCard(
width: 72.w,
height: 86.w,
url: '',
),
Container(
height: 87.w,
margin: EdgeInsets.only(left: 13.w),
// color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('书名',style: TextStyle(fontSize: 14.w,height: 1.5,fontWeight: Fonts.medium,color: Colours.c3),),
Text('作者',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c6),),
],
),
],
),
)
],
),
)
],
),
);
}
}
part of web;
class ReadCategoryPage extends StatefulWidget {
final ReadController controller;
const ReadCategoryPage({
Key? key,
required this.controller,
}) : super(key: key);
@override
State<ReadCategoryPage> createState() => _ReadCategoryPageState();
}
class _ReadCategoryPageState extends State<ReadCategoryPage> {
late TextEditingController searchController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
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: '请输入书籍名称',
onTap: () {
// context.pushNamed(Routes.msgs);
},
onEditingComplete: () {
},
),
),
),
BuildBook(),
// Expanded(
// child: ListView.builder(
// itemBuilder:(BuildContext context, int index){
// return BuildItem(model: widget.controller.chapters[index],);
// },
// itemCount: widget.controller.chapters.length,
// ),
// ),
],
),
);
}
}
part of web;
class ReadDiscussPage extends StatefulWidget {
const ReadDiscussPage({Key? key}) : super(key: key);
@override
State<ReadDiscussPage> createState() => _ReadDiscussPageState();
}
class _ReadDiscussPageState extends State<ReadDiscussPage> {
late TextEditingController searchController = TextEditingController();
@override
Widget build(BuildContext context) {
return GetBuilder<DiscussController>(
init: DiscussController(),
builder:(controller) => Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
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: '请输入书籍名称',
onTap: () {
// context.pushNamed(Routes.msgs);
},
onEditingComplete: () {
},
),
),
),
BuildBook(),
ListView.builder(
itemBuilder: (BuildContext context,int index){
DiscussModel model = controller.discuss[index];
return BuildDiscuss(model: model,);
},
itemCount: controller.discuss.length,
)
],
),
),
);
}
}
part of web;
class ReadNotePage extends StatefulWidget {
const ReadNotePage({Key? key}) : super(key: key);
@override
State<ReadNotePage> createState() => _ReadNotePageState();
}
class _ReadNotePageState extends State<ReadNotePage> {
late TextEditingController searchController = TextEditingController();
@override
Widget build(BuildContext context) {
return GetBuilder<NoteController>(
init: NoteController(),
builder:(controller) =>Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
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: '请输入书籍名称',
onTap: () {
// context.pushNamed(Routes.msgs);
},
onEditingComplete: () {
},
),
),
),
BuildBook(),
Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context,int index){
NoteModel model = controller.notes[index];
// 划线
if(model.types == 1){
return BuildLine(model: model,);
}
// 高亮
else if(model.types == 2){
return BuildHigh(model: model,);
}
// 笔记
else if(model.types == 3){
return BuildNote(model: model,);
}
},
itemCount: controller.notes.length,
),
),
],
),
);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论