diff --git a/README.md b/README.md index 73674d9..7881ca4 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,12 @@ * 使用google-GFSegmentTab,将导航分为:体系,常用网站,公众号三个Tab部分 * 使用google-Stick-header,构建体系页面 * 导航-体系/常用网站/公众号完成 +### v7.0 +* 使用google-GFSegmentTab,将导航分为:未读消息和已读消息两个部分 +* 填充:未读消息和已读消息列表 +* 在BaseController中根据用户是否已经登陆请求数据接口,展示消息数据 +* 将MessageControlLer中读取未读消息的数据,移动到未读消息控制器中,在数据请求到同时调用此接口 + ## 五 使用的指令 @@ -78,6 +84,11 @@ flutter build apk --split-per-abi * pull_to_refresh:https://pub.flutter-io.cn/packages/pull_to_refresh * lottie:https://pub.flutter-io.cn/packages/lottie * sprintf:https://pub.flutter-io.cn/packages/sprintf +* shimmer:https://pub.flutter-io.cn/packages/shimmer +* cached_network_image:https://pub.flutter-io.cn/packages/cached_network_image +* flutter_html:https://pub.flutter-io.cn/packages/webview_flutter +* webview_flutter:https://pub.flutter-io.cn/packages/webview_flutter +* badges:https://pub.flutter-io.cn/packages/badges diff --git a/lib/models/message_read_list_response.dart b/lib/models/message_read_list_response.dart index fce8dc1..2b8744b 100644 --- a/lib/models/message_read_list_response.dart +++ b/lib/models/message_read_list_response.dart @@ -6,9 +6,8 @@ part 'message_read_list_response.g.dart'; @JsonSerializable() class MessageReadListResponse extends Object { - @JsonKey(name: 'data') - Data data; + MessageData data; @JsonKey(name: 'errorCode') int errorCode; @@ -16,51 +15,59 @@ class MessageReadListResponse extends Object { @JsonKey(name: 'errorMsg') String errorMsg; - MessageReadListResponse(this.data,this.errorCode,this.errorMsg,); + MessageReadListResponse( + this.data, + this.errorCode, + this.errorMsg, + ); - factory MessageReadListResponse.fromJson(Map srcJson) => _$MessageReadListResponseFromJson(srcJson); + factory MessageReadListResponse.fromJson(Map srcJson) => + _$MessageReadListResponseFromJson(srcJson); Map toJson() => _$MessageReadListResponseToJson(this); - } - @JsonSerializable() -class Data extends Object { - +class MessageData extends Object { @JsonKey(name: 'curPage') - int curPage; + int? curPage; @JsonKey(name: 'datas') - List datas; + List? datas; @JsonKey(name: 'offset') - int offset; + int? offset; @JsonKey(name: 'over') - bool over; + bool? over; @JsonKey(name: 'pageCount') - int pageCount; + int? pageCount; @JsonKey(name: 'size') - int size; + int? size; @JsonKey(name: 'total') - int total; - - Data(this.curPage,this.datas,this.offset,this.over,this.pageCount,this.size,this.total,); - - factory Data.fromJson(Map srcJson) => _$DataFromJson(srcJson); - - Map toJson() => _$DataToJson(this); - + int? total; + + MessageData({ + this.curPage, + this.datas, + this.offset, + this.over, + this.pageCount, + this.size, + this.total, + }); + + factory MessageData.fromJson(Map srcJson) => + _$MessageDataFromJson(srcJson); + + Map toJson() => _$MessageDataToJson(this); } - @JsonSerializable() -class Datas extends Object { - +class Message extends Object { @JsonKey(name: 'category') int category; @@ -100,12 +107,24 @@ class Datas extends Object { @JsonKey(name: 'userId') int userId; - Datas(this.category,this.date,this.fromUser,this.fromUserId,this.fullLink,this.id,this.isRead,this.link,this.message,this.niceDate,this.tag,this.title,this.userId,); - - factory Datas.fromJson(Map srcJson) => _$DatasFromJson(srcJson); - - Map toJson() => _$DatasToJson(this); - + Message( + this.category, + this.date, + this.fromUser, + this.fromUserId, + this.fullLink, + this.id, + this.isRead, + this.link, + this.message, + this.niceDate, + this.tag, + this.title, + this.userId, + ); + + factory Message.fromJson(Map srcJson) => + _$MessageFromJson(srcJson); + + Map toJson() => _$MessageToJson(this); } - - diff --git a/lib/models/message_read_list_response.g.dart b/lib/models/message_read_list_response.g.dart index 6b887c9..f483ee6 100644 --- a/lib/models/message_read_list_response.g.dart +++ b/lib/models/message_read_list_response.g.dart @@ -9,7 +9,7 @@ part of 'message_read_list_response.dart'; MessageReadListResponse _$MessageReadListResponseFromJson( Map json) => MessageReadListResponse( - Data.fromJson(json['data'] as Map), + MessageData.fromJson(json['data'] as Map), json['errorCode'] as int, json['errorMsg'] as String, ); @@ -22,19 +22,20 @@ Map _$MessageReadListResponseToJson( 'errorMsg': instance.errorMsg, }; -Data _$DataFromJson(Map json) => Data( - json['curPage'] as int, - (json['datas'] as List) - .map((e) => Datas.fromJson(e as Map)) +MessageData _$MessageDataFromJson(Map json) => MessageData( + curPage: json['curPage'] as int?, + datas: (json['datas'] as List?) + ?.map((e) => Message.fromJson(e as Map)) .toList(), - json['offset'] as int, - json['over'] as bool, - json['pageCount'] as int, - json['size'] as int, - json['total'] as int, + offset: json['offset'] as int?, + over: json['over'] as bool?, + pageCount: json['pageCount'] as int?, + size: json['size'] as int?, + total: json['total'] as int?, ); -Map _$DataToJson(Data instance) => { +Map _$MessageDataToJson(MessageData instance) => + { 'curPage': instance.curPage, 'datas': instance.datas, 'offset': instance.offset, @@ -44,7 +45,7 @@ Map _$DataToJson(Data instance) => { 'total': instance.total, }; -Datas _$DatasFromJson(Map json) => Datas( +Message _$MessageFromJson(Map json) => Message( json['category'] as int, json['date'] as int, json['fromUser'] as String, @@ -60,7 +61,7 @@ Datas _$DatasFromJson(Map json) => Datas( json['userId'] as int, ); -Map _$DatasToJson(Datas instance) => { +Map _$MessageToJson(Message instance) => { 'category': instance.category, 'date': instance.date, 'fromUser': instance.fromUser, diff --git a/lib/models/message_unread_list_response.dart b/lib/models/message_unread_list_response.dart index 1fa2688..1e21572 100644 --- a/lib/models/message_unread_list_response.dart +++ b/lib/models/message_unread_list_response.dart @@ -1,3 +1,4 @@ +import 'package:flutter_wanandroid/models/message_read_list_response.dart'; import 'package:json_annotation/json_annotation.dart'; part 'message_unread_list_response.g.dart'; @@ -8,7 +9,7 @@ part 'message_unread_list_response.g.dart'; class MessageUnReadListResponse extends Object { @JsonKey(name: 'data') - Data data; + MessageUnreadData data; @JsonKey(name: 'errorCode') int errorCode; @@ -26,13 +27,13 @@ class MessageUnReadListResponse extends Object { @JsonSerializable() -class Data extends Object { +class MessageUnreadData extends Object { @JsonKey(name: 'curPage') int curPage; @JsonKey(name: 'datas') - List datas; + List datas; @JsonKey(name: 'offset') int offset; @@ -49,63 +50,63 @@ class Data extends Object { @JsonKey(name: 'total') int total; - Data(this.curPage,this.datas,this.offset,this.over,this.pageCount,this.size,this.total,); + MessageUnreadData(this.curPage,this.datas,this.offset,this.over,this.pageCount,this.size,this.total,); - factory Data.fromJson(Map srcJson) => _$DataFromJson(srcJson); + factory MessageUnreadData.fromJson(Map srcJson) => _$MessageUnreadDataFromJson(srcJson); - Map toJson() => _$DataToJson(this); + Map toJson() => _$MessageUnreadDataToJson(this); } - -@JsonSerializable() -class Datas extends Object { - - @JsonKey(name: 'category') - int category; - - @JsonKey(name: 'date') - int date; - - @JsonKey(name: 'fromUser') - String fromUser; - - @JsonKey(name: 'fromUserId') - int fromUserId; - - @JsonKey(name: 'fullLink') - String fullLink; - - @JsonKey(name: 'id') - int id; - - @JsonKey(name: 'isRead') - int isRead; - - @JsonKey(name: 'link') - String link; - - @JsonKey(name: 'message') - String message; - - @JsonKey(name: 'niceDate') - String niceDate; - - @JsonKey(name: 'tag') - String tag; - - @JsonKey(name: 'title') - String title; - - @JsonKey(name: 'userId') - int userId; - - Datas(this.category,this.date,this.fromUser,this.fromUserId,this.fullLink,this.id,this.isRead,this.link,this.message,this.niceDate,this.tag,this.title,this.userId,); - - factory Datas.fromJson(Map srcJson) => _$DatasFromJson(srcJson); - - Map toJson() => _$DatasToJson(this); - -} +// +// @JsonSerializable() +// class Datas extends Object { +// +// @JsonKey(name: 'category') +// int category; +// +// @JsonKey(name: 'date') +// int date; +// +// @JsonKey(name: 'fromUser') +// String fromUser; +// +// @JsonKey(name: 'fromUserId') +// int fromUserId; +// +// @JsonKey(name: 'fullLink') +// String fullLink; +// +// @JsonKey(name: 'id') +// int id; +// +// @JsonKey(name: 'isRead') +// int isRead; +// +// @JsonKey(name: 'link') +// String link; +// +// @JsonKey(name: 'message') +// String message; +// +// @JsonKey(name: 'niceDate') +// String niceDate; +// +// @JsonKey(name: 'tag') +// String tag; +// +// @JsonKey(name: 'title') +// String title; +// +// @JsonKey(name: 'userId') +// int userId; +// +// Datas(this.category,this.date,this.fromUser,this.fromUserId,this.fullLink,this.id,this.isRead,this.link,this.message,this.niceDate,this.tag,this.title,this.userId,); +// +// factory Datas.fromJson(Map srcJson) => _$DatasFromJson(srcJson); +// +// Map toJson() => _$DatasToJson(this); +// +// } diff --git a/lib/models/message_unread_list_response.g.dart b/lib/models/message_unread_list_response.g.dart index 796f923..ac87bb3 100644 --- a/lib/models/message_unread_list_response.g.dart +++ b/lib/models/message_unread_list_response.g.dart @@ -9,7 +9,7 @@ part of 'message_unread_list_response.dart'; MessageUnReadListResponse _$MessageUnReadListResponseFromJson( Map json) => MessageUnReadListResponse( - Data.fromJson(json['data'] as Map), + MessageUnreadData.fromJson(json['data'] as Map), json['errorCode'] as int, json['errorMsg'] as String, ); @@ -22,10 +22,11 @@ Map _$MessageUnReadListResponseToJson( 'errorMsg': instance.errorMsg, }; -Data _$DataFromJson(Map json) => Data( +MessageUnreadData _$MessageUnreadDataFromJson(Map json) => + MessageUnreadData( json['curPage'] as int, (json['datas'] as List) - .map((e) => Datas.fromJson(e as Map)) + .map((e) => Message.fromJson(e as Map)) .toList(), json['offset'] as int, json['over'] as bool, @@ -34,7 +35,8 @@ Data _$DataFromJson(Map json) => Data( json['total'] as int, ); -Map _$DataToJson(Data instance) => { +Map _$MessageUnreadDataToJson(MessageUnreadData instance) => + { 'curPage': instance.curPage, 'datas': instance.datas, 'offset': instance.offset, @@ -43,35 +45,3 @@ Map _$DataToJson(Data instance) => { 'size': instance.size, 'total': instance.total, }; - -Datas _$DatasFromJson(Map json) => Datas( - json['category'] as int, - json['date'] as int, - json['fromUser'] as String, - json['fromUserId'] as int, - json['fullLink'] as String, - json['id'] as int, - json['isRead'] as int, - json['link'] as String, - json['message'] as String, - json['niceDate'] as String, - json['tag'] as String, - json['title'] as String, - json['userId'] as int, - ); - -Map _$DatasToJson(Datas instance) => { - 'category': instance.category, - 'date': instance.date, - 'fromUser': instance.fromUser, - 'fromUserId': instance.fromUserId, - 'fullLink': instance.fullLink, - 'id': instance.id, - 'isRead': instance.isRead, - 'link': instance.link, - 'message': instance.message, - 'niceDate': instance.niceDate, - 'tag': instance.tag, - 'title': instance.title, - 'userId': instance.userId, - }; diff --git a/lib/pages/main/views/main_view.dart b/lib/pages/main/views/main_view.dart index 52410a1..343b93a 100644 --- a/lib/pages/main/views/main_view.dart +++ b/lib/pages/main/views/main_view.dart @@ -42,45 +42,45 @@ class MainView extends GetView { // } AppBar? _buildAppBar() { - // return AppBar( - // centerTitle: true, - // title: Text("${controller.currentTitle}"), - // actions: [ - // (controller.currentTitle == Keys.me.tr) - // ? IconButton( - // icon: const Icon(Icons.settings), - // onPressed: () { - // Get.toNamed(Routes.setting); - // }, - // ) - // : IconButton( - // icon: const Icon(Icons.search), - // onPressed: () {}, - // ) - // ], - // ); + return AppBar( + centerTitle: true, + title: Text("${controller.currentTitle}"), + actions: [ + (controller.currentTitle == Keys.me.tr) + ? IconButton( + icon: const Icon(Icons.settings), + onPressed: () { + Get.toNamed(Routes.setting); + }, + ) + : IconButton( + icon: const Icon(Icons.search), + onPressed: () {}, + ) + ], + ); - if (controller.currentTitle == Keys.navigation.tr) { - return null; - } else { - return AppBar( - centerTitle: true, - title: Text("${controller.currentTitle}"), - actions: [ - (controller.currentTitle == Keys.me.tr) - ? IconButton( - icon: const Icon(Icons.settings), - onPressed: () { - Get.toNamed(Routes.setting); - }, - ) - : IconButton( - icon: const Icon(Icons.search), - onPressed: () {}, - ) - ], - ); - } + // if (controller.currentTitle == Keys.navigation.tr) { + // return null; + // } else { + // return AppBar( + // centerTitle: true, + // title: Text("${controller.currentTitle}"), + // actions: [ + // (controller.currentTitle == Keys.me.tr) + // ? IconButton( + // icon: const Icon(Icons.settings), + // onPressed: () { + // Get.toNamed(Routes.setting); + // }, + // ) + // : IconButton( + // icon: const Icon(Icons.search), + // onPressed: () {}, + // ) + // ], + // ); + // } // if (controller.currentTitle == Keys.home.tr || // controller.currentTitle == Keys.me.tr) { diff --git a/lib/pages/message/bindings/message_binding.dart b/lib/pages/message/bindings/message_binding.dart new file mode 100644 index 0000000..022538a --- /dev/null +++ b/lib/pages/message/bindings/message_binding.dart @@ -0,0 +1,17 @@ +import 'package:flutter_wanandroid/pages/message/controllers/message_controller.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_detail_web_controller.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_read_list_controller.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_unread_list_controller.dart'; +import 'package:get/get.dart'; + +class MessageBinding extends Bindings { + @override + void dependencies() { + + Get.lazyPut(() => MessageController()); + Get.lazyPut(() => MessageUnreadListController()); + Get.lazyPut(() => MessageReadListController()); + + + } +} diff --git a/lib/pages/message/bindings/message_detail_web_binding.dart b/lib/pages/message/bindings/message_detail_web_binding.dart new file mode 100644 index 0000000..75abf6f --- /dev/null +++ b/lib/pages/message/bindings/message_detail_web_binding.dart @@ -0,0 +1,11 @@ +import 'package:get/get.dart'; + +import '../controllers/message_detail_web_controller.dart'; + +class MessageDetailWebBinding extends Bindings{ + @override + void dependencies() { + Get.lazyPut(() => MessageDetailWebController()); + } + +} \ No newline at end of file diff --git a/lib/pages/message/controllers/message_controller.dart b/lib/pages/message/controllers/message_controller.dart index adc2de6..9d072c5 100644 --- a/lib/pages/message/controllers/message_controller.dart +++ b/lib/pages/message/controllers/message_controller.dart @@ -1,30 +1,52 @@ +import 'package:flutter/material.dart'; import 'package:flutter_wanandroid/pages/main/controllers/main_controller.dart'; +import 'package:flutter_wanandroid/pages/message/views/message_read_list_view.dart'; +import 'package:flutter_wanandroid/pages/message/views/message_unread_list_view.dart'; import 'package:flutter_wanandroid/provider/base_controller.dart'; import 'package:flutter_wanandroid/provider/request_api.dart'; import 'package:flutter_wanandroid/res/constant.dart'; import 'package:get/instance_manager.dart'; +import '../../../widgets/keep_alive_wrapper.dart'; + /// 日期:2022-05-15 /// 描述:主页-主屏页面-Body-Message-页面 /// 说明: class MessageController extends BaseController { + + late TabController tabController; + late List tabPageBodies; + + final tabValues = ['未读消息列表', '已读消息列表']; + @override void onInit() { super.onInit(); - //getUnReadMessageResponse(); + tabController = TabController(length: tabValues.length, initialIndex: 0, vsync: this); + tabPageBodies = [ + const KeepAliveWrapper( + keepAlive: true, + child: MessageUnreadListView(), + ), + const KeepAliveWrapper( + keepAlive: true, + child: MessageReadListView(), + ) + ]; + } ///获取未读消息接口 - Future getUnReadMessageResponse() async { - httpManager( - loadingType: Constant.noLoading, - future: provider.get(RequestAPI.messageUnread), - onSuccess: (value) { - ///消息赋值 - MainController mainController = Get.put(MainController()); - mainController.messageNum = value; - }, - onFail: (fail) {}, - onError: (error) {}); - } + // Future getUnReadMessageResponse() async { + // httpManager( + // loadingType: Constant.noLoading, + // future: provider.get(RequestAPI.messageUnread), + // onSuccess: (value) { + // ///消息赋值 + // MainController mainController = Get.put(MainController()); + // mainController.messageNum = value; + // }, + // onFail: (fail) {}, + // onError: (error) {}); + // } } diff --git a/lib/pages/message/controllers/message_detail_web_controller.dart b/lib/pages/message/controllers/message_detail_web_controller.dart new file mode 100644 index 0000000..e43dd72 --- /dev/null +++ b/lib/pages/message/controllers/message_detail_web_controller.dart @@ -0,0 +1,112 @@ +import 'package:flutter_wanandroid/provider/base_controller.dart'; +import 'package:get/get.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import 'dart:async'; +import 'dart:io'; + + +class MessageDetailWebController extends BaseController{ + /// 收藏动画显示与否 + final _collectAnimation = false.obs; + get collectAnimation => _collectAnimation.value; + set collectAnimation(value) => _collectAnimation.value = value; + + /// 取消收藏动画显示与否 + final _unCollectAnimation = false.obs; + get unCollectAnimation => _unCollectAnimation.value; + set unCollectAnimation(value) => _unCollectAnimation.value = value; + + late WebViewController webViewController; + + /////进度条 + final _webProgress = 0.0.obs; + get webProgress => _webProgress.value; + set webProgress(value) => _webProgress.value = value; + + /// 第一次进入WebView显示加载页面 + final _isFirstInitWeb = true.obs; + get isFirstInitWeb => _isFirstInitWeb.value; + set isFirstInitWeb(value) => _isFirstInitWeb.value = value; + + /// 当前网页Title + String? currentTitle; + + // 当前页面链接 + var currentPageUrl = ""; + // 收藏、取消收藏接口路径 + late String requestURL; + late Future> future; + + @override + void onInit() { + super.onInit(); + if (Platform.isAndroid) { + WebView.platform = SurfaceAndroidWebView(); + } + } + + /// WebView加载页面进度 + void updateWebProgress(int progress) { + webProgress = (progress / 100).toDouble(); + webCanBack(); + } + + //WebView创建时回调 + Future onWebViewCreated(WebViewController controller) async { + //WebView控制器,通过WebViewController可以实现Web内的前进、后退等操作 + webViewController = controller; + } + + void reloadWebView() { + // 刷新页面 + webViewController.reload(); + } + + void onPageStarted(String url, String link) { + webCanBack(); + // 显示加载动画页面 + unCollectAnimation = true; + + } + + void onPageFinished(String url, String link) { + webCanBack(); + // 关闭加载动画页面 + unCollectAnimation = false; + // 当前页面链接 + currentPageUrl = url; + } + + void onWebResourceError(WebResourceError error, String url, String link) { + webCanBack(); + // 关闭加载动画页面 + unCollectAnimation = false; + + } + + Future onWillPop() async { + //点击返回键时回调 + if (await webViewController.canGoBack()) { + //如果WebView可以返回 + webViewController.goBack(); + //WebView返回,界面不返回 + return false; + } else { + //否则界面返回,且恢复第一次进入标志 + isFirstInitWeb = true; + return true; + } + } + + Future webCanBack() async { + currentTitle = await webViewController.getTitle(); + if (await webViewController.canGoBack()) { + // Web页面可以返回,非首页 + isFirstInitWeb = false; + } else { + // Web页面不可以返回,首页 + isFirstInitWeb = true; + } + } + +} \ No newline at end of file diff --git a/lib/pages/message/controllers/message_read_list_controller.dart b/lib/pages/message/controllers/message_read_list_controller.dart new file mode 100644 index 0000000..50db143 --- /dev/null +++ b/lib/pages/message/controllers/message_read_list_controller.dart @@ -0,0 +1,111 @@ +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_wanandroid/provider/base_refresh_controller.dart'; +import 'package:get/get_rx/src/rx_types/rx_types.dart'; +import 'package:sprintf/sprintf.dart'; +import '../../../models/message_read_list_response.dart'; +import '../../../provider/request_api.dart'; +import '../../../provider/state/load_state.dart'; +import '../../../res/constant.dart'; + +class MessageReadListController extends BaseRefreshController { + ///未读消息 + final messageUnread = MessageData().obs; + + ///未读消息列表 + final messageUnReadList = RxList(); + + @override + void onInit() { + super.onInit(); + onFirstInMessageReadData(); + } + + /// 第一次进入 + void onFirstInMessageReadData() { + getMessageReadData( + loadingType: Constant.simpleShimmerLoading, + refreshState: RefreshState.first, + ); + } + + /// 下拉刷新 + void onRefreshMessageReadData() { + getMessageReadData( + loadingType: Constant.noLoading, + refreshState: RefreshState.refresh, + ); + } + + /// 上滑加载更多 + void onLoadMoreMessageReadData() { + getMessageReadData( + loadingType: Constant.noLoading, + refreshState: RefreshState.loadMore, + ); + } + + /// 获取首页数据 + Future getMessageReadData({ + required String loadingType, + required RefreshState refreshState, + }) async { + if (refreshState == RefreshState.refresh || + refreshState == RefreshState.first) { + /// 下拉刷新 + currentPage = 0; + } + if (refreshState == RefreshState.loadMore) { + /// 上滑加载更多 + currentPage++; + } + + getMessageUnReadList(loadingType, refreshState); + } + + ///获取首页文章列表 + Future getMessageUnReadList( + String loadingType, RefreshState refreshState) async { + String requestUrl = sprintf(RequestAPI.messageReadList, [currentPage]); + httpManagerWithRefreshPaging( + loadingType: loadingType, + refreshState: refreshState, + future: provider.get(requestUrl), + onSuccess: (response) { + var messageData = MessageData.fromJson(response); + List? dataList = messageData.datas; + // 加载到底部判断 + var over = messageData.over; + if (over != null) { + if (over) { + loadNoData(); + } + } + if (dataList != null && dataList.isNotEmpty) { + refreshLoadState = LoadState.success; + + if (refreshState == RefreshState.first) { + messageUnReadList.assignAll(dataList); + } else if (refreshState == RefreshState.refresh) { + messageUnReadList.assignAll(dataList); + } else if (refreshState == RefreshState.loadMore) { + messageUnReadList.addAll(dataList); + } + } else { + if (loadingType != Constant.noLoading) { + refreshLoadState = LoadState.empty; + } else { + loadNoData(); + } + } + }, + onFail: (error) { + refreshLoadState = LoadState.fail; + EasyLoading.showToast('数据请求失败 ${error.errorCode} ${error.errorMsg}'); + }, + onError: (error) { + refreshLoadState = LoadState.fail; + EasyLoading.showToast('数据请求失败 ${error.errorCode} ${error.errorMsg}'); + }, + ); + } +} diff --git a/lib/pages/message/controllers/message_unread_list_controller.dart b/lib/pages/message/controllers/message_unread_list_controller.dart new file mode 100644 index 0000000..08a4539 --- /dev/null +++ b/lib/pages/message/controllers/message_unread_list_controller.dart @@ -0,0 +1,133 @@ +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_wanandroid/models/message_read_list_response.dart'; +import 'package:flutter_wanandroid/provider/base_refresh_controller.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:get/get_rx/src/rx_types/rx_types.dart'; +import 'package:sprintf/sprintf.dart'; +import '../../../provider/request_api.dart'; +import '../../../provider/state/load_state.dart'; +import '../../../res/constant.dart'; +import '../../../utils/logger/logger_util.dart'; +import '../../main/controllers/main_controller.dart'; + +class MessageUnreadListController extends BaseRefreshController { + ///未读消息 + final messageUnread = MessageData().obs; + + ///未读消息列表 + final messageUnReadList = RxList(); + + @override + void onInit() { + super.onInit(); + onFirstInMessageUnReadData(); + } + ///获取未读消息接口 + Future getUnReadMessageResponse() async { + httpManager( + loadingType: Constant.noLoading, + future: provider.get(RequestAPI.messageUnread), + onSuccess: (value) { + ///消息赋值 + MainController mainController = Get.put(MainController()); + mainController.messageNum = value; + }, + onFail: (fail) {}, + onError: (error) {}); + } + + /// 第一次进入 + void onFirstInMessageUnReadData() { + getMessageUnReadData( + loadingType: Constant.simpleShimmerLoading, + refreshState: RefreshState.first, + ); + } + + /// 下拉刷新 + void onRefreshMessageUnReadData() { + getMessageUnReadData( + loadingType: Constant.noLoading, + refreshState: RefreshState.refresh, + ); + } + + /// 上滑加载更多 + void onLoadMoreMessageUnReadData() { + LoggerUtil.d('============> onLoadMoreHomeData()', tag: 'HomeController'); + getMessageUnReadData( + loadingType: Constant.noLoading, + refreshState: RefreshState.loadMore, + ); + } + + /// 获取首页数据 + Future getMessageUnReadData({ + required String loadingType, + required RefreshState refreshState, + }) async { + if (refreshState == RefreshState.refresh || + refreshState == RefreshState.first) { + /// 下拉刷新 + currentPage = 0; + } + if (refreshState == RefreshState.loadMore) { + /// 上滑加载更多 + currentPage++; + } + LoggerUtil.d('============> getHomeData() $currentPage', + tag: 'HomeController'); + ///获取未读消息数量 + getUnReadMessageResponse(); + // 获取首页文章列表 + getMessageUnReadList(loadingType, refreshState); + } + + ///获取首页文章列表 + Future getMessageUnReadList( + String loadingType, RefreshState refreshState) async { + String requestUrl = sprintf(RequestAPI.messageUnReadList, [currentPage]); + httpManagerWithRefreshPaging( + loadingType: loadingType, + refreshState: refreshState, + future: provider.get(requestUrl), + onSuccess: (response) { + var messageData = MessageData.fromJson(response); + List? dataList = messageData.datas; + // 加载到底部判断 + var over = messageData.over; + if (over != null) { + if (over) { + loadNoData(); + } + } + if (dataList != null && dataList.isNotEmpty) { + refreshLoadState = LoadState.success; + + if (refreshState == RefreshState.first) { + messageUnReadList.assignAll(dataList); + } else if (refreshState == RefreshState.refresh) { + messageUnReadList.assignAll(dataList); + } else if (refreshState == RefreshState.loadMore) { + messageUnReadList.addAll(dataList); + } + } else { + if (loadingType != Constant.noLoading) { + refreshLoadState = LoadState.empty; + } else { + loadNoData(); + } + } + }, + onFail: (error) { + refreshLoadState = LoadState.fail; + EasyLoading.showToast('数据请求失败 ${error.errorCode} ${error.errorMsg}'); + }, + onError: (error) { + refreshLoadState = LoadState.fail; + EasyLoading.showToast('数据请求失败 ${error.errorCode} ${error.errorMsg}'); + }, + ); + } +} diff --git a/lib/pages/message/views/message_detail_web_page.dart b/lib/pages/message/views/message_detail_web_page.dart new file mode 100644 index 0000000..f9856cd --- /dev/null +++ b/lib/pages/message/views/message_detail_web_page.dart @@ -0,0 +1,84 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'package:flutter_wanandroid/models/message_read_list_response.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_detail_web_controller.dart'; +import 'package:get/get.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import '../../../res/app_color.dart'; + +/// 描述: 消息Web页面 + +class MessageDetailWebPage extends GetView { + const MessageDetailWebPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + var arguments = Get.arguments; + final Message model = arguments['data']; + return WillPopScope( + child: Scaffold( + appBar: AppBar( + title: Text(model.title), + ), + body: webViewContainer(context, model), + ), + onWillPop: () => controller.onWillPop(), + ); + } + + Stack webViewContainer(BuildContext context, Message model) { + var url = ''; + if (model.fullLink.isNotEmpty) { + url = model.fullLink; + } + return Stack( + children: [ + WebView( + allowsInlineMediaPlayback: true, + zoomEnabled: true, + // 默认禁止js + javascriptMode: JavascriptMode.unrestricted, + // 初始url + initialUrl: url, + gestureNavigationEnabled: true, + onWebViewCreated: (webController) { + controller.onWebViewCreated(webController); + }, + // 页面开始加载时 + onPageStarted: (String url) async { + controller.onPageStarted(url, model.link ?? ""); + }, + onProgress: (int progress) { + // WebView加载页面进度 + controller.updateWebProgress(progress); + }, + onPageFinished: (url) async { + controller.onPageFinished(url, model.link ?? ""); + }, + navigationDelegate: (NavigationRequest request) { + if (!request.url.contains('http')) { + return NavigationDecision.prevent; + } + return NavigationDecision.navigate; + }, + onWebResourceError: (WebResourceError error) { + controller.onWebResourceError(error, url, model.link ?? ""); + }, + ), + Obx(() { + // WebView加载页面进度 + return Visibility( + visible: controller.webProgress < 1, + child: LinearProgressIndicator( + minHeight: 1, + backgroundColor: AppColors.bgColor, + color: AppColors.iconLightColor, + value: controller.webProgress, + ), + ); + }), + ], + ); + } +} diff --git a/lib/pages/message/views/message_read_list_view.dart b/lib/pages/message/views/message_read_list_view.dart new file mode 100644 index 0000000..58e15fa --- /dev/null +++ b/lib/pages/message/views/message_read_list_view.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_read_list_controller.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; +import '../../../provider/refresh/refresh_paging_state_page.dart'; +import '../../../widgets/message_list_item_widget.dart'; + +class MessageReadListView extends GetView{ + const MessageReadListView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return RefreshPagingStatePage( + controller: controller, + onPressed: () => controller.onFirstInMessageReadData(), + onRefresh: () => controller.onRefreshMessageReadData(), + onLoadMore: () => controller.onLoadMoreMessageReadData(), + refreshController: controller.refreshController, + header: const ClassicHeader(), + lottieRocketRefreshHeader: false, + child: CustomScrollView( + controller: controller.scrollController, + slivers: [_messageReadList(controller)], + ), + ); + } + Widget _messageReadList(MessageReadListController controller) { + return Obx(() { + return SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return MessageListItemWidget( + dataList: controller.messageUnReadList, + index: index, + onCollectClick: (int index) {}, + ); + }, + childCount: controller.messageUnReadList.length, + ), + ); + }); + } + +} \ No newline at end of file diff --git a/lib/pages/message/views/message_unread_list_view.dart b/lib/pages/message/views/message_unread_list_view.dart new file mode 100644 index 0000000..2a24185 --- /dev/null +++ b/lib/pages/message/views/message_unread_list_view.dart @@ -0,0 +1,46 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_unread_list_controller.dart'; +import 'package:flutter_wanandroid/widgets/message_list_item_widget.dart'; +import 'package:get/get.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; + +import '../../../provider/refresh/refresh_paging_state_page.dart'; + +class MessageUnreadListView extends GetView{ + const MessageUnreadListView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return RefreshPagingStatePage( + controller: controller, + onPressed: () => controller.onFirstInMessageUnReadData(), + onRefresh: () => controller.onRefreshMessageUnReadData(), + onLoadMore: () => controller.onLoadMoreMessageUnReadData(), + refreshController: controller.refreshController, + header: const ClassicHeader(), + lottieRocketRefreshHeader: false, + child: CustomScrollView( + controller: controller.scrollController, + slivers: [_messageUnReadList(controller)], + ), + ); + } + Widget _messageUnReadList(MessageUnreadListController controller) { + return Obx(() { + return SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return MessageListItemWidget( + dataList: controller.messageUnReadList, + index: index, + onCollectClick: (int index) {}, + ); + }, + childCount: controller.messageUnReadList.length, + ), + ); + }); + } + +} \ No newline at end of file diff --git a/lib/pages/message/views/message_view.dart b/lib/pages/message/views/message_view.dart index c16cec8..bc25cb7 100644 --- a/lib/pages/message/views/message_view.dart +++ b/lib/pages/message/views/message_view.dart @@ -1,6 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_wanandroid/pages/message/controllers/message_controller.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; import 'package:get/get_state_manager/src/simple/get_view.dart'; +import 'package:getwidget/colors/gf_color.dart'; +import 'package:getwidget/components/appbar/gf_appbar.dart'; +import 'package:getwidget/components/tabs/gf_segment_tabs.dart'; +import 'package:getwidget/components/tabs/gf_tabbar_view.dart'; /// 日期:2022-05-15 /// 描述:主页-主屏页面-Body-tree-页面 @@ -11,8 +17,41 @@ class MessageView extends GetView { @override Widget build(BuildContext context) { - //controller.getUnReadMessageResponse(); - //return Scaffold(appBar: AppBar(title: Text('Tree'),),); - return const Center(child: Text('Message')); + + return Scaffold( + appBar: GFAppBar( + //backgroundColor: GFColors.INFO, + actions: [_buildTabsWidget()], + //title:_buildTabsWidget(), + ), + body: GFTabBarView( + controller: controller.tabController, + children: controller.tabPageBodies), + ); + } + + Widget _buildTabsWidget(){ + return GFSegmentTabs( + width: Get.width, + height: 40, + //controller: controller.tabController, + tabController: controller.tabController, + tabBarColor: GFColors.LIGHT, + labelColor: GFColors.WHITE, + unselectedLabelColor: GFColors.DARK, + indicator: const BoxDecoration( + color: GFColors.DARK, + border: Border( + bottom: BorderSide( + color: GFColors.SUCCESS, + width: 3, + ), + ), + ), + //indicatorPadding: const EdgeInsets.all(0), + //indicatorWeight: 2, + //border: Border.all(color: Colors.white, width: 1), + length: 3, + tabs: controller.tabValues.map((e) => Text(e)).toList()); } } diff --git a/lib/pages/navigation/views/navigation_site_view.dart b/lib/pages/navigation/views/navigation_site_view.dart index dd07924..2563858 100644 --- a/lib/pages/navigation/views/navigation_site_view.dart +++ b/lib/pages/navigation/views/navigation_site_view.dart @@ -58,8 +58,7 @@ class NavigationSiteView extends GetView { : Colors.grey.withOpacity(0.1), child: InkWell( /// 点击导航item切换当前导航item值currentNavigation - onTap: () => - controller.changeNavigation(navigationGroupList[index]), + onTap: () => controller.changeNavigation(navigationGroupList[index]), child: Container( height: 40, alignment: Alignment.center, diff --git a/lib/pages/navigation/views/navigation_view.dart b/lib/pages/navigation/views/navigation_view.dart index 3dd5760..cdada8c 100644 --- a/lib/pages/navigation/views/navigation_view.dart +++ b/lib/pages/navigation/views/navigation_view.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:getwidget/colors/gf_color.dart'; import 'package:getwidget/components/appbar/gf_appbar.dart'; import 'package:getwidget/components/tabs/gf_segment_tabs.dart'; +import 'package:getwidget/components/tabs/gf_tabbar.dart'; import 'package:getwidget/components/tabs/gf_tabbar_view.dart'; /// 日期:2022-05-15 @@ -17,32 +18,37 @@ class NavigationView extends GetView { Widget build(BuildContext context) { return Scaffold( appBar: GFAppBar( - ///backgroundColor: GFColors.DARK, - title: GFSegmentTabs( - width: Get.width, - height: 40, - tabController: controller.tabController, - tabBarColor: GFColors.LIGHT, - labelColor: GFColors.WHITE, - unselectedLabelColor: GFColors.DARK, - indicator: const BoxDecoration( - color: GFColors.DARK, - border: Border( - bottom: BorderSide( - color: GFColors.SUCCESS, - width: 3, - ), - ), - ), - //indicatorPadding: const EdgeInsets.all(0), - //indicatorWeight: 2, - //border: Border.all(color: Colors.white, width: 1), - length: 3, - tabs: controller.tabValues.map((e) => Text(e)).toList()), + //backgroundColor: GFColors.INFO, + actions: [_buildTabsWidget()], + //title:_buildTabsWidget(), ), body: GFTabBarView( controller: controller.tabController, children: controller.tabPageBodies), ); } + Widget _buildTabsWidget(){ + return GFSegmentTabs( + width: Get.width, + height: 40, + //controller: controller.tabController, + tabController: controller.tabController, + tabBarColor: GFColors.LIGHT, + labelColor: GFColors.WHITE, + unselectedLabelColor: GFColors.DARK, + indicator: const BoxDecoration( + color: GFColors.DARK, + border: Border( + bottom: BorderSide( + color: GFColors.SUCCESS, + width: 3, + ), + ), + ), + //indicatorPadding: const EdgeInsets.all(0), + //indicatorWeight: 2, + //border: Border.all(color: Colors.white, width: 1), + length: 3, + tabs: controller.tabValues.map((e) => Text(e)).toList()); + } } diff --git a/lib/provider/base_controller.dart b/lib/provider/base_controller.dart index e2dd134..c7f18e9 100644 --- a/lib/provider/base_controller.dart +++ b/lib/provider/base_controller.dart @@ -4,6 +4,8 @@ import 'package:flutter_wanandroid/models/login_register_response.dart'; import 'package:flutter_wanandroid/pages/main/controllers/main_controller.dart'; import 'package:flutter_wanandroid/pages/me/controllers/me_controller.dart'; import 'package:flutter_wanandroid/pages/message/controllers/message_controller.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_read_list_controller.dart'; +import 'package:flutter_wanandroid/pages/message/controllers/message_unread_list_controller.dart'; import 'package:flutter_wanandroid/provider/state/load_state.dart'; import 'package:get/get.dart'; import '../config/api_provider_config.dart'; @@ -64,13 +66,26 @@ class BaseController extends GetxController with StateMixin,GetSingleTicke MeController meController = Get.put(MeController()); meController.getUserInfo(); - MessageController messageController = Get.put(MessageController()); - messageController.getUnReadMessageResponse(); + // MessageController messageController = Get.put(MessageController()); + // messageController.getUnReadMessageResponse(); + + ///已读消息列表刷新数据 + MessageReadListController messageReadListController=Get.put(MessageReadListController()); + messageReadListController.onFirstInMessageReadData(); + ///未读消息列表刷新数据 + MessageUnreadListController messageUnreadListController=Get.put(MessageUnreadListController()); + messageUnreadListController.onFirstInMessageUnReadData(); } else { EasyLoading.showSuccess(Keys.logoutContent.tr); messageNum = 0; + ///已读消息列表刷新数据 + MessageReadListController messageReadListController=Get.put(MessageReadListController()); + messageReadListController.onFirstInMessageReadData(); + ///未读消息列表刷新数据 + MessageUnreadListController messageUnreadListController=Get.put(MessageUnreadListController()); + messageUnreadListController.onFirstInMessageUnReadData(); ///清除Cookie CookieUtils.clearCookie(); diff --git a/lib/provider/request_api.dart b/lib/provider/request_api.dart index e191afc..f5be74a 100644 --- a/lib/provider/request_api.dart +++ b/lib/provider/request_api.dart @@ -392,14 +392,14 @@ abstract class RequestAPI { /// 方法: GET /// 参数: ///******************************************************************/ - static const String messageReadList = '/message/lg/readed_list/index/json'; + static const String messageReadList = '/message/lg/readed_list/%s/json'; /// ******************14.3 未读消息列表 **************** /// 示例:https://wanandroid.com/message/lg/unread_list/页码/json /// 方法: GET /// 参数: ///******************************************************************/ - static const String messageUnReadList = '/message/lg/unread_list/index/json'; + static const String messageUnReadList = '/message/lg/unread_list/%s/json'; ///15- 公众号 diff --git a/lib/provider/state/load_error_page.dart b/lib/provider/state/load_error_page.dart index 2ed0c95..788b5c7 100644 --- a/lib/provider/state/load_error_page.dart +++ b/lib/provider/state/load_error_page.dart @@ -8,9 +8,7 @@ import '../../res/gaps.dart'; import '../../res/r.dart'; import 'load_state.dart'; - /// 类名: load_error_page.dart -/// 创建日期: 11/16/21 on 6:21 PM /// 描述: 加载错误页面 @@ -39,10 +37,10 @@ class EmptyErrorStatePage extends StatelessWidget { alignment: Alignment.center, child: Column( mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Gaps.vGap150, + //Gaps.vGap150, Container( child: Lottie.asset( loadState == LoadState.empty diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index 3136d71..ae1c989 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -11,6 +11,8 @@ import 'package:flutter_wanandroid/pages/main/views/main_view.dart'; import 'package:flutter_wanandroid/pages/me/bindings/me_binding.dart'; import 'package:flutter_wanandroid/pages/me/controllers/me_controller.dart'; import 'package:flutter_wanandroid/pages/me/views/me_view.dart'; +import 'package:flutter_wanandroid/pages/message/bindings/message_detail_web_binding.dart'; +import 'package:flutter_wanandroid/pages/message/views/message_detail_web_page.dart'; import 'package:flutter_wanandroid/pages/navigation/bindings/navigation_binding.dart'; import 'package:flutter_wanandroid/pages/setting/bindings/setting_binding.dart'; import 'package:flutter_wanandroid/pages/setting/views/setting_view.dart'; @@ -20,6 +22,7 @@ import '../pages/article_webpage/bindings/article_detail_binding.dart'; import '../pages/article_webpage/views/article_detail_page.dart'; import '../pages/language/bindings/language_binding.dart'; import '../pages/language/views/language_view.dart'; +import '../pages/message/bindings/message_binding.dart'; import '../pages/not_found/not_found_view.dart'; import '../pages/theme/bindings/theme_binding.dart'; import '../pages/theme/views/theme_view.dart'; @@ -32,7 +35,7 @@ class AppPages { static String init = Routes.main.nameToRoute(); static final unknownRoute = - GetPage(name: Routes.notFound.nameToRoute(), page: () => NotFound()); + GetPage(name: Routes.notFound.nameToRoute(), page: () => const NotFound()); static final routes = [ ///主界面 @@ -40,7 +43,7 @@ class AppPages { name: Routes.main.nameToRoute(), page: () => const MainView(), title: Routes.main, - bindings: [MainBinding(),NavigationBinding()], + bindings: [MainBinding(),NavigationBinding(),MessageBinding()], /// binding: MainBinding() ), @@ -91,6 +94,12 @@ class AppPages { title: Routes.articleDetail, binding: ArticleDetailBinding() ), + GetPage( + name: Routes.messageWebView.nameToRoute(), + page: () => const MessageDetailWebPage(), + title: Routes.messageWebView, + binding: MessageDetailWebBinding() + ), ///金币 // GetPage( diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index 4a52bb4..4836442 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -11,6 +11,7 @@ abstract class Routes{ static const coinList='coinList'; static const coin='coin'; static const articleDetail='articleDetail'; + static const messageWebView='messageWebView'; } extension RoutesExtension on String{ diff --git a/lib/widgets/message_list_item_widget.dart b/lib/widgets/message_list_item_widget.dart new file mode 100644 index 0000000..481dd34 --- /dev/null +++ b/lib/widgets/message_list_item_widget.dart @@ -0,0 +1,158 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_wanandroid/models/message_read_list_response.dart'; +import 'package:flutter_wanandroid/pages/message/views/message_detail_web_page.dart'; +import 'package:flutter_wanandroid/provider/base_controller.dart'; +import 'package:flutter_wanandroid/res/app_theme.dart'; +import 'package:flutter_wanandroid/routes/app_routes.dart'; +import 'package:flutter_wanandroid/widgets/ripple_view.dart'; +import 'package:get/get.dart'; +import 'package:getwidget/colors/gf_color.dart'; +import 'package:getwidget/components/card/gf_card.dart'; +import '../i18n/i18n_keys.dart'; +import '../models/home_article_response.dart'; +import '../res/constant.dart'; +import '../res/gaps.dart'; +import '../utils/decoration_style.dart'; +import '../utils/html_utils.dart'; +import 'cached_network_image_view.dart'; + +/// 类名: message_list_item_widget.dart +/// 描述: 消息列表Item + +class MessageListItemWidget extends GetView { + const MessageListItemWidget({ + Key? key, + required this.dataList, + required this.index, + required this.onCollectClick, + }) : super(key: key); + + /// 文章类表数据源 + final List dataList; + + /// ListView item index + final int index; + + /// 红心收藏点击事件 + final Function(int index) onCollectClick; + + @override + Widget build(BuildContext context) { + return RippleView( + onTap: () => Get.toNamed( + Routes.messageWebView.nameToRoute(), + ///此处要修改 + arguments: { + "data": dataList[index], + "index": index, + "showCollect": true, + }, + ), + child: GFCard( + color: context.colorItemBackground, + padding: const EdgeInsets.all(5), + margin: const EdgeInsets.all(5), + boxFit: BoxFit.cover, + content: Column( + children: [ + chapterCollect(context), + Gaps.vGap10, + //chapterTag(context), + //Gaps.vGap10, + authorShareTime(context) + //leftContainer(context) + ], + ), + )); + } + + Widget leftContainer(BuildContext context) { + return Text(dataList[index].message); + } + + // /// 作者、时间 + Widget authorShareTime(BuildContext context) { + return Column( + children: [chapterTag(context), Gaps.vGap10, leftContainer(context)], + ); + } + + /// tags + Widget chapterTag(BuildContext context) { + return Container( + margin: const EdgeInsets.only(right: 10), + padding: const EdgeInsets.symmetric( + horizontal: 3, + vertical: 2, + ), + decoration: DecorationStyle.imageDecorationCircle( + color: Colors.blueAccent, + borderRadius: 3, + ), + child: Text( + dataList[index].title, + style: const TextStyle( + color: Colors.white, + fontSize: 15, + ), + ), + ); + } + + /// 时间、分享时间 + Widget niceDate(BuildContext context) { + return Row( + children: [ + const Icon(Icons.access_time, size: 15), + Gaps.hGap5, + Text( + dataList[index].niceDate, + style: context.bodyText2Style?.copyWith(fontSize: 12), + ), + ], + ); + } + + /// 分类、是否收藏 + Widget chapterCollect(BuildContext context) { + return Row( + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 3, vertical: 2), + decoration: DecorationStyle.imageDecorationCircle( + color: Colors.lightBlue, + borderRadius: 3, + ), + child: Row( + children: [ + const Icon(Icons.person_outline, size: 15), + Text( + dataList[index].fromUser, + style: context.bodyText2Style?.copyWith(fontSize: 12), + ) + ], + ), + ), + Gaps.hGap10, + Container( + padding: const EdgeInsets.symmetric(horizontal: 3, vertical: 2), + decoration: DecorationStyle.imageDecorationCircle( + color: Colors.red, + borderRadius: 3, + ), + child: Text( + dataList[index].tag, + style: context.bodyText2Style?.copyWith( + fontSize: 12, + color: Colors.white, + ), + ), + ), + const Spacer(), + niceDate(context), + ], + ); + } +}