diff --git a/assets/user/card_description.png b/assets/user/card_description.png new file mode 100644 index 0000000..5fc6743 Binary files /dev/null and b/assets/user/card_description.png differ diff --git a/assets/user/card_description_simple.png b/assets/user/card_description_simple.png new file mode 100644 index 0000000..54107d5 Binary files /dev/null and b/assets/user/card_description_simple.png differ diff --git a/assets/user/icon_money.png b/assets/user/icon_money.png new file mode 100644 index 0000000..f9a3907 Binary files /dev/null and b/assets/user/icon_money.png differ diff --git a/assets/user/user_recommend_single.png b/assets/user/user_recommend_single.png new file mode 100644 index 0000000..9723474 Binary files /dev/null and b/assets/user/user_recommend_single.png differ diff --git a/lib/pages/user/invite/group_invite_card.dart b/lib/pages/user/invite/group_invite_card.dart new file mode 100644 index 0000000..4c911f6 --- /dev/null +++ b/lib/pages/user/invite/group_invite_card.dart @@ -0,0 +1,205 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:oktoast/oktoast.dart'; +import 'package:recook/constants/api.dart'; +import 'package:recook/constants/api_v2.dart'; +import 'package:recook/manager/http_manager.dart'; +import 'package:recook/manager/user_manager.dart'; +import 'package:recook/pages/user/model/user_common_model.dart'; +import 'package:recook/utils/user_level_tool.dart'; +import 'package:recook/constants/header.dart'; +import 'package:recook/widgets/alert.dart'; +import 'package:recook/widgets/progress/re_toast.dart'; +import 'package:velocity_x/velocity_x.dart'; + +class GroupInviteCard extends StatelessWidget { + final UserCommonModel model; + const GroupInviteCard({Key key, @required this.model}) : super(key: key); + _renderItem(String asset, String value) { + return Row( + children: [ + Image.asset(asset, width: 10.w, height: 10.w), + value.text.size(11.sp).color(Color(0xFF999999)).make().expand(), + ], + ).expand(); + } + + upgradeFunc() async { + bool result = await Get.dialog(NormalContentDialog( + title: '提示', + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + '确定将'.text.size(14.sp).color(Color(0xFF333333)).center.make(), + model.nickname.text + .size(14.sp) + .color(Color(0xFF0080FF)) + .center + .make(), + '开设成为您的分销店铺吗?' + .text + .size(14.sp) + .color(Color(0xFF333333)) + .center + .make(), + 10.hb, + '确定后,您将获得${model.nickname}店铺销售额的分销店铺补贴,${model.nickname}将享受钻石店铺权益' + .text + .center + .size(12.sp) + .color(Color(0xFF333333)) + .make(), + ], + ), + items: ['取消', '确定'], + listener: (index) async { + switch (index) { + case 0: + Get.back(result: false); + break; + case 1: + final cancel = ReToast.loading(text: '推荐中'); + ResultData result = await HttpManager.post( + APIV2.userAPI.recommendDiamond, + {'userId': model.userId}, + ); + cancel(); + if (result.data['code'] == 'FAIL') { + Get.back(result: false); + showToast('${result.data['msg']}'); + } else + Get.back(result: true); + break; + } + }, + )); + + if (result == true) { + Get.dialog(Center( + child: GestureDetector( + onTap: () => Get.back(), + child: Material( + color: Colors.transparent, + child: Stack( + children: [ + Image.asset( + R.ASSETS_USER_GROUP_RECOMMEND_BG_PNG, + height: 306.w, + width: 344.w, + ), + Positioned( + left: 0, + right: 0, + top: 62.w, + child: '恭喜! ${UserManager.instance.user.info.nickname}' + .text + .white + .size(16.sp) + .make() + .centered(), + ), + Positioned( + left: 60.w, + right: 60.w, + top: 111.w, + child: Column( + children: [ + '您已成功将' + .text + .color(Color(0xFF333333)) + .size(16.sp) + .make() + .centered(), + '${model.nickname}' + .text + .color(Color(0xFF008AFF)) + .size(16.sp) + .make() + .centered(), + '开设成为您的分销店铺' + .text + .color(Color(0xFF333333)) + .size(16.sp) + .make() + .centered(), + ], + ), + ), + ], + ), + ), + ), + )); + } + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + 16.wb, + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(20.w), + child: FadeInImage.assetNetwork( + placeholder: R.ASSETS_PLACEHOLDER_NEW_1X1_A_PNG, + image: Api.getImgUrl(model.headImgUrl), + height: 40.w, + width: 40.w, + ), + ), + 10.hb, + Image.asset( + UserLevelTool.getRoleLevelIcon(model.roleLevelEnum), + width: 12.w, + height: 12.w, + ), + ], + ), + 10.wb, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 12.hb, + model.nickname.text.black.size(14.sp).make(), + 8.hb, + Row( + children: [ + _renderItem(R.ASSETS_USER_ICON_PHONE_PNG, model.phone), + _renderItem(R.ASSETS_USER_ICON_WECHAT_PNG, model.wechatNo), + ], + ), + 5.hb, + Row( + children: [ + _renderItem( + R.ASSETS_USER_ICON_GROUP_PNG, model.count.toString()), + _renderItem(R.ASSETS_USER_ICON_MONEY_PNG, 'TODO 销售额'), + ], + ), + 16.hb, + ], + ).expand(), + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // if (model.isRecommand) + MaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + minWidth: 0, + padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 12.w), + child: Image.asset( + R.ASSETS_USER_USER_RECOMMEND_SINGLE_PNG, + height: 17.w, + ), + onPressed: upgradeFunc, + ), + 44.hb, + ], + ), + ], + ); + } +} diff --git a/lib/pages/user/invite/my_group_page.dart b/lib/pages/user/invite/my_group_page.dart index 5ea425c..41a5b82 100644 --- a/lib/pages/user/invite/my_group_page.dart +++ b/lib/pages/user/invite/my_group_page.dart @@ -8,6 +8,8 @@ import 'package:recook/widgets/refresh_widget.dart'; import 'package:velocity_x/velocity_x.dart'; import 'package:recook/constants/header.dart'; +//TODO CLEAN BOTTOM CODES. +@Deprecated(" my_group_page need to be cleaned.") class MyGroupPage extends StatefulWidget { final UsersMode type; MyGroupPage({Key key, @required this.type}) : super(key: key); diff --git a/lib/pages/user/invite/my_group_page_v2.dart b/lib/pages/user/invite/my_group_page_v2.dart new file mode 100644 index 0000000..71a6229 --- /dev/null +++ b/lib/pages/user/invite/my_group_page_v2.dart @@ -0,0 +1,251 @@ +import 'package:flutter/material.dart'; +import 'package:recook/pages/user/functions/user_func.dart'; +import 'package:recook/pages/user/invite/group_invite_card.dart'; +import 'package:recook/pages/user/model/user_common_model.dart'; +import 'package:recook/utils/user_level_tool.dart'; +import 'package:recook/widgets/alert.dart'; +import 'package:recook/widgets/recook/recook_scaffold.dart'; +import 'package:recook/widgets/refresh_widget.dart'; +import 'package:velocity_x/velocity_x.dart'; +import 'package:recook/constants/header.dart'; + +class MyGroupPageV2 extends StatefulWidget { + MyGroupPageV2({Key key}) : super(key: key); + + @override + _MyGroupPageV2State createState() => _MyGroupPageV2State(); +} + +class _MyGroupPageV2State extends State { + TextEditingController _editingController = TextEditingController(); + List _models = []; + UsersMode usersMode = UsersMode.MY_GROUP; + int get _allGroupCount { + int value = 0; + _models.forEach((element) { + value += element.count; + }); + return value; + } + + GSRefreshController _refreshController = GSRefreshController.auto(); + + _renderShitTab(String name, UsersMode mode) { + bool same = mode == usersMode; + return MaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + minWidth: double.infinity, + child: name.text + .size(14.sp) + .color(same ? Colors.black : Color(0xFFA3A3A3)) + .make(), + onPressed: () { + usersMode = mode; + _refreshController.requestRefresh(); + setState(() {}); + }, + ).expand(); + } + + Widget get _renderShitVerticalLine => Container( + height: 20.w, + width: 1.w, + color: Color(0xFF979797), + ); + + _renderTopCard() { + return Material( + color: Colors.white, + borderRadius: BorderRadius.circular(4.w), + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Container( + height: 76.w, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(UserLevelTool.currentCardImagePath()), + fit: BoxFit.cover, + ), + ), + alignment: Alignment.center, + child: Image.asset( + UserLevelTool.currentMedalImagePath(), + height: 56.w, + width: 56.w, + ), + ), + Row( + children: [ + 50.hb, + _renderShitTab('自营店铺', UsersMode.MY_GROUP), + _renderShitVerticalLine, + _renderShitTab('分销店铺', UsersMode.MY_RECOMMEND), + _renderShitVerticalLine, + _renderShitTab('代理店铺', UsersMode.MY_REWARD), + ], + ), + ], + ), + ).pSymmetric(h: 36.w, v: 10.w); + } + + _renderSearchBar() { + return Material( + color: Colors.white, + shape: StadiumBorder(), + child: Row( + children: [ + 34.hb, + TextField( + controller: _editingController, + onEditingComplete: () { + _refreshController.requestRefresh(); + }, + style: TextStyle(color: Colors.black), + decoration: InputDecoration( + isDense: true, + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(horizontal: 20.w), + hintText: '请输入昵称/备注/手机号/微信号', + hintStyle: TextStyle( + fontSize: 12.sp, + color: Color(0xFF999999), + ), + ), + ).expand(), + Icon( + Icons.search, + color: Color(0xFF999999), + ), + 20.wb, + ], + ), + ).pSymmetric(h: 15.w, v: 10.w); + } + + _renderShitLine() { + return Container( + height: 10.w, + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFE3E3E3), + borderRadius: BorderRadius.circular(5.w), + boxShadow: [ + BoxShadow( + offset: Offset(0, 2.w), + blurRadius: 4.w, + color: Colors.black.withOpacity(0.2451), + ) + ], + ), + margin: EdgeInsets.symmetric(horizontal: 6.w), + alignment: Alignment.center, + child: Container( + height: 4.w, + width: double.infinity, + margin: EdgeInsets.symmetric(horizontal: 4.w), + decoration: BoxDecoration( + color: Color(0xFF6A6A6A).withOpacity(0.3178), + borderRadius: BorderRadius.circular(2.w), + ), + ), + ); + } + + Widget _renderShitList() { + return Container( + child: Column( + children: [ + Row( + children: [ + 54.hb, + 16.wb, + '我的自营店铺'.text.bold.size(14.sp).black.make(), + MaterialButton( + padding: EdgeInsets.all(4.w), + minWidth: 0, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + child: Icon( + Icons.help_outline, + size: 12.w, + color: Color(0xFFA5A5A5), + ), + onPressed: () { + Alert.show( + context, + NormalContentDialog( + title: '店铺贡献榜图标定义', + content: Image.asset(R.ASSETS_USER_CARD_DESCRIPTION_PNG), + items: ["确认"], + listener: (index) => Alert.dismiss(context), + ), + ); + }, + ), + Spacer(), + Image.asset( + R.ASSETS_USER_ICON_GROUP_PNG, + width: 12.w, + height: 12.w, + ), + _allGroupCount.toString().text.size(12.sp).black.make(), + 20.wb, + ], + ), + ..._models.map((e) => GroupInviteCard(model: e)).toList().sepWidget( + separate: Divider( + indent: 65.w, + endIndent: 15.w, + height: 1.w, + thickness: 1.w, + )), + ], + ), + margin: EdgeInsets.symmetric(horizontal: 16.w), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical(bottom: Radius.circular(2.w)), + boxShadow: [ + BoxShadow( + offset: Offset(0, 2.w), + blurRadius: 4.w, + color: Colors.black.withOpacity(0.1089), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return RecookScaffold( + title: '我的店铺', + whiteBg: true, + body: NestedScrollView( + headerSliverBuilder: (context, _) => + [SliverToBoxAdapter(child: _renderTopCard())], + body: RefreshWidget( + controller: _refreshController, + onRefresh: () async { + _models = await UserFunc.usersList( + usersMode, + keyword: _editingController.text, + ); + _refreshController.refreshCompleted(); + setState(() {}); + }, + body: SingleChildScrollView( + child: Column( + children: [ + _renderSearchBar(), + _renderShitLine(), + _renderShitList(), + ], + ), + ), + ), + ).material(color: AppColor.frenchColor), + ); + } +} diff --git a/lib/pages/user/widget/shop_manager_view.dart b/lib/pages/user/widget/shop_manager_view.dart index 8c0feb4..62f569b 100644 --- a/lib/pages/user/widget/shop_manager_view.dart +++ b/lib/pages/user/widget/shop_manager_view.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:recook/pages/shop/get_platform_award_page.dart'; import 'package:recook/pages/user/functions/user_func.dart'; import 'package:recook/pages/user/invite/my_group_page.dart'; +import 'package:recook/pages/user/invite/my_group_page_v2.dart'; import 'package:recook/utils/custom_route.dart'; import 'package:recook/utils/share_tool.dart'; import 'package:recook/utils/user_level_tool.dart'; @@ -80,10 +82,10 @@ class ShopManagerView extends StatelessWidget { show: showTop, ), _buildGridItem( - title: '我的团队', + title: '我的店铺', subTitle: '有福同享·真壕友', - onTap: () => - CRoute.push(context, MyGroupPage(type: UsersMode.MY_GROUP)), + onTap: () => Get.to(MyGroupPageV2()), + // CRoute.push(context, MyGroupPage(type: UsersMode.MY_GROUP)), path: R.ASSETS_SHOP_MY_GROUP_WEBP, show: showTop, ), diff --git a/lib/utils/custom_route.dart b/lib/utils/custom_route.dart index fab1386..8b66dab 100644 --- a/lib/utils/custom_route.dart +++ b/lib/utils/custom_route.dart @@ -3,7 +3,9 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -//TODO 路由重构计划 + +//TODO CLEAN BOTTOM CODES. +@Deprecated("move CRoute to GetX") class CRoute { static get isIOS => Platform.isIOS; static Route _cPageRoute(BuildContext context, Widget child) { diff --git a/lib/widgets/refresh_widget.dart b/lib/widgets/refresh_widget.dart index 5326f7b..6ea2802 100644 --- a/lib/widgets/refresh_widget.dart +++ b/lib/widgets/refresh_widget.dart @@ -178,6 +178,10 @@ class GSRefreshController { _controller = RefreshController(initialRefresh: initialRefresh); } + GSRefreshController.auto() { + _controller = RefreshController(initialRefresh: true); + } + void requestRefresh() { _controller.requestRefresh(); } @@ -231,7 +235,6 @@ class GSRefreshController { bool get isNoData => (_controller?.footerStatus ?? LoadStatus.canLoading) == LoadStatus.noMore; - void dispose() { _controller.dispose(); }