diff --git a/lib/constants/api.dart b/lib/constants/api.dart index 0da0fa35..49184be1 100644 --- a/lib/constants/api.dart +++ b/lib/constants/api.dart @@ -159,6 +159,9 @@ class _Community { ///社区公告:根据社区公告主键id查询社区公告信息 String get boardDetail => '/user/announcement/findById'; + + ///社区话题:查询最新的所有主题信息 + String get topicList => '/user/gambit/list'; } class _Upload { diff --git a/lib/model/community/community_topic_model.dart b/lib/model/community/community_topic_model.dart new file mode 100644 index 00000000..6508ff3c --- /dev/null +++ b/lib/model/community/community_topic_model.dart @@ -0,0 +1,146 @@ +import 'package:akuCommunity/model/common/img_model.dart'; + +class CommunityTopicModel { + int id; + int createId; + int isComment; + int isLike; + String createName; + String content; + String gambitTitle; + String createDate; + List likeNames; + List imgUrls; + List headSculptureImgUrl; + List gambitThemeCommentVoList; + + CommunityTopicModel( + {this.id, + this.createId, + this.isComment, + this.isLike, + this.createName, + this.content, + this.gambitTitle, + this.createDate, + this.likeNames, + this.imgUrls, + this.headSculptureImgUrl, + this.gambitThemeCommentVoList}); + + CommunityTopicModel.fromJson(Map json) { + id = json['id']; + createId = json['createId']; + isComment = json['isComment']; + isLike = json['isLike']; + createName = json['createName']; + content = json['content']; + gambitTitle = json['gambitTitle']; + createDate = json['createDate']; + if (json['likeNames'] != null) { + likeNames = new List(); + json['likeNames'].forEach((v) { + likeNames.add(new LikeNames.fromJson(v)); + }); + } + if (json['imgUrls'] != null) { + imgUrls = new List(); + json['imgUrls'].forEach((v) { + imgUrls.add(new ImgModel.fromJson(v)); + }); + } else + imgUrls = []; + if (json['headSculptureImgUrl'] != null) { + headSculptureImgUrl = new List(); + json['headSculptureImgUrl'].forEach((v) { + headSculptureImgUrl.add(new ImgModel.fromJson(v)); + }); + } else + headSculptureImgUrl = []; + if (json['gambitThemeCommentVoList'] != null) { + gambitThemeCommentVoList = new List(); + json['gambitThemeCommentVoList'].forEach((v) { + gambitThemeCommentVoList.add(new GambitThemeCommentVoList.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['createId'] = this.createId; + data['isComment'] = this.isComment; + data['isLike'] = this.isLike; + data['createName'] = this.createName; + data['content'] = this.content; + data['gambitTitle'] = this.gambitTitle; + data['createDate'] = this.createDate; + if (this.likeNames != null) { + data['likeNames'] = this.likeNames.map((v) => v.toJson()).toList(); + } + if (this.imgUrls != null) { + data['imgUrls'] = this.imgUrls.map((v) => v.toJson()).toList(); + } + if (this.headSculptureImgUrl != null) { + data['headSculptureImgUrl'] = + this.headSculptureImgUrl.map((v) => v.toJson()).toList(); + } + if (this.gambitThemeCommentVoList != null) { + data['gambitThemeCommentVoList'] = + this.gambitThemeCommentVoList.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class LikeNames { + int id; + String name; + + LikeNames({this.id, this.name}); + + LikeNames.fromJson(Map json) { + id = json['id']; + name = json['name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + return data; + } +} + +class GambitThemeCommentVoList { + int id; + String parentName; + String content; + String createName; + String createDate; + + GambitThemeCommentVoList( + {this.id, + this.parentName, + this.content, + this.createName, + this.createDate}); + + GambitThemeCommentVoList.fromJson(Map json) { + id = json['id']; + parentName = json['parentName']; + content = json['content']; + createName = json['createName']; + createDate = json['createDate']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['parentName'] = this.parentName; + data['content'] = this.content; + data['createName'] = this.createName; + data['createDate'] = this.createDate; + return data; + } +} diff --git a/lib/pages/activities_page/activities_page.dart b/lib/pages/activities_page/activities_page.dart index 2d32e722..9d7944ef 100644 --- a/lib/pages/activities_page/activities_page.dart +++ b/lib/pages/activities_page/activities_page.dart @@ -10,6 +10,8 @@ import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:akuCommunity/widget/activity_card.dart'; import 'package:akuCommunity/widget/bee_scaffold.dart'; +//TODO CLEAN BOTTOM CODES. +@Deprecated("sh*t activities_page need to be cleaned.") class ActivitiesPage extends StatefulWidget { ActivitiesPage({Key key}) : super(key: key); diff --git a/lib/pages/community/community_index.dart b/lib/pages/community/community_index.dart index 83713e91..e6473843 100644 --- a/lib/pages/community/community_index.dart +++ b/lib/pages/community/community_index.dart @@ -12,6 +12,8 @@ import 'package:akuCommunity/utils/headers.dart'; import 'package:akuCommunity/widget/bee_scaffold.dart'; import 'widget/tab_list.dart'; +//TODO CLEAN BOTTOM CODES. +@Deprecated("sh*t community_index need to be cleaned.") class CommunityIndex extends StatefulWidget { CommunityIndex({Key key}) : super(key: key); diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index cfa70f19..99c4b40a 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -5,6 +5,7 @@ import 'dart:convert'; // Flutter imports: import 'package:akuCommunity/model/community/board_model.dart'; import 'package:akuCommunity/ui/home/application/all_application.dart'; +import 'package:akuCommunity/widget/buttons/column_action_button.dart'; import 'package:akuCommunity/widget/views/application_view.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -105,23 +106,6 @@ class _HomePageState extends State }); } - _buildColButton({IconData icon, String title, VoidCallback onTap}) { - return MaterialButton( - onPressed: onTap, - minWidth: 0, - padding: EdgeInsets.symmetric(horizontal: 16.w), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(icon, size: 48.w, color: Colors.black), - 4.hb, - title.text.size(20.sp).black.make(), - ], - ), - ); - } - @override Widget build(BuildContext context) { super.build(context); @@ -132,12 +116,11 @@ class _HomePageState extends State appBar: AnimateAppBar( scrollController: _scrollController, actions: [ - _buildColButton( - icon: AntDesign.bells, + ColumnActionButton( + onPressed: MessageCenterPage().to, title: '消息', - onTap: MessageCenterPage().to, + path: R.ASSETS_ICONS_ALARM_PNG, ), - 16.wb, ], ), body: EasyRefresh( diff --git a/lib/pages/tab_navigator.dart b/lib/pages/tab_navigator.dart index ac10db5f..0269f741 100644 --- a/lib/pages/tab_navigator.dart +++ b/lib/pages/tab_navigator.dart @@ -1,4 +1,5 @@ // Flutter imports: +import 'package:akuCommunity/ui/community/community_views/community_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -37,7 +38,8 @@ class _TabNavigatorState extends State { HomePage(), // MarketPage(), PropertyIndex(), - CommunityIndex(), + // CommunityIndex(), + CommunityPage(), PersonalIndex() ]; } diff --git a/lib/ui/community/community_views/community_page.dart b/lib/ui/community/community_views/community_page.dart new file mode 100644 index 00000000..4d58a2d9 --- /dev/null +++ b/lib/ui/community/community_views/community_page.dart @@ -0,0 +1,67 @@ +import 'package:akuCommunity/ui/community/community_views/my_community_view.dart'; +import 'package:akuCommunity/ui/community/community_views/new_community_view.dart'; +import 'package:akuCommunity/ui/community/community_views/topic/topic_community_view.dart'; +import 'package:akuCommunity/utils/headers.dart'; +import 'package:akuCommunity/widget/bee_scaffold.dart'; +import 'package:akuCommunity/widget/buttons/column_action_button.dart'; +import 'package:akuCommunity/widget/tab_bar/bee_tab_bar.dart'; +import 'package:flutter/material.dart'; + +class CommunityPage extends StatefulWidget { + CommunityPage({Key key}) : super(key: key); + + @override + _CommunityPageState createState() => _CommunityPageState(); +} + +class _CommunityPageState extends State + with TickerProviderStateMixin, AutomaticKeepAliveClientMixin { + TabController _tabController; + List _tabs = ['最新', '话题', '我的']; + @override + void initState() { + super.initState(); + _tabController = TabController( + vsync: this, + length: _tabs.length, + ); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return BeeScaffold( + title: '社区', + actions: [ + ColumnActionButton( + onPressed: () {}, + title: '消息', + path: R.ASSETS_ICONS_ALARM_PNG, + ), + ], + appBarBottom: PreferredSize( + preferredSize: Size.fromHeight(48), + child: Align( + alignment: Alignment.centerLeft, + child: BeeTabBar( + controller: _tabController, + tabs: _tabs, + scrollable: true, + ), + ), + ), + body: TabBarView( + children: [ + NewCommunityView(), + TopicCommunityView(), + MyCommunityView(), + ], + controller: _tabController, + ), + bodyColor: Colors.white, + ); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/ui/community/community_views/my_community_view.dart b/lib/ui/community/community_views/my_community_view.dart new file mode 100644 index 00000000..3a101b32 --- /dev/null +++ b/lib/ui/community/community_views/my_community_view.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class MyCommunityView extends StatefulWidget { + MyCommunityView({Key key}) : super(key: key); + + @override + _MyCommunityViewState createState() => _MyCommunityViewState(); +} + +class _MyCommunityViewState extends State + with AutomaticKeepAliveClientMixin { + @override + Widget build(BuildContext context) { + super.build(context); + return Container(); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/ui/community/community_views/new_community_view.dart b/lib/ui/community/community_views/new_community_view.dart new file mode 100644 index 00000000..626bfbf8 --- /dev/null +++ b/lib/ui/community/community_views/new_community_view.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class NewCommunityView extends StatefulWidget { + NewCommunityView({Key key}) : super(key: key); + + @override + _NewCommunityViewState createState() => _NewCommunityViewState(); +} + +class _NewCommunityViewState extends State + with AutomaticKeepAliveClientMixin { + @override + Widget build(BuildContext context) { + super.build(context); + return Container(); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/ui/community/community_views/topic/topic_community_view.dart b/lib/ui/community/community_views/topic/topic_community_view.dart new file mode 100644 index 00000000..a1e4190c --- /dev/null +++ b/lib/ui/community/community_views/topic/topic_community_view.dart @@ -0,0 +1,125 @@ +import 'dart:ui'; + +import 'package:akuCommunity/ui/community/community_views/topic/topic_detail_page.dart'; +import 'package:akuCommunity/utils/headers.dart'; +import 'package:akuCommunity/constants/api.dart'; +import 'package:akuCommunity/model/community/community_topic_model.dart'; +import 'package:akuCommunity/pages/things_page/widget/bee_list_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyrefresh/easy_refresh.dart'; +import 'package:get/get.dart'; + +class TopicCommunityView extends StatefulWidget { + TopicCommunityView({Key key}) : super(key: key); + + @override + _TopicCommunityViewState createState() => _TopicCommunityViewState(); +} + +class _TopicCommunityViewState extends State + with AutomaticKeepAliveClientMixin { + EasyRefreshController _refreshController = EasyRefreshController(); + + _buildItem(CommunityTopicModel model) { + var firstImg = ''; + if (model?.imgUrls?.isNotEmpty ?? false) { + firstImg = model?.imgUrls?.first?.url ?? ''; + } + return MaterialButton( + padding: EdgeInsets.symmetric(horizontal: 53.w, vertical: 20.w), + onPressed: () { + Get.to(TopicDetailPage(id: model.id)); + }, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.w), + color: Colors.black12, + ), + child: Stack( + children: [ + FadeInImage.assetNetwork( + placeholder: R.ASSETS_IMAGES_LOGO_PNG, + image: API.image(firstImg), + height: 160.w, + width: 250.w, + ), + Positioned( + bottom: 0, + left: 0, + right: 0, + child: ClipRRect( + borderRadius: BorderRadius.vertical( + bottom: Radius.circular(8.w), + ), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + //TODO 等待后端接口补充话题摘要 + // model.summary + child: ('#${''}') + .text + .center + .size(28.sp) + .white + .make() + .material(color: Colors.black26), + ), + ), + ), + ], + ), + ), + 12.wb, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + (model?.gambitTitle ?? '') + .text + .maxLines(2) + .size(28.sp) + .bold + .overflow(TextOverflow.ellipsis) + .make(), + (model?.content ?? '') + .text + .maxLines(1) + .size(22.sp) + .overflow(TextOverflow.ellipsis) + .make(), + 12.hb, + ], + ).expand(), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return BeeListView( + path: API.community.topicList, + controller: _refreshController, + convert: (model) { + return model.tableList + .map((e) => CommunityTopicModel.fromJson(e)) + .toList(); + }, + builder: (items) { + return ListView.separated( + itemBuilder: (context, index) { + return _buildItem(items[index]); + }, + separatorBuilder: (_, __) => 20.hb, + itemCount: items.length, + ); + }, + ); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/ui/community/community_views/topic/topic_detail_page.dart b/lib/ui/community/community_views/topic/topic_detail_page.dart new file mode 100644 index 00000000..0f0efcd1 --- /dev/null +++ b/lib/ui/community/community_views/topic/topic_detail_page.dart @@ -0,0 +1,38 @@ +import 'package:akuCommunity/ui/community/community_views/topic/topic_scrollable_text.dart'; +import 'package:akuCommunity/utils/headers.dart'; +import 'package:flutter/material.dart'; + +class TopicDetailPage extends StatefulWidget { + final int id; + TopicDetailPage({Key key, @required this.id}) : super(key: key); + + @override + _TopicDetailPageState createState() => _TopicDetailPageState(); +} + +class _TopicDetailPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: CustomScrollView( + slivers: [ + SliverAppBar( + expandedHeight: 500.w, + backgroundColor: Colors.transparent, + elevation: 0, + pinned: true, + flexibleSpace: FlexibleSpaceBar( + title: TopicScrollableText(title: '#TEST'), + titlePadding: EdgeInsets.zero, + collapseMode: CollapseMode.pin, + background: Container(color: Colors.red), + ), + ), + SliverToBoxAdapter( + child: 40000.hb, + ), + ], + ), + ); + } +} diff --git a/lib/ui/community/community_views/topic/topic_scrollable_text.dart b/lib/ui/community/community_views/topic/topic_scrollable_text.dart new file mode 100644 index 00000000..bb23f6e0 --- /dev/null +++ b/lib/ui/community/community_views/topic/topic_scrollable_text.dart @@ -0,0 +1,47 @@ +import 'package:akuCommunity/utils/headers.dart'; +import 'package:flutter/material.dart'; + +class TopicScrollableText extends StatefulWidget { + final String title; + TopicScrollableText({Key key, @required this.title}) : super(key: key); + + @override + _TopicScrollableTextState createState() => _TopicScrollableTextState(); +} + +class _TopicScrollableTextState extends State { + ScrollPosition _scrollPosition; + + _positionListener() { + setState(() {}); + } + + @override + void dispose() { + _scrollPosition?.removeListener(_positionListener); + super.dispose(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _scrollPosition = Scrollable.of(context)?.position; + _scrollPosition?.addListener(_positionListener); + } + + double get offset { + if (_scrollPosition.pixels >= 500.w) return 1; + if (_scrollPosition.pixels < 500.w && _scrollPosition.pixels >= 0) { + return _scrollPosition.pixels / 500.w; + } else + return 0; + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(bottom: 202.w - offset * 160.w), + child: Text(widget.title), + ); + } +} diff --git a/lib/widget/tab_bar/bee_tab_bar.dart b/lib/widget/tab_bar/bee_tab_bar.dart index 19c09a29..837c5d94 100644 --- a/lib/widget/tab_bar/bee_tab_bar.dart +++ b/lib/widget/tab_bar/bee_tab_bar.dart @@ -11,9 +11,14 @@ class BeeTabBar extends StatefulWidget with PreferredSizeWidget { final TabController controller; final List tabs; final Function(int index) onTap; - BeeTabBar( - {Key key, @required this.controller, @required this.tabs, this.onTap}) - : super(key: key); + final bool scrollable; + BeeTabBar({ + Key key, + @required this.controller, + @required this.tabs, + this.onTap, + this.scrollable = false, + }) : super(key: key); @override _BeeTabBarState createState() => _BeeTabBarState(); @@ -54,6 +59,7 @@ class _BeeTabBarState extends State { indicatorSize: TabBarIndicatorSize.label, tabs: widget.tabs.map((e) => Tab(text: e)).toList(), onTap: widget.onTap, + isScrollable: widget.scrollable, ); } }