import 'dart:io'; import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:zhiying_base_widget/pages/feedback_page/bloc/feedback_bloc.dart'; import 'package:zhiying_base_widget/pages/feedback_page/bloc/feedback_repository.dart'; import 'package:zhiying_base_widget/pages/feedback_page/feedback_record_page.dart'; import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_model.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; import 'package:zhiying_base_widget/pages/feedback_page/widgets/feedback_image.dart'; import 'package:zhiying_base_widget/pages/feedback_page/widgets/feedback_tab_widget.dart'; import 'package:zhiying_base_widget/widgets/others/action_selected_alert/action_selected_alert.dart'; import 'package:zhiying_comm/util/log/let_log.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'bloc/feedback_bloc.dart'; import 'bloc/feedback_repository.dart'; import 'bloc/feedback_state.dart'; import 'bloc/feedback_event.dart'; import 'package:fluttertoast/fluttertoast.dart'; /// /// 意见反馈 /// class FeedbackPage extends StatefulWidget { final Map data; FeedbackPage(this.data); @override _FeedbackPageState createState() => _FeedbackPageState(); } class _FeedbackPageState extends State { @override Widget build(BuildContext context) { return BlocProvider( create: (_) => FeedbackBloc(FeedBackRepository())..add(FeedbackInitEvent()), child: _FeedbackPageContainer(), ); } } class _FeedbackPageContainer extends StatefulWidget { @override __FeedbackPageContainerState createState() => __FeedbackPageContainerState(); } class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { List _images = List(); bool _submitable = false; TextEditingController _feedback; TextEditingController _title; // 是否上传中 bool isUpLoading = false; @override void initState() { _feedback = TextEditingController(); _title = TextEditingController(); super.initState(); } @override void dispose() { _feedback?.dispose(); _title?.dispose(); super.dispose(); } /// 选择图片 void _onAddImage() async { if (_images.length >= 4) { Fluttertoast.showToast(msg: '最多上传4张图片'); return; } 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; int index = await showModalBottomSheet( context: context, builder: (context) { return ActionSelectedAlert( // title: '拍照/选择图片', actions: ['拍照', '从相册选择图片'], ); }, isScrollControlled: false, backgroundColor: Colors.transparent); if (index != null) { if (index == 0) { file = await picker.getImage(source: ImageSource.camera); } else { file = await picker.getImage(source: ImageSource.gallery); } if (file == null) return; if (_images.length <= 4) { setState(() { _images.add(File(file.path)); }); } else { Fluttertoast.showToast(msg: '最多只能选择4张'); } // File resultFile = await EncodeUtil.compressImage(file, 800); } } @override Widget build(BuildContext context) { return BlocConsumer( listener: (context, state) {}, buildWhen: (prev, current) { /// 保存成功 if (current is FeedbackSaveSuccessState) { Fluttertoast.showToast(msg: '反馈成功~'); Navigator.pop(context); return false; } if (current is FeedbackSaveErrorState) { Fluttertoast.showToast(msg: '反馈失败~'); setState(() { isUpLoading = false; }); return false; } return true; }, builder: (context, state) { if (state is FeedbackLoadedState) { return _getMainWidget(state?.model); } return _getEmptyWidget(); }, ); } /// 有数据 Widget _getMainWidget(FeedbackModel model) { return Scaffold( resizeToAvoidBottomInset: false, appBar: _createNav(model), body: GestureDetector( onTap: () { FocusScope.of(context).requestFocus(FocusNode()); }, child: SafeArea( child: Column( children: [ Expanded( child: SingleChildScrollView( child: Column( children: [ Container( width: double.infinity, margin: EdgeInsets.only(top: 10, bottom: 10, left: 12.5, right: 12.5), padding: EdgeInsets.all(12.5), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(7.5)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ _createTitle(model), _createUpload(model), _createSubmit(model), ], ), ) ], ), ), ), Center( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => RouterUtil.route(model, model.toJson(), context), child: Container( width: 120, height: 30, margin: EdgeInsets.all(10), decoration: BoxDecoration( color: HexColor.fromHex(model?.feedbackListBtnBgColor ?? '#FFFFFF'), borderRadius: BorderRadius.circular(15), border: Border.all(color: HexColor.fromHex(model?.feedbackListBtnBorderColor ?? '#D1D1D1'), width: 0.5), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: EdgeInsets.only(right: 6), child: CachedNetworkImage( imageUrl: model?.feedbackListBtnIcon ?? '', width: 16.5, ), ), Text( model?.feedbackListBtnText ?? '反馈记录', style: TextStyle(fontSize: 13, color: HexColor.fromHex(model?.feedbackListBtnTextColor ?? '#333333'), fontWeight: FontWeight.bold), ) ], ), ), ), ), const SizedBox(height: 25), ], ), ), ), ); } /// 没数据 Widget _getEmptyWidget() { return Scaffold( resizeToAvoidBottomInset: false, appBar: _createNav(null), body: Container(), ); } /// 导航栏 Widget _createNav(FeedbackModel mode) { return CupertinoNavigationBar( border: Border( bottom: BorderSide( width: 0.0, // One physical pixel. style: BorderStyle.none, ), ), backgroundColor: HexColor.fromHex(mode?.appBarBgColor ?? '#FFFFFF'), leading: Navigator.canPop(context) ? GestureDetector( child: Container( padding: EdgeInsets.zero, child: Icon( Icons.arrow_back_ios, size: 20, ), ), onTap: () { if (Navigator.canPop(context)) { Navigator.pop(context); } }, ) : Container(), middle: Text( mode?.appBarName ?? '意见反馈', style: TextStyle( fontSize: 15, color: HexColor.fromHex(mode?.appBarNameColor ?? '#333333'), ), ), ); } Widget _createTitle(FeedbackModel model) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Text( model?.feedbackTitle ?? '反馈描述', style: TextStyle( fontSize: 14, color: Color(0xff333333), fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), /// 异常选项 Padding( padding: EdgeInsets.only(top: 4, bottom: 4), child: Visibility( visible: !EmptyUtil.isEmpty(model?.feedbackTypes), child: Row( children: model.feedbackTypes .map((e) => Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { model.feedbackTypes.forEach((element) { element.isSelect = false; }); e.isSelect = true; }); }, child: Container( margin: EdgeInsets.only(left: 2, right: 2), height: 28, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(2.5), border: Border.all( color: HexColor.fromHex(e.isSelect ? model?.feedbackTypeSelectedBorderColor : model?.feedbackTypeNoSelectedBorderColor), //e.isSelect ? Colors.redAccent : Color(0xffe7e7e7), width: 1, ), ), child: Stack( children: [ Center( child: Text( e.name ?? '', style: TextStyle( fontSize: 12, color: HexColor.fromHex( e.isSelect ? model?.feedbackTypeSelectedTextColor : model?.feedbackTypeNoSelectedTextColor) //e.isSelect ? Colors.redAccent : Color(0xff999999), ), ), ), Visibility( visible: e.isSelect, child: Align( alignment: Alignment.bottomRight, child: CachedNetworkImage( imageUrl: model?.feedbackTypeSelectedBorderIcon, width: 10, ), ), ) ], ), )), ))) .toList(), ), ), ), // 标题 Container( height: 32.5, margin: EdgeInsets.only(left: 2, right: 2, top: 4, bottom: 4), child: CupertinoTextField( controller: _title, textAlignVertical: TextAlignVertical.center, style: TextStyle(fontSize: 12, color: Color(0xff333333)), maxLines: 1, placeholder: model?.feedbackInputHintText ?? '请输入反馈标题(最多15个字)', placeholderStyle: TextStyle( fontSize: 12, color: HexColor.fromHex(model?.feedbackInputHintTextColor ?? '#999999'), ), decoration: BoxDecoration(color: Color(0xfff9f9f9), borderRadius: BorderRadius.circular(7.5)), onChanged: (value) { if (value == null || value == '' || EmptyUtil.isEmpty(_feedback?.text?.toString()?.trim())) { _submitable = false; } else { _submitable = true; } setState(() {}); }, ), ), // 内容 Container( height: 118, margin: EdgeInsets.only(left: 2, right: 2, top: 4, bottom: 4), child: CupertinoTextField( controller: _feedback, textAlignVertical: TextAlignVertical.top, style: TextStyle(fontSize: 12, color: Color(0xff333333)), maxLines: null, placeholder: model?.feedbackInputContentHintText ?? '请输入您的意见(最多100个字)', placeholderStyle: TextStyle( fontSize: 12, color: HexColor.fromHex(model?.feedbackInputContentHintTextColor ?? '#999999'), ), decoration: BoxDecoration(color: Color(0xfff9f9f9), borderRadius: BorderRadius.circular(7.5)), onChanged: (value) { if (value == null || value == '' || EmptyUtil.isEmpty(_title?.text?.toString()?.trim())) { _submitable = false; } else { _submitable = true; } setState(() {}); }, ), ), ], ); } Widget _createUpload(FeedbackModel model) { List images = List(); _images.forEach((file) { images.add(Container( margin: EdgeInsets.only(top: 4, bottom: 4, right: 8), width: 80, height: 80, child: FeedbackImageWidget( file: file, onDelete: () { setState(() { _images.remove(file); }); }, ), )); }); if (images.length < 4) { images.add(GestureDetector( child: Container( margin: EdgeInsets.only(top: 4, bottom: 4), decoration: BoxDecoration(borderRadius: BorderRadius.circular(7.5), color: Color(0xfff9f9f9)), height: 80, width: 80, child: Icon( Icons.add, size: 60, color: Color(0xffd8d8d8), ), ), onTap: _onAddImage, )); } return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Padding( padding: EdgeInsets.only(right: 10, top: 4, bottom: 4), child: Text( model?.feedbackUploadImageTitle ?? '上传图片', style: TextStyle( fontSize: 14, color: Color(0xff333333), fontWeight: FontWeight.bold, ), ), ), Text( model?.feedbackUploadImageSubtitle ?? '最多上传4张,大小不超过1M/张', style: TextStyle( fontSize: 12, color: Color(0xff999999), ), ), ], ), // Row( // children: images, // ) Wrap( crossAxisAlignment: WrapCrossAlignment.center, textDirection: TextDirection.ltr, spacing: 0, runSpacing: 0, runAlignment: WrapAlignment.center, alignment: WrapAlignment.start, children: images, ), ], ); } Widget _createSubmit(FeedbackModel model) { return GestureDetector( onTap: () { if (!_submitable) { return; } if(isUpLoading){ // Fluttertoast.showToast(msg: '提交中...'); return; } setState(() { isUpLoading = true; }); Logger.debug('提交:${_feedback.text.toString()}'); String selectId; model.feedbackTypes.forEach((element) { if (element.isSelect) { selectId = element.typeId; } }); BlocProvider.of(context) .add(FeedbackSubmitEvent(model: {'title': _title?.text?.toString(), 'content': _feedback?.text?.toString(), 'type': selectId, 'files': _images})); // Fluttertoast.showToast(msg: '提交成功~'); // Navigator.pop(context); }, child: Container( margin: EdgeInsets.only(top: 24, bottom: 4), height: 45, decoration: BoxDecoration( color: HexColor.fromHex(_submitable ? model?.feedbackTypeSelectedBorderColor ?? '' : model?.feedbackPostBtnBgColor ?? ''), borderRadius: BorderRadius.circular(7.5), ), child: Center( child: Text( isUpLoading ? '提交意见...' : model?.feedbackPostBtnText ?? '提交意见', style: TextStyle( fontSize: 14, color: HexColor.fromHex(model?.feedbackPostBtnTextColor ?? '#FFFFFF'), ), ), ), ), ); } }