From 2ec413a3355511d288e04a96ce6b365ee4b37597 Mon Sep 17 00:00:00 2001 From: PH2 <1293456824@qq.com> Date: Mon, 23 Nov 2020 13:41:05 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=BE=AE=E4=BF=A1=E5=8F=B7=E7=9A=84?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=202=E3=80=81=E5=BE=AE=E4=BF=A1=E5=AF=BC?= =?UTF-8?q?=E5=B8=88=E7=9A=84=E5=AE=9E=E7=8E=B0=203=E3=80=81=E6=88=91?= =?UTF-8?q?=E7=9A=84=E4=BA=BA=E8=84=89=E5=A4=B4=E5=83=8F=E5=8F=98=E5=9C=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/images/qrcode/default_qrcode.png | Bin 0 -> 5009 bytes .../mine_detail_page/mine_detail_page.dart | 7 + .../models/mine_detail_model.dart | 7 +- .../bloc/upload_wechat_bloc.dart | 52 +++ .../bloc/upload_wechat_event.dart | 17 + .../bloc/upload_wechat_repository.dart | 65 ++++ .../bloc/upload_wechat_state.dart | 24 ++ .../model/upload_wechat_model.dart | 18 + .../upload_wechat_page.dart | 288 ++++++++++++++++ .../bloc/wechat_teacher_bloc.dart | 62 ++++ .../bloc/wechat_teacher_event.dart | 14 + .../bloc/wechat_teacher_repository.dart | 89 +++++ .../bloc/wechat_teacher_state.dart | 25 ++ .../model/wechat_teacher_data_model.dart | 32 ++ .../model/wechat_teacher_style_model.dart | 293 ++++++++++++++++ .../wechat_teacher_page.dart | 326 +++++++++++++++--- .../widgets/wechat_teacher_item.dart | 118 +++++-- lib/register.dart | 7 +- .../mine/mine_data/mine_data_widget.dart | 8 +- .../team/fans_list/team_fans_item.dart | 10 +- .../team/recommend/team_recommend_widget.dart | 8 +- .../team_details_referrer_widget.dart | 7 +- pubspec.yaml | 3 +- 23 files changed, 1378 insertions(+), 102 deletions(-) create mode 100755 assets/images/qrcode/default_qrcode.png create mode 100644 lib/pages/upload_wechat_page/bloc/upload_wechat_bloc.dart create mode 100644 lib/pages/upload_wechat_page/bloc/upload_wechat_event.dart create mode 100644 lib/pages/upload_wechat_page/bloc/upload_wechat_repository.dart create mode 100644 lib/pages/upload_wechat_page/bloc/upload_wechat_state.dart create mode 100644 lib/pages/upload_wechat_page/model/upload_wechat_model.dart create mode 100644 lib/pages/upload_wechat_page/upload_wechat_page.dart create mode 100644 lib/pages/wechat_teacher_page/bloc/wechat_teacher_bloc.dart create mode 100644 lib/pages/wechat_teacher_page/bloc/wechat_teacher_event.dart create mode 100644 lib/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart create mode 100644 lib/pages/wechat_teacher_page/bloc/wechat_teacher_state.dart create mode 100644 lib/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart create mode 100644 lib/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart diff --git a/assets/images/qrcode/default_qrcode.png b/assets/images/qrcode/default_qrcode.png new file mode 100755 index 0000000000000000000000000000000000000000..948ced4532689c2a98be9041f7bf278956603554 GIT binary patch literal 5009 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 literal 0 HcmV?d00001 diff --git a/lib/pages/mine_detail_page/mine_detail_page.dart b/lib/pages/mine_detail_page/mine_detail_page.dart index 89db894..125a661 100644 --- a/lib/pages/mine_detail_page/mine_detail_page.dart +++ b/lib/pages/mine_detail_page/mine_detail_page.dart @@ -11,6 +11,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:zhiying_base_widget/dialog/loading/loading.dart'; import 'package:zhiying_base_widget/pages/mine_detail_page/mine_detail_bloc.dart'; import 'package:zhiying_base_widget/pages/mine_detail_page/models/mine_detail_model.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/upload_wechat_page.dart'; import 'package:zhiying_base_widget/widgets/others/action_date_alert/action_date_alert.dart'; import 'package:zhiying_base_widget/widgets/others/action_list_alert/action_list_alert.dart'; import 'package:zhiying_base_widget/widgets/others/action_selected_alert/action_selected_alert.dart'; @@ -133,6 +134,12 @@ class _MineDetailContainerState extends State<_MineDetailContainer> { DateTime.fromMillisecondsSinceEpoch( registTime * 1000)) : user?.registerTime ?? ''), + + Padding( padding: const EdgeInsets.only(top: 8),child: _createItem('填写微信号', user?.is_upload_wx == '1' ? '已上传' : '未上传微信号与二维码', + onTap: (){ + Navigator.push(context, CupertinoPageRoute(builder: (_) => UploadWeChatPage())); + })) + ], ), ); diff --git a/lib/pages/mine_detail_page/models/mine_detail_model.dart b/lib/pages/mine_detail_page/models/mine_detail_model.dart index 9319c07..0dca455 100644 --- a/lib/pages/mine_detail_page/models/mine_detail_model.dart +++ b/lib/pages/mine_detail_page/models/mine_detail_model.dart @@ -6,6 +6,7 @@ class MineDetailModel { String registerTime; String fileBucketUrl; String fileFormat; + String is_upload_wx; MineDetailModel( {this.avatar, @@ -14,7 +15,9 @@ class MineDetailModel { this.birthday, this.registerTime, this.fileBucketUrl, - this.fileFormat}); + this.fileFormat, + this.is_upload_wx, + }); MineDetailModel.fromJson(Map json) { avatar = json['avatar']; @@ -24,6 +27,7 @@ class MineDetailModel { registerTime = json['register_time']; fileBucketUrl = json['file_bucket_url']; fileFormat = json['file_format']; + is_upload_wx = json['is_upload_wx']; } Map toJson() { @@ -35,6 +39,7 @@ class MineDetailModel { data['register_time'] = this.registerTime; data['file_bucket_url'] = this.fileBucketUrl; data['file_format'] = this.fileFormat; + data['is_upload_wx'] = this.is_upload_wx; return data; } } diff --git a/lib/pages/upload_wechat_page/bloc/upload_wechat_bloc.dart b/lib/pages/upload_wechat_page/bloc/upload_wechat_bloc.dart new file mode 100644 index 0000000..b19b67e --- /dev/null +++ b/lib/pages/upload_wechat_page/bloc/upload_wechat_bloc.dart @@ -0,0 +1,52 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/bloc/upload_wechat_repository.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'upload_wechat_event.dart'; +import 'upload_wechat_state.dart'; + +class UploadWeChatBloc extends Bloc { + @override + UploadWeChatState get initialState => UploadWeChatInitial(); + + UploadWeChatRepository repository; + + UploadWeChatBloc(this.repository); + + @override + Stream mapEventToState( + UploadWeChatEvent event, + ) async* { + /// 初始化 + if (event is UploadWeChatInitEvent) { + yield* _mapInitEventToState(event); + } + + /// 更新微信信息 + if (event is UploadWeChatSubmitEvent) { + yield* _mapUpdateEventToState(event); + } + } + + /// 初始化 + Stream _mapInitEventToState(UploadWeChatInitEvent event) async* { + var result = await repository.fetchInitData(); + if (!EmptyUtil.isEmpty(result)) { + yield UploadWeChatLoadedState(model: result); + } else { + yield UploadWeChatInitErrorState(); + } + } + + /// 更新微信信息 + Stream _mapUpdateEventToState(UploadWeChatSubmitEvent event) async* { + var result = await repository.fetchUpdateWeChatInfo(event?.file, event?.wxAccount); + if (!EmptyUtil.isEmpty(result)) { + yield UploadWeChatSubmitSuccessState(); + yield UploadWeChatLoadedState(model: result); + } else { + yield UploadWeChatSubmitErrorState(); + } + } +} diff --git a/lib/pages/upload_wechat_page/bloc/upload_wechat_event.dart b/lib/pages/upload_wechat_page/bloc/upload_wechat_event.dart new file mode 100644 index 0000000..c6bf742 --- /dev/null +++ b/lib/pages/upload_wechat_page/bloc/upload_wechat_event.dart @@ -0,0 +1,17 @@ +import 'dart:io'; + +import 'package:meta/meta.dart'; + +@immutable +abstract class UploadWeChatEvent {} + +/// 获取数据 +class UploadWeChatInitEvent extends UploadWeChatEvent {} + +/// 上传或者更新二维码或者图片 +class UploadWeChatSubmitEvent extends UploadWeChatEvent { + File file; + String wxAccount; + + UploadWeChatSubmitEvent({this.file, this.wxAccount}); +} diff --git a/lib/pages/upload_wechat_page/bloc/upload_wechat_repository.dart b/lib/pages/upload_wechat_page/bloc/upload_wechat_repository.dart new file mode 100644 index 0000000..78e1b59 --- /dev/null +++ b/lib/pages/upload_wechat_page/bloc/upload_wechat_repository.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:path/path.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/model/upload_wechat_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; + +class UploadWeChatRepository { + /// 获取数据 + Future fetchInitData() async { + try { + var result = await NetUtil.post('/api/v1/user/info/wx', method: NetMethod.GET); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return UploadWeChatModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + /// 上传信息 + Future fetchUpdateWeChatInfo(final File file, final String wxAccount) async { + try { + if (!EmptyUtil.isEmpty(file) && !EmptyUtil.isEmpty(wxAccount)) { + String uploadUrl = await uploadFile(file); + if (EmptyUtil.isEmpty(uploadUrl)) return null; + var result = await NetUtil.post('/api/v1/user/info/wx', params: {'wx_account': wxAccount, 'wx_qrcode': uploadUrl}, method: NetMethod.POST); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return UploadWeChatModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + } + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + /// 上传图片 + Future uploadFile(final File imageFile) async { + try { + List originBytes = await imageFile.readAsBytes(); + var result1 = await NetUtil.post('/api/v1/img/upload', params: {'dir': 'qrcode', 'file_size': originBytes.length, 'file_name': basename(imageFile.path)}, method: NetMethod.PUT); + if (NetUtil.isSuccess(result1) && !EmptyUtil.isEmpty(result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]) && !EmptyUtil.isEmpty(result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['token'])) { + String token = result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['token']; + String host = result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['host']; + String key = result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['key']; + String method = result1[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['method']; + + var result2 = await NetUtil.uploadFile(host, imageFile, params: {'key': key, 'token': token}, method: method); + Map json = jsonDecode(result2.toString()); + if (NetUtil.isSuccess(json) && !EmptyUtil.isEmpty(json[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + String filename = json['data']['fname'] ?? ''; + print(filename); + // filename += '?${DateTime.now().millisecondsSinceEpoch.toString()}'; + // print(filename); + // ⚠️ 这里返回key是因为fname是带有域名的,所以直接用key即可 + return !EmptyUtil.isEmpty(filename) ? key : null; + } + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } +} diff --git a/lib/pages/upload_wechat_page/bloc/upload_wechat_state.dart b/lib/pages/upload_wechat_page/bloc/upload_wechat_state.dart new file mode 100644 index 0000000..8016642 --- /dev/null +++ b/lib/pages/upload_wechat_page/bloc/upload_wechat_state.dart @@ -0,0 +1,24 @@ +import 'package:meta/meta.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/model/upload_wechat_model.dart'; + +@immutable +abstract class UploadWeChatState {} + +/// 初始化 +class UploadWeChatInitial extends UploadWeChatState {} + +/// 初始化失败 +class UploadWeChatInitErrorState extends UploadWeChatState{} + +/// 数据加载成功 +class UploadWeChatLoadedState extends UploadWeChatState { + UploadWeChatModel model; + + UploadWeChatLoadedState({this.model}); +} + +/// 上传信息成功 +class UploadWeChatSubmitSuccessState extends UploadWeChatState {} + +/// 上传信息失败 +class UploadWeChatSubmitErrorState extends UploadWeChatState {} diff --git a/lib/pages/upload_wechat_page/model/upload_wechat_model.dart b/lib/pages/upload_wechat_page/model/upload_wechat_model.dart new file mode 100644 index 0000000..52af7e5 --- /dev/null +++ b/lib/pages/upload_wechat_page/model/upload_wechat_model.dart @@ -0,0 +1,18 @@ +class UploadWeChatModel { + String wxAccount; + String wxQrcode; + + UploadWeChatModel({this.wxAccount, this.wxQrcode}); + + UploadWeChatModel.fromJson(Map json) { + wxAccount = json['wx_account']; + wxQrcode = json['wx_qrcode']; + } + + Map toJson() { + final Map data = new Map(); + data['wx_account'] = this.wxAccount; + data['wx_qrcode'] = this.wxQrcode; + return data; + } +} diff --git a/lib/pages/upload_wechat_page/upload_wechat_page.dart b/lib/pages/upload_wechat_page/upload_wechat_page.dart new file mode 100644 index 0000000..6f8ffb3 --- /dev/null +++ b/lib/pages/upload_wechat_page/upload_wechat_page.dart @@ -0,0 +1,288 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/bloc/upload_wechat_bloc.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/bloc/upload_wechat_event.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/bloc/upload_wechat_repository.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/bloc/upload_wechat_state.dart'; +import 'package:zhiying_base_widget/pages/upload_wechat_page/model/upload_wechat_model.dart'; +import 'package:zhiying_base_widget/widgets/others/action_selected_alert/action_selected_alert.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class UploadWeChatPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => UploadWeChatBloc(UploadWeChatRepository())..add(UploadWeChatInitEvent()), + child: _UploadWeChatPage(), + ); + } +} + +class _UploadWeChatPage extends StatefulWidget { + @override + __UploadWeChatPageState createState() => __UploadWeChatPageState(); +} + +class __UploadWeChatPageState extends State<_UploadWeChatPage> { + /// 是否上传中 + bool _isUploading = false; + bool _canSubmit = true; + TextEditingController _editingController; + File _qrCodeImg; + + /// 选择图片 + void _onAddImage() async { + Logger.debug('上传图片'); + + var status = await Permission.photos.status; + if (status != PermissionStatus.granted) { + status = await Permission.photos.request(); + } + if (status == PermissionStatus.denied) { + Fluttertoast.showToast(msg: '暂无权限,图片选择失败'); + return null; + } + + final picker = ImagePicker(); + PickedFile file = await picker.getImage(source: ImageSource.gallery); + + if (file == null) return; + + setState(() { + _qrCodeImg = File(file.path); + }); + // File resultFile = await EncodeUtil.compressImage(file, 800); + } + + /// 点击提交事件 + void _submitOnClick() { + if (!_isUploading) { + + String wxAccount = _editingController?.text?.toString(); + if (EmptyUtil.isEmpty(wxAccount)) { + Fluttertoast.cancel(); + Fluttertoast.showToast(msg: '微信号不能为空'); + return; + } + if (EmptyUtil.isEmpty(_qrCodeImg)) { + Fluttertoast.cancel(); + Fluttertoast.showToast(msg: '请上传二维码'); + return; + } + + setState(() { + _isUploading = true; + }); + BlocProvider.of(context).add(UploadWeChatSubmitEvent(file: _qrCodeImg, wxAccount: wxAccount)); + } + } + + @override + void initState() { + _editingController = TextEditingController(); + super.initState(); + } + + @override + void dispose() { + _editingController?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: HexColor.fromHex('#FFF9F9F9'), + appBar: _buildAppBarWidget(), + body: SingleChildScrollView( + child: BlocConsumer( + listener: (context, state) {}, + buildWhen: (prov, current) { + if (current is UploadWeChatInitErrorState) { + return false; + } + if (current is UploadWeChatSubmitErrorState) { + _isUploading = false; + } + if (current is UploadWeChatSubmitSuccessState) { + _isUploading = false; + Fluttertoast.showToast(msg: '上传成功'); + } + return true; + }, + builder: (context, state) { + if (state is UploadWeChatLoadedState) { + if (!EmptyUtil.isEmpty(state?.model?.wxAccount)) { + _editingController.text = state.model.wxAccount; + } + return _buildMainWidget(state?.model); + } + return _buildMainWidget(null); + }, + ), + ), + ); + } + + Widget _buildMainWidget(UploadWeChatModel model) { + return Column( + children: [ + _buildWeChatImageWidget(model), + _createLine(), + _createInput('微信号', _editingController), + Padding(padding: const EdgeInsets.symmetric(horizontal: 12.5, vertical: 15), child: _buildSubmitButtonWidget()), + ], + ); + } + + /// 二维码图片 + Widget _buildWeChatImageWidget(UploadWeChatModel model) { + return Container( + width: double.infinity, + margin: const EdgeInsets.only(top: 5), + padding: const EdgeInsets.only(top: 15, bottom: 15), + decoration: BoxDecoration( + color: HexColor.fromHex('#FFFFFFFF'), + ), + child: Column( + children: [ + GestureDetector( + onTap: () => _onAddImage(), + behavior: HitTestBehavior.opaque, + child: Container( + height: 90, + width: 90, + // color: Colors.red, + child: !EmptyUtil.isEmpty(_qrCodeImg) + ? Image.file( + _qrCodeImg, + fit: BoxFit.cover, + ) + : !EmptyUtil.isEmpty(model?.wxQrcode) + ? CachedNetworkImage( + imageUrl: model?.wxQrcode ?? '', + fit: BoxFit.cover, + ) + : Image.asset( + 'assets/images/qrcode/default_qrcode.png', + package: 'zhiying_base_widget', + ), + ), + ), + const SizedBox(height: 6), + GestureDetector( + onTap: () => _onAddImage(), + behavior: HitTestBehavior.opaque, + child: Text( + '点击上传二维码', + style: TextStyle(color: HexColor.fromHex('#FF999999'), fontSize: 13), + ), + ) + ], + ), + ); + } + + /// 阴影 + Widget _createLine() { + return Container( + width: double.infinity, + height: 0.5, + margin: EdgeInsets.only(left: 12.5, right: 12.5), + color: HexColor.fromHex('#FFF7F7F7'), + ); + } + + Widget _createInput(String title, TextEditingController controller, {VoidCallback onTap}) { + return GestureDetector( + child: Container( + padding: EdgeInsets.only(left: 12.5, right: 12.5), + height: 48, + color: Colors.white, + child: Row( + children: [ + Expanded( + child: Text( + title ?? '', + style: TextStyle(fontSize: 13, color: Color(0xff333333), fontWeight: FontWeight.bold), + ), + ), + Expanded( + child: CupertinoTextField( + decoration: BoxDecoration(color: Colors.transparent), + textInputAction: TextInputAction.done, + controller: controller, + textAlign: TextAlign.right, + placeholder: '请输入微信号', + style: TextStyle( + fontSize: 13, + color: Color(0xff999999), + ), + ), + ), + onTap == null + ? Container() + : Icon( + Icons.arrow_forward_ios, + size: 12, + color: Color(0xff999999), + ) + ], + ), + ), + onTap: onTap, + ); + } + + /// 提交按钮 + Widget _buildSubmitButtonWidget() { + return Material( + child: Container( + height: 48, + width: double.infinity, + color: Colors.white, + child: RaisedButton( + child: Text( + _isUploading ? '提交中...' : '提交', + style: TextStyle(fontSize: 15), + ), + textColor: HexColor.fromHex('#FFFFFF'), + color: HexColor.fromHex('#FFFF4242'), + disabledColor: HexColor.fromHex('#F5F5F5'), + disabledTextColor: HexColor.fromHex('#999999'), + elevation: 5, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(52 / 2)), + onPressed: _canSubmit ? _submitOnClick : null, + ), + ), + ); + } + + /// appbar + Widget _buildAppBarWidget() { + return AppBar( + backgroundColor: HexColor.fromHex('#FFFFFF'), + brightness: Brightness.light, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + size: 22, + color: HexColor.fromHex('#333333'), + ), + onPressed: () => Navigator.maybePop(context), + ), + title: Text( + '填写微信号', + style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 15, fontWeight: FontWeight.bold), + ), + centerTitle: true, + elevation: 0, + ); + } +} diff --git a/lib/pages/wechat_teacher_page/bloc/wechat_teacher_bloc.dart b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_bloc.dart new file mode 100644 index 0000000..19d8457 --- /dev/null +++ b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_bloc.dart @@ -0,0 +1,62 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart'; +import 'wechat_teacher_event.dart'; +import 'wechat_teacher_state.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; + +class WechatTeacherBloc extends Bloc { + @override + WechatTeacherState get initialState => WechatTeacherInitial(); + + WechatTeacherRepository repository; + + WechatTeacherBloc(this.repository); + + @override + Stream mapEventToState( + WechatTeacherEvent event, + ) async* { + /// 初始化 + if (event is WechatTeacherInitEvent) { + yield* _mapInitEventToState(event); + } + + /// 绑定微信导师 + if (event is WechatTeacherBindEvent) { + yield* _mapBindEventToState(event); + } + } + + /// 初始化 + Stream _mapInitEventToState(WechatTeacherInitEvent event) async* { + var cacheStyle = await repository.fetchCachedStyle(); + if (!EmptyUtil.isEmpty(cacheStyle)) { + yield WechatTeacherLoadedState(dataModel: null, styleModel: cacheStyle); + } + var netStyle = await repository.fetchInitStyle(); + if (!EmptyUtil.isEmpty(netStyle)) { + yield WechatTeacherLoadedState(dataModel: null, styleModel: netStyle); + } + var data = await repository.fetchInitData(); + if (!EmptyUtil.isEmpty(data) && (!EmptyUtil.isEmpty(cacheStyle) || !EmptyUtil.isEmpty(netStyle))) { + yield WechatTeacherLoadedState(styleModel: !EmptyUtil.isEmpty(netStyle) ? netStyle : cacheStyle, dataModel: data); + } else { + yield WechatTeacherInitErrorState(); + } + } + + /// 绑定微信导师 + Stream _mapBindEventToState(WechatTeacherBindEvent event) async* { + var style = repository.styleModel; + var result = await repository.bindTeacher(event?.teacherWxChat); + if (!EmptyUtil.isEmpty(result)) { + yield WechatTeacherBindSuccessState(); + yield WechatTeacherLoadedState(styleModel: style, dataModel: result); + } else { + yield WechatTeacherBindErrorState(); + yield WechatTeacherLoadedState(styleModel: style, dataModel: null); + } + } +} diff --git a/lib/pages/wechat_teacher_page/bloc/wechat_teacher_event.dart b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_event.dart new file mode 100644 index 0000000..090b9b5 --- /dev/null +++ b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_event.dart @@ -0,0 +1,14 @@ +import 'package:meta/meta.dart'; + +@immutable +abstract class WechatTeacherEvent {} + +/// 初始化 +class WechatTeacherInitEvent extends WechatTeacherEvent {} + +/// 绑定邀请人 +class WechatTeacherBindEvent extends WechatTeacherEvent { + String teacherWxChat; + + WechatTeacherBindEvent({this.teacherWxChat}); +} diff --git a/lib/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart new file mode 100644 index 0000000..19824df --- /dev/null +++ b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart @@ -0,0 +1,89 @@ +import 'dart:convert'; + +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; + +class WechatTeacherRepository { + final Map data; + + WechatTeacherRepository(this.data); + + WechatTeacherStyleModel _styleModel; + WechatTeacherDataModel _dataModel; + + WechatTeacherStyleModel get styleModel => _styleModel; + + WechatTeacherDataModel get dataModel => _dataModel; + + /// 初始化 + Future fetchInitStyle() async { + try { + String skipIdentifier = + !EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.wechat_teacher'; + + var result = await NetUtil.post('/api/v1/mod/$skipIdentifier', method: NetMethod.GET, cache: true); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return handleStyleModel(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + Future fetchCachedStyle() async { + try { + String skipIdentifier = + !EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.wechat_teacher'; + var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skipIdentifier'); + if (!EmptyUtil.isEmpty(result)) { + return handleStyleModel(result); + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + WechatTeacherStyleModel handleStyleModel(final Map result) { + var modListData = result['mod_list'][0]['data']; + if (!EmptyUtil.isEmpty(modListData)) { + WechatTeacherStyleModel model = WechatTeacherStyleModel.fromJson(modListData is String ? jsonDecode(modListData) : modListData); + if (!EmptyUtil.isEmpty(model)) { + _styleModel = model; + } + return _styleModel; + } + return null; + } + + Future fetchInitData() async { + try { + var result = await NetUtil.post('/api/v1/user/wx_teacher', method: NetMethod.GET); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + WechatTeacherDataModel model = WechatTeacherDataModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + if (!EmptyUtil.isEmpty(model)) { + _dataModel = model; + } + return _dataModel; + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } + + /// 绑定导师 + Future bindTeacher(final String wxchatAccount) async { + try { + var result = await NetUtil.post('/api/v1/user/myteam/relate', method: NetMethod.POST, params: {'invite_code': wxchatAccount}); + if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return await fetchInitData(); + } + } catch (e, s) { + Logger.error(e, s); + } + return null; + } +} diff --git a/lib/pages/wechat_teacher_page/bloc/wechat_teacher_state.dart b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_state.dart new file mode 100644 index 0000000..642920e --- /dev/null +++ b/lib/pages/wechat_teacher_page/bloc/wechat_teacher_state.dart @@ -0,0 +1,25 @@ +import 'package:meta/meta.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart'; + +@immutable +abstract class WechatTeacherState {} + +class WechatTeacherInitial extends WechatTeacherState {} + +/// 数据加载成功 +class WechatTeacherLoadedState extends WechatTeacherState { + WechatTeacherDataModel dataModel; + WechatTeacherStyleModel styleModel; + + WechatTeacherLoadedState({this.dataModel, this.styleModel}); +} + +/// 初始化失败 +class WechatTeacherInitErrorState extends WechatTeacherState {} + +/// 绑定导师成功 +class WechatTeacherBindSuccessState extends WechatTeacherState {} + +/// 绑定导师失败 +class WechatTeacherBindErrorState extends WechatTeacherState {} diff --git a/lib/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart b/lib/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart new file mode 100644 index 0000000..fbc33c5 --- /dev/null +++ b/lib/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart @@ -0,0 +1,32 @@ +class WechatTeacherDataModel { + String isBindTeacher; + String teacherAvatar; + String teacherUsername; + String teacherWechatAccount; + String teacherWxQrCode; + + WechatTeacherDataModel( + {this.isBindTeacher, + this.teacherAvatar, + this.teacherUsername, + this.teacherWechatAccount, + this.teacherWxQrCode}); + + WechatTeacherDataModel.fromJson(Map json) { + isBindTeacher = json['is_bind_teacher']; + teacherAvatar = json['teacher_avatar']; + teacherUsername = json['teacher_username']; + teacherWechatAccount = json['teacher_wechat_account']; + teacherWxQrCode = json['teacher_wx_qr_code']; + } + + Map toJson() { + final Map data = new Map(); + data['is_bind_teacher'] = this.isBindTeacher; + data['teacher_avatar'] = this.teacherAvatar; + data['teacher_username'] = this.teacherUsername; + data['teacher_wechat_account'] = this.teacherWechatAccount; + data['teacher_wx_qr_code'] = this.teacherWxQrCode; + return data; + } +} diff --git a/lib/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart b/lib/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart new file mode 100644 index 0000000..c549299 --- /dev/null +++ b/lib/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart @@ -0,0 +1,293 @@ +class WechatTeacherStyleModel { + String appBarName; + String appBarNameColor; + String appBarBgColor; + String bgColor; + String bgImg; + String teacherDialogTitle; + String teacherDialogTitleColor; + String teacherDialogBgColor; + CommStyle commStyle; + NobindTeacherDialog nobindTeacherDialog; + MyTeacher myTeacher; + BindTeacherDialog bindTeacherDialog; + String chatDialogImg; + OfficalWxchat officalWxchat; + + WechatTeacherStyleModel({ + this.appBarName, + this.appBarNameColor, + this.appBarBgColor, + this.bgColor, + this.bgImg, + this.teacherDialogTitle, + this.teacherDialogTitleColor, + this.teacherDialogBgColor, + this.commStyle, + this.nobindTeacherDialog, + this.myTeacher, + this.bindTeacherDialog, + this.chatDialogImg, + this.officalWxchat, + }); + + WechatTeacherStyleModel.fromJson(Map json) { + appBarName = json['app_bar_name']; + appBarNameColor = json['app_bar_name_color']; + appBarBgColor = json['app_bar_bg_color']; + bgColor = json['bg_color']; + bgImg = json['bg_img']; + teacherDialogTitle = json['teacher_dialog_title']; + teacherDialogTitleColor = json['teacher_dialog_title_color']; + teacherDialogBgColor = json['teacher_dialog_bg_color']; + commStyle = json['comm_style'] != null ? new CommStyle.fromJson(json['comm_style']) : null; + nobindTeacherDialog = json['nobind_teacher_dialog'] != null ? new NobindTeacherDialog.fromJson(json['nobind_teacher_dialog']) : null; + myTeacher = json['my_teacher'] != null ? new MyTeacher.fromJson(json['my_teacher']) : null; + bindTeacherDialog = json['bind_teacher_dialog'] != null ? new BindTeacherDialog.fromJson(json['bind_teacher_dialog']) : null; + chatDialogImg = json['chat_dialog_img']; + officalWxchat = json['offical_wxchat'] != null ? new OfficalWxchat.fromJson(json['offical_wxchat']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['app_bar_name'] = this.appBarName; + data['app_bar_name_color'] = this.appBarNameColor; + data['app_bar_bg_color'] = this.appBarBgColor; + data['bg_color'] = this.bgColor; + data['bg_img'] = this.bgImg; + data['teacher_dialog_title'] = this.teacherDialogTitle; + data['teacher_dialog_title_color'] = this.teacherDialogTitleColor; + data['teacher_dialog_bg_color'] = this.teacherDialogBgColor; + if (this.commStyle != null) { + data['comm_style'] = this.commStyle.toJson(); + } + if (this.nobindTeacherDialog != null) { + data['nobind_teacher_dialog'] = this.nobindTeacherDialog.toJson(); + } + if (this.myTeacher != null) { + data['my_teacher'] = this.myTeacher.toJson(); + } + if (this.bindTeacherDialog != null) { + data['bind_teacher_dialog'] = this.bindTeacherDialog.toJson(); + } + data['chat_dialog_img'] = this.chatDialogImg; + if (this.officalWxchat != null) { + data['offical_wxchat'] = this.officalWxchat.toJson(); + } + return data; + } +} + +class CommStyle { + String wechatAccountColor; + String btnTextColor; + String btnBgColor; + + CommStyle({ + this.wechatAccountColor, + this.btnTextColor, + this.btnBgColor, + }); + + CommStyle.fromJson(Map json) { + wechatAccountColor = json['wechat_account_color']; + btnTextColor = json['btn_text_color']; + btnBgColor = json['btn_bg_color']; + } + + Map toJson() { + final Map data = new Map(); + data['wechat_account_color'] = this.wechatAccountColor; + data['btn_text_color'] = this.btnTextColor; + data['btn_bg_color'] = this.btnBgColor; + return data; + } +} + +class NobindTeacherDialog { + String inputHintText; + String inputHintTextColor; + String inputLineColor; + String btnText; + + NobindTeacherDialog({ + this.inputHintText, + this.inputHintTextColor, + this.inputLineColor, + this.btnText, + }); + + NobindTeacherDialog.fromJson(Map json) { + inputHintText = json['input_hint_text']; + inputHintTextColor = json['input_hint_text_color']; + inputLineColor = json['input_line_color']; + btnText = json['btn_text']; + } + + Map toJson() { + final Map data = new Map(); + data['input_hint_text'] = this.inputHintText; + data['input_hint_text_color'] = this.inputHintTextColor; + data['input_line_color'] = this.inputLineColor; + data['btn_text'] = this.btnText; + return data; + } +} + +class MyTeacher { + String teacherType; + DefalutTeacher defalutTeacher; + + MyTeacher({this.teacherType, this.defalutTeacher}); + + MyTeacher.fromJson(Map json) { + teacherType = json['teacher_type']; + defalutTeacher = json['defalut_teacher'] != null ? new DefalutTeacher.fromJson(json['defalut_teacher']) : null; + } + + Map toJson() { + final Map data = new Map(); + data['teacher_type'] = this.teacherType; + if (this.defalutTeacher != null) { + data['defalut_teacher'] = this.defalutTeacher.toJson(); + } + return data; + } +} + +class DefalutTeacher { + String avatar; + String qrcode; + String wxAccount; + + DefalutTeacher({this.avatar, this.qrcode, this.wxAccount}); + + DefalutTeacher.fromJson(Map json) { + avatar = json['avatar']; + qrcode = json['qrcode']; + wxAccount = json['wx_account']; + } + + Map toJson() { + final Map data = new Map(); + data['avatar'] = this.avatar; + data['qrcode'] = this.qrcode; + data['wx_account'] = this.wxAccount; + return data; + } +} + +class BindTeacherDialog { + List dataKeys; + String btnText; + String btnTextColor; + String btnBgColor; + String qrcodeText; + String qrcodeTextColor; + + BindTeacherDialog({ + this.dataKeys, + this.btnText, + this.btnTextColor, + this.btnBgColor, + this.qrcodeText, + this.qrcodeTextColor, + }); + + BindTeacherDialog.fromJson(Map json) { + dataKeys = json['data_keys'].cast(); + btnText = json['btn_text']; + btnTextColor = json['btn_text_color']; + btnBgColor = json['btn_bg_color']; + qrcodeText = json['qrcode_text']; + qrcodeTextColor = json['qrcode_text_color']; + } + + Map toJson() { + final Map data = new Map(); + data['data_keys'] = this.dataKeys; + data['btn_text'] = this.btnText; + data['btn_text_color'] = this.btnTextColor; + data['btn_bg_color'] = this.btnBgColor; + data['qrcode_text'] = this.qrcodeText; + data['qrcode_text_color'] = this.qrcodeTextColor; + return data; + } +} + +class OfficalWxchat { + String qrcodeText; + String qrcodeTextColor; + String bgColor; + String title; + String titleColor; + String btnText; + List list; + + OfficalWxchat({ + this.qrcodeText, + this.qrcodeTextColor, + this.bgColor, + this.title, + this.titleColor, + this.btnText, + this.list, + }); + + OfficalWxchat.fromJson(Map json) { + qrcodeText = json['qrcode_text']; + qrcodeTextColor = json['qrcode_text_color']; + bgColor = json['bg_color']; + title = json['title']; + titleColor = json['title_color']; + btnText = json['btn_text']; + if (json['list'] != null) { + list = new List(); + json['list'].forEach((v) { + list.add(new OfficalWxchatList.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['qrcode_text'] = this.qrcodeText; + data['qrcode_text_color'] = this.qrcodeTextColor; + data['bg_color'] = this.bgColor; + data['title'] = this.title; + data['title_color'] = this.titleColor; + data['btn_text'] = this.btnText; + if (this.list != null) { + data['list'] = this.list.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class OfficalWxchatList { + String type; + String text; + String subText; + String wechatAccount; + String qrcode; + + OfficalWxchatList({this.type, this.text, this.subText, this.wechatAccount, this.qrcode}); + + OfficalWxchatList.fromJson(Map json) { + type = json['type']; + text = json['text']; + subText = json['sub_text']; + wechatAccount = json['wechat_account']; + qrcode = json['qrcode']; + } + + Map toJson() { + final Map data = new Map(); + data['type'] = this.type; + data['text'] = this.text; + data['sub_text'] = this.subText; + data['wechat_account'] = this.wechatAccount; + data['qrcode'] = this.qrcode; + return data; + } +} diff --git a/lib/pages/wechat_teacher_page/wechat_teacher_page.dart b/lib/pages/wechat_teacher_page/wechat_teacher_page.dart index 5f7adbe..155deaa 100644 --- a/lib/pages/wechat_teacher_page/wechat_teacher_page.dart +++ b/lib/pages/wechat_teacher_page/wechat_teacher_page.dart @@ -1,24 +1,132 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/bloc/wechat_teacher_bloc.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/bloc/wechat_teacher_repository.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_data_model.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart'; import 'package:zhiying_base_widget/pages/wechat_teacher_page/widgets/wechat_teacher_item.dart'; +import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'bloc/wechat_teacher_state.dart'; +import 'bloc/wechat_teacher_event.dart'; +import 'package:fluttertoast/fluttertoast.dart'; -// 微信导师 -class WechatTeacherPage extends StatefulWidget { +/// +/// 微信导师 +/// +class WechatTeacherPage extends StatelessWidget { + final Map data; + + WechatTeacherPage(this.data); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (_) => WechatTeacherBloc(WechatTeacherRepository(data))..add(WechatTeacherInitEvent()), + child: _WechatTeacherPageContainer(), + ); + } +} + +class _WechatTeacherPageContainer extends StatefulWidget { @override - _WechatTeacherPageState createState() => _WechatTeacherPageState(); + _WechatTeacherPageContainerState createState() => _WechatTeacherPageContainerState(); } -class _WechatTeacherPageState extends State { +class _WechatTeacherPageContainerState extends State<_WechatTeacherPageContainer> { + TextEditingController _editingController; + + /// 是否绑定中 + bool _isBinding = false; + + /// 绑定邀请人 + void _bindTeacher() { + if (!_isBinding) { + String wxAccount = _editingController?.text?.toString(); + if (EmptyUtil.isEmpty(wxAccount)) { + Fluttertoast.showToast(msg: '请输入邀请码或者手机号码'); + return; + } + setState(() { + _isBinding = true; + }); + BlocProvider.of(context).add(WechatTeacherBindEvent(teacherWxChat: wxAccount)); + } + } + + /// 拷贝 + void _copyText(String text) { + if (!EmptyUtil.isEmpty(text)) { + Clipboard.setData(ClipboardData(text: text)); + Fluttertoast.showToast(msg: '复制成功~'); + } else { + Fluttertoast.showToast(msg: '内容不能为空~'); + } + } + + /// 长按保存图片 + void _longClickSaveImage() { + Logger.log('长按保存图片'); + } + + @override + void initState() { + _editingController = TextEditingController(); + super.initState(); + } + + @override + void dispose() { + _editingController?.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) {}, + buildWhen: (prov, current) { + if (current is WechatTeacherInitErrorState) { + return false; + } + if (current is WechatTeacherBindErrorState) { + _isBinding = false; + return false; + } + if (current is WechatTeacherBindSuccessState) { + _isBinding = false; + Fluttertoast.showToast(msg: '绑定成功'); + return false; + } + return true; + }, + builder: (context, state) { + if (state is WechatTeacherLoadedState) { + return _createMainWidget(state?.styleModel, state?.dataModel); + } + return _createMainWidget(null, null); + }, + ); + } + + Widget _createMainWidget(WechatTeacherStyleModel styleModel, WechatTeacherDataModel dataModel) { return Scaffold( - appBar: _createNav(), + appBar: _createNav(styleModel), + backgroundColor: HexColor.fromHex(styleModel?.bgColor ?? '#FFF5F5F5'), body: SafeArea( child: SingleChildScrollView( child: Column( children: [ - _createHeader(), - _createWechat(), + _createHeader(styleModel,dataModel), + Padding( + padding: const EdgeInsets.only(top: 15), + child: CachedNetworkImage( + imageUrl: styleModel?.chatDialogImg ?? '', + width: double.infinity, + )), + _createWechat(styleModel), ], ), ), @@ -27,7 +135,7 @@ class _WechatTeacherPageState extends State { } // 导航栏 - Widget _createNav() { + Widget _createNav(WechatTeacherStyleModel styleModel) { return CupertinoNavigationBar( border: Border( bottom: BorderSide( @@ -35,7 +143,7 @@ class _WechatTeacherPageState extends State { style: BorderStyle.none, ), ), - backgroundColor: Colors.white, + backgroundColor: HexColor.fromHex(styleModel?.appBarBgColor ?? '#FFFFFF'), leading: Navigator.canPop(context) ? GestureDetector( child: Container( @@ -53,26 +161,145 @@ class _WechatTeacherPageState extends State { ) : Container(), middle: Text( - '微信导师', + styleModel?.appBarName ?? '微信导师', style: TextStyle( fontSize: 15, - color: Color(0xff333333), + color: HexColor.fromHex(styleModel?.appBarNameColor ?? '#333333'), ), ), ); } - Widget _createHeader() { + /// 没绑定的UI + Widget _createNoBindWidget(WechatTeacherStyleModel styleModel) { + return Column( + children: [ + Container( + margin: EdgeInsets.only(top: 8, bottom: 2), + child: CupertinoTextField( + onSubmitted: (val) => _bindTeacher(), + controller: _editingController, + placeholder: styleModel?.nobindTeacherDialog?.inputHintText ?? '请填写邀请人邀请码/手机号码', + placeholderStyle: TextStyle(fontSize: 14), + decoration: BoxDecoration(), + ), + ), + Container( + height: 0.5, + color: Color(0xffd5d5d5), + ), + GestureDetector( + onTap: () => _bindTeacher(), + child: Center( + child: Container( + margin: EdgeInsets.only(top: 10), + width: 130, + height: 30, + decoration: BoxDecoration( + color: HexColor.fromHex(styleModel?.commStyle?.btnBgColor ?? '#FF5A5A'), + borderRadius: BorderRadius.circular(15), + ), + child: Center( + child: Text( + _isBinding ? '绑定中...' : styleModel?.nobindTeacherDialog?.btnText ?? '绑定邀请人', + style: TextStyle(color: HexColor.fromHex(styleModel?.commStyle?.btnTextColor ?? '#FFFFFFF'), fontSize: 14), + ), + ), + ), + ), + ) + ], + ); + } + + /// 绑定的UI + Widget _createBindWidget(WechatTeacherStyleModel styleModel, WechatTeacherDataModel dataModel) { + return Container( + width: double.infinity, + height: double.infinity, + margin: const EdgeInsets.only(top: 10), + child: Row( + children: [ + Container( + width: 50, + height: 50, + // color: Colors.red, + child: CircleAvatar(child: CachedNetworkImage(imageUrl: dataModel?.teacherAvatar ??'',)), + ), + const SizedBox(width: 13), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text(dataModel?.teacherUsername ??'', style: TextStyle(fontSize: 15, color: HexColor.fromHex(styleModel?.teacherDialogTitleColor ?? '#3C3C3C'))), + Text('微信号: ${dataModel?.teacherWechatAccount??''}', style: TextStyle(fontSize: 15, color: HexColor.fromHex(styleModel?.commStyle.wechatAccountColor ?? '#FF5050'))), + GestureDetector( + onTap: () => _copyText(dataModel?.teacherWechatAccount), + child: UnconstrainedBox( + child: Container( + decoration: BoxDecoration( + // color: Color(0xffffdada), + color: HexColor.fromHex(styleModel?.bindTeacherDialog?.btnBgColor ?? '#FFDADA'), + borderRadius: BorderRadius.circular(20), + ), + padding: EdgeInsets.only(left: 9, right: 9, top: 4, bottom: 4), + child: Text( + styleModel?.bindTeacherDialog?.btnText ?? '复制去微信添加', + style: TextStyle(fontSize: 13, color: HexColor.fromHex(styleModel?.bindTeacherDialog?.btnTextColor ?? '#FF0000')), + ), + ), + ), + ), + ], + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: GestureDetector( + onLongPress: () => _longClickSaveImage(), + child: Column( + children: [ + Container( + width: 56, + height: 56, + // color: Colors.red, + child: CachedNetworkImage( + imageUrl: dataModel?.teacherWxQrCode ?? styleModel?.myTeacher?.defalutTeacher?.qrcode ?? '', + ), + ), + const SizedBox(height: 9), + Text( + styleModel?.officalWxchat?.qrcodeText ?? '长按保存二维码', + style: TextStyle(fontSize: 13, color: HexColor.fromHex(styleModel?.officalWxchat?.qrcodeTextColor ?? '#999999')), + ), + ], + ), + ), + ), + ) + ], + ), + ); + } + + Widget _createHeader(WechatTeacherStyleModel styleModel, WechatTeacherDataModel dataModel) { return Container( width: double.infinity, height: 283, child: Stack( children: [ + // 背景图 Container( width: double.infinity, height: 185, - color: Colors.redAccent, + // color: Colors.redAccent, + child: CachedNetworkImage( + imageUrl: styleModel?.bgImg ?? '', + fit: BoxFit.contain, + ), ), + + // 中间弹窗 Align( alignment: Alignment.bottomCenter, child: Container( @@ -81,7 +308,7 @@ class _WechatTeacherPageState extends State { margin: EdgeInsets.only(left: 10, right: 10), padding: EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: HexColor.fromHex(styleModel?.teacherDialogBgColor ?? '#FFFFFF'), borderRadius: BorderRadius.circular(10), ), child: Column( @@ -89,39 +316,18 @@ class _WechatTeacherPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '我的导师', + styleModel?.teacherDialogTitle ?? '我的导师', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, - color: Color(0xff333333), - ), - ), - Container( - margin: EdgeInsets.only(top: 8, bottom: 2), - child: CupertinoTextField( - placeholder: '请填写邀请人邀请码/手机号码', - placeholderStyle: TextStyle(fontSize: 14), - decoration: BoxDecoration(), + color: HexColor.fromHex(styleModel?.teacherDialogTitleColor ?? '#3C3C3C'), ), ), - Container( - height: 0.5, - color: Color(0xffd5d5d5), - ), - Center( - child: Container( - margin: EdgeInsets.only(top: 10), - width: 130, - height: 30, - decoration: BoxDecoration( - color: Colors.redAccent, - borderRadius: BorderRadius.circular(15)), - child: Center( - child: Text( - '绑定邀请人', - style: TextStyle(color: Colors.white, fontSize: 14), - ), - ), + Expanded( + child: Visibility( + visible: dataModel?.isBindTeacher == '1', + replacement: _createNoBindWidget(styleModel), + child: _createBindWidget(styleModel, dataModel), ), ) ], @@ -133,13 +339,13 @@ class _WechatTeacherPageState extends State { ); } - Widget _createWechat() { + Widget _createWechat(WechatTeacherStyleModel styleModel) { return Container( width: double.infinity, - margin: EdgeInsets.only(left: 10, right: 10, top: 15), + margin: EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 22), padding: EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: HexColor.fromHex(styleModel?.officalWxchat?.bgColor ?? '#FFFFFF'), borderRadius: BorderRadius.circular(10), ), child: Column( @@ -147,22 +353,34 @@ class _WechatTeacherPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '官方微信', + styleModel?.officalWxchat?.title ?? '官方微信', style: TextStyle( + color: HexColor.fromHex(styleModel?.officalWxchat?.titleColor ?? '#3C3C3C'), fontSize: 15, fontWeight: FontWeight.bold, ), ), - WechatTeachetItem(), - Container( - margin: EdgeInsets.only(top: 4, bottom: 4), - width: double.infinity, - height: 0.5, - color: Color(0xffebebeb), - ), - WechatTeachetItem(), + _createOfficalWxchatListWidget(styleModel), ], ), ); } + + Widget _createOfficalWxchatListWidget(WechatTeacherStyleModel styleModel) { + List widgets = []; + int length = styleModel?.officalWxchat?.list?.length ?? 0; + if (length > 0) { + styleModel.officalWxchat.list.forEach((element) { + widgets.add(WechatTeachetItem(element, styleModel)); + widgets.add(Container(margin: EdgeInsets.only(top: 4, bottom: 4), width: double.infinity, height: 0.5, color: Color(0xffebebeb))); + }); + widgets.removeLast(); + } else { + widgets.add(Container()); + } + + return Column( + children: widgets, + ); + } } diff --git a/lib/pages/wechat_teacher_page/widgets/wechat_teacher_item.dart b/lib/pages/wechat_teacher_page/widgets/wechat_teacher_item.dart index cd6e91a..8c813f4 100644 --- a/lib/pages/wechat_teacher_page/widgets/wechat_teacher_item.dart +++ b/lib/pages/wechat_teacher_page/widgets/wechat_teacher_item.dart @@ -1,6 +1,31 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:zhiying_base_widget/pages/wechat_teacher_page/model/wechat_teacher_style_model.dart'; +import 'package:zhiying_comm/zhiying_comm.dart'; +import 'package:fluttertoast/fluttertoast.dart'; class WechatTeachetItem extends StatelessWidget { + OfficalWxchatList itemStyleModel; + WechatTeacherStyleModel styleModel; + + WechatTeachetItem(this.itemStyleModel, this.styleModel); + + /// 拷贝 + void _copyText(String text) { + if(!EmptyUtil.isEmpty(text)) { + Clipboard.setData(ClipboardData(text: text)); + Fluttertoast.showToast(msg: '复制成功~'); + }else{ + Fluttertoast.showToast(msg: '内容不能为空~'); + } + } + + /// 长按保存图片 + void _longClickSaveImage(){ + Logger.log('长按保存图片'); + + } + @override Widget build(BuildContext context) { return Container( @@ -11,54 +36,77 @@ class WechatTeachetItem extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - '微信公众号 智莺生活公众号', - style: TextStyle( - fontSize: 14, - color: Color(0xff3c3c3c), - fontWeight: FontWeight.bold, - ), + // Text( + // itemStyleModel?.text ?? '微信公众号 智莺生活公众号', + // style: TextStyle( + // fontSize: 14, + // color: Color(0xff3c3c3c), + // fontWeight: FontWeight.bold, + // ), + // ), + + RichText( + text: TextSpan(children: [ + TextSpan( + text: itemStyleModel?.text ?? '', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: HexColor.fromHex(styleModel?.officalWxchat?.titleColor ?? '#FF3C3C3C'))), + TextSpan( + text: ' ${itemStyleModel?.subText ?? ''}', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 11, color: HexColor.fromHex(styleModel?.officalWxchat?.titleColor ?? '#FF3C3C3C'))), + ]), ), + Padding( padding: const EdgeInsets.only(top: 8.0, bottom: 8), child: Text( - '微信号:5645434', + '微信号:${itemStyleModel?.wechatAccount ?? ''}', style: TextStyle( - fontSize: 13, - color: Color(0xffff5050), - fontWeight: FontWeight.bold), + fontSize: 13, + // color: Color(0xffff5050), + color: HexColor.fromHex(styleModel?.commStyle?.wechatAccountColor ?? '#FF5050'), + fontWeight: FontWeight.bold, + ), ), ), - UnconstrainedBox( - child: Container( - decoration: BoxDecoration( - color: Color(0xffffdada), - borderRadius: BorderRadius.circular(20), - ), - padding: - EdgeInsets.only(left: 9, right: 9, top: 4, bottom: 4), - child: Text( - '长按保存二维码', - style: TextStyle(fontSize: 13, color: Color(0xffff0000)), + GestureDetector( + onTap: ()=> _copyText(itemStyleModel?.wechatAccount), + child: UnconstrainedBox( + child: Container( + decoration: BoxDecoration( + // color: Color(0xffffdada), + color: HexColor.fromHex(styleModel?.bindTeacherDialog?.btnBgColor ?? '#FFDADA'), + borderRadius: BorderRadius.circular(20), + ), + padding: EdgeInsets.only(left: 9, right: 9, top: 4, bottom: 4), + child: Text( + styleModel?.bindTeacherDialog?.btnText ?? '复制去微信添加', + style: TextStyle(fontSize: 13, color: HexColor.fromHex(styleModel?.bindTeacherDialog?.btnTextColor ?? '#FF0000')), + ), ), ), ), ], ), ), - Column( - children: [ - Container( - margin: EdgeInsets.only(bottom: 4), - width: 55, - height: 55, - color: Colors.redAccent, - ), - Text( - '长按保存二维码', - style: TextStyle(fontSize: 12, color: Color(0xff999999)), - ), - ], + GestureDetector( + onLongPress: ()=> _longClickSaveImage(), + child: Column( + children: [ + Container( + margin: EdgeInsets.only(bottom: 4), + width: 55, + height: 55, + // color: Colors.redAccent, + child: CachedNetworkImage( + imageUrl: itemStyleModel?.qrcode ?? '', + ), + ), + Text( + styleModel?.officalWxchat?.qrcodeText ?? '长按保存二维码', + style: TextStyle(fontSize: 13, color: HexColor.fromHex(styleModel?.officalWxchat?.qrcodeTextColor ?? '#999999')), + ), + ], + ), ) ], ), diff --git a/lib/register.dart b/lib/register.dart index f036261..566a54c 100644 --- a/lib/register.dart +++ b/lib/register.dart @@ -79,6 +79,8 @@ import 'widgets/search/input/search_input_widget.dart'; import 'widgets/search/tabbar/search_tab_creater.dart'; import 'widgets/search_result/goods_list/search_result_goods_list_creater.dart'; import 'widgets/search_result/search_input/search_result_input.dart'; +import 'package:secverify/secverify.dart'; +import 'package:zhiying_comm/util/second_test/second_test_util.dart'; class BaseWidgetRegister { /// 初始化方法 @@ -126,6 +128,9 @@ class BaseWidgetRegister { SharesdkPlugin.regist(register); }); + // MOB 秒验 + SecondTestUtil.getInstance().init(); + Application.addMethod(() async { return Future.delayed(Duration(seconds: 1)); }); @@ -152,7 +157,7 @@ class BaseWidgetRegister { PageFactory.regist('pub.flutter.feedback', (model) => FeedbackPage(model)); PageFactory.regist('pub.flutter.feedback_list', (model) => FeedbackRecordPage(model)); PageFactory.regist( - 'pub.flutter.wechat_teacher', (model) => WechatTeacherPage()); + 'pub.flutter.wechat_teacher', (model) => WechatTeacherPage(model)); PageFactory.regist('pub.flutter.cash_out', (model) => WithdrawPage(model)); // webview diff --git a/lib/widgets/mine/mine_data/mine_data_widget.dart b/lib/widgets/mine/mine_data/mine_data_widget.dart index 7b7022d..62a43db 100644 --- a/lib/widgets/mine/mine_data/mine_data_widget.dart +++ b/lib/widgets/mine/mine_data/mine_data_widget.dart @@ -82,7 +82,7 @@ class MineDataWidget extends StatelessWidget { ), ), Text( - '${profile.total}', + '${profile?.total?? '0.00'}', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w800, @@ -136,6 +136,8 @@ class MineDataWidget extends StatelessWidget { Widget _createCenter() { List datas = profile.gridViews; + int length = datas?.length ?? 0; + if (length > 0) { int maxColumn = 2; int row = (datas.length / 2).ceil(); if (row % 3 == 0) { @@ -192,13 +194,15 @@ class MineDataWidget extends StatelessWidget { )); } } - return Container( width: double.infinity, child: Column( children: columns, ), ); + }else{ + return Container(); + } } Widget _createrCenterItem(String name, String value) { diff --git a/lib/widgets/team/fans_list/team_fans_item.dart b/lib/widgets/team/fans_list/team_fans_item.dart index 5dc0789..bcd885f 100644 --- a/lib/widgets/team/fans_list/team_fans_item.dart +++ b/lib/widgets/team/fans_list/team_fans_item.dart @@ -73,8 +73,14 @@ class _TeamFansItemState extends State { onTap: () => _openFansItemDetailsPage(), child: Container( width: 50, - child: CachedNetworkImage( - imageUrl: widget?.dataModel?.avatar ?? '', + height: 50, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(50/2) + // ), + child: CircleAvatar( + backgroundImage: CachedNetworkImageProvider( + widget?.dataModel?.avatar ?? '', + ), ), )), const SizedBox(width: 10), diff --git a/lib/widgets/team/recommend/team_recommend_widget.dart b/lib/widgets/team/recommend/team_recommend_widget.dart index 65d6a4a..239fa69 100644 --- a/lib/widgets/team/recommend/team_recommend_widget.dart +++ b/lib/widgets/team/recommend/team_recommend_widget.dart @@ -255,10 +255,12 @@ class __TeamRecommendWidgetState extends State<_TeamRecommendWidgetContainer> { borderRadius: BorderRadius.circular(55/2), child: Container( width: 55, - // height: 55, + height: 55, // color: Colors.red, - child: CachedNetworkImage( - imageUrl: dataModel?.referrerAvatar ?? '', + child: CircleAvatar( + backgroundImage: CachedNetworkImageProvider( + dataModel?.referrerAvatar ?? '', + ), ), ), ); diff --git a/lib/widgets/team_details/referrer/team_details_referrer_widget.dart b/lib/widgets/team_details/referrer/team_details_referrer_widget.dart index 0bc9a40..cc8cda1 100644 --- a/lib/widgets/team_details/referrer/team_details_referrer_widget.dart +++ b/lib/widgets/team_details/referrer/team_details_referrer_widget.dart @@ -78,8 +78,11 @@ class TeamDetailsReferrerWidget extends StatelessWidget { Container( width: 50, height: 50, - child: CachedNetworkImage( - imageUrl: dataModel?.avatar ?? '', + child: CircleAvatar( + backgroundImage: CachedNetworkImageProvider(dataModel?.avatar ?? ''), + // child: CachedNetworkImage( + // imageUrl: dataModel?.avatar ?? '', + // ), ), ), const SizedBox(width: 10), diff --git a/pubspec.yaml b/pubspec.yaml index 5b7f2b8..6b80b99 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -24,8 +24,6 @@ dependencies: git: url: 'http://192.168.0.138:3000/FnuoOS_Flutter_Components/Image_Cropper.git' ref: '1.2.3+1' - # mob 分享sdk - sharesdk_plugin: ^1.2.8 # 系统分享 share_extend: ^1.1.9 flutter_native_image: ^0.0.5 @@ -69,6 +67,7 @@ flutter: assets: - assets/images/launch_image/launch_image.png - assets/images/empty/empty.png + - assets/images/qrcode/default_qrcode.png # # For details regarding assets in packages, see # https://flutter.dev/assets-and-images/#from-packages