@@ -22,10 +22,29 @@ class FeedbackBloc extends Bloc<FeedbackEvent, FeedbackState> { | |||||
if (event is FeedbackInitEvent) { | if (event is FeedbackInitEvent) { | ||||
yield* _mapInitToState(event); | yield* _mapInitToState(event); | ||||
} | } | ||||
/// 提交反馈 | |||||
if (event is FeedbackSubmitEvent) { | |||||
yield* _mapSaveToState(event); | |||||
} | |||||
} | |||||
/// 提交反馈 | |||||
Stream<FeedbackState> _mapSaveToState(FeedbackSubmitEvent event) async* { | |||||
var result = await repository.saveFeedback(event?.model); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
yield FeedbackSaveSuccessState(); | |||||
} else { | |||||
yield FeedbackSaveErrorState(); | |||||
} | |||||
} | } | ||||
/// 初始化 | /// 初始化 | ||||
Stream<FeedbackState> _mapInitToState(FeedbackInitEvent event) async* { | Stream<FeedbackState> _mapInitToState(FeedbackInitEvent event) async* { | ||||
var cache = await repository.fetchCachedData(event.model); | |||||
if (!EmptyUtil.isEmpty(cache)) { | |||||
yield FeedbackLoadedState(model: cache); | |||||
} | |||||
var result = await repository.fetchData(event.model); | var result = await repository.fetchData(event.model); | ||||
if (!EmptyUtil.isEmpty(result)) { | if (!EmptyUtil.isEmpty(result)) { | ||||
yield FeedbackLoadedState(model: result); | yield FeedbackLoadedState(model: result); | ||||
@@ -10,4 +10,8 @@ class FeedbackInitEvent extends FeedbackEvent{ | |||||
} | } | ||||
/// 提交反馈 | /// 提交反馈 | ||||
class FeedbackSubmitEvent extends FeedbackEvent{} | |||||
class FeedbackSubmitEvent extends FeedbackEvent{ | |||||
final Map<String, dynamic> model; | |||||
FeedbackSubmitEvent({this.model}); | |||||
} |
@@ -0,0 +1,73 @@ | |||||
import 'dart:async'; | |||||
import 'package:bloc/bloc.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/bloc/feedback_record_repository.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
import 'feedback_record_event.dart'; | |||||
import 'feedback_record_state.dart'; | |||||
class FeedbackRecordBloc extends Bloc<FeedbackRecordEvent, FeedbackRecordState> { | |||||
// FeedbackRecordBloc() : super(FeedbackRecordInitial()); | |||||
@override | |||||
FeedbackRecordState get initialState => FeedbackRecordInitial(); | |||||
FeedbackRecordRepository repository; | |||||
FeedbackRecordBloc(this.repository); | |||||
@override | |||||
Stream<FeedbackRecordState> mapEventToState( | |||||
FeedbackRecordEvent event, | |||||
) async* { | |||||
/// 初始化 | |||||
if (event is FeedbackRecordInitEvent) { | |||||
yield* _mapInitEventToState(event); | |||||
} | |||||
/// 刷新 | |||||
if (event is FeedbackRecordRefreshEvent) { | |||||
yield* _mapRefreshEventToState(event); | |||||
} | |||||
/// 加载更多 | |||||
if (event is FeedbackRecordLoadEvent) { | |||||
yield* _mapLoadEventToState(event); | |||||
} | |||||
} | |||||
/// 初始化 | |||||
Stream<FeedbackRecordState> _mapInitEventToState(FeedbackRecordInitEvent event) async* { | |||||
var styleCache = await repository.fetchCacheStyle(); | |||||
var styleNet = await repository.fetchInitStyle(); | |||||
var data = await repository.fetchInitData(); | |||||
if (!EmptyUtil.isEmpty(data) && (!EmptyUtil.isEmpty(styleCache) || !EmptyUtil.isEmpty(styleNet))) { | |||||
yield FeedbackRecordLoadedState(dataModel: data, styleModel: !EmptyUtil.isEmpty(styleNet) ? styleNet : styleCache); | |||||
} else { | |||||
yield FeedbackRecordInitErrorState(); | |||||
} | |||||
} | |||||
/// 刷新 | |||||
Stream<FeedbackRecordState> _mapRefreshEventToState(FeedbackRecordRefreshEvent event) async* { | |||||
var style = repository.styleModel; | |||||
var result = await repository.fetchRefreshData(); | |||||
if (!EmptyUtil.isEmpty(result) && !EmptyUtil.isEmpty(style)) { | |||||
yield FeedbackRecordRefreshSuccessState(); | |||||
yield FeedbackRecordLoadedState(dataModel: result, styleModel: style); | |||||
} else { | |||||
yield FeedbackRecordRefreshErrorState(); | |||||
} | |||||
} | |||||
/// 加载更多 | |||||
Stream<FeedbackRecordState> _mapLoadEventToState(FeedbackRecordLoadEvent event) async* { | |||||
var style = repository.styleModel; | |||||
var result = await repository.fetchLoadData(); | |||||
if (!EmptyUtil.isEmpty(result) && !EmptyUtil.isEmpty(style)) { | |||||
yield FeedbackRecordLoadSuccessState(); | |||||
yield FeedbackRecordLoadedState(dataModel: result, styleModel: style); | |||||
} else { | |||||
yield FeedbackRecordLoadErrorState(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
import 'package:meta/meta.dart'; | |||||
@immutable | |||||
abstract class FeedbackRecordEvent {} | |||||
/// 初始化 | |||||
class FeedbackRecordInitEvent extends FeedbackRecordEvent {} | |||||
/// 下拉刷新 | |||||
class FeedbackRecordRefreshEvent extends FeedbackRecordEvent {} | |||||
/// 加载更多 | |||||
class FeedbackRecordLoadEvent extends FeedbackRecordEvent {} |
@@ -0,0 +1,117 @@ | |||||
import 'dart:convert'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_data_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_style_model.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FeedbackRecordRepository { | |||||
// final int max = 5; | |||||
int _currentPage = 1; | |||||
bool _hasMore = true; | |||||
final Map<String, dynamic> data; | |||||
FeedbackRecordRepository(this.data) { | |||||
_dataModel = FeedbackRecordDataModel(); | |||||
_dataModel.data = []; | |||||
} | |||||
/// 样式数据 | |||||
FeedbackRecordStyleModel _styleModel; | |||||
/// 数据 | |||||
FeedbackRecordDataModel _dataModel; | |||||
FeedbackRecordStyleModel get styleModel => _styleModel; | |||||
FeedbackRecordDataModel get dataModel => _dataModel; | |||||
/// 初始化数据 | |||||
Future<dynamic> fetchInitData() async { | |||||
_hasMore = true; | |||||
_currentPage = 1; | |||||
return _fetchBaseRequest(); | |||||
} | |||||
/// 样式初始化 | |||||
Future<dynamic> fetchInitStyle() async { | |||||
try { | |||||
String skipIdentifier = | |||||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.feedback_list'; | |||||
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 _handleStyle(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 获取缓存样式 | |||||
Future<dynamic> fetchCacheStyle() async { | |||||
try { | |||||
String skipIdentifier = | |||||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.feedback_list'; | |||||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skipIdentifier'); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
return _handleStyle(result); | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 处理样式 | |||||
dynamic _handleStyle(Map<String, dynamic> data) { | |||||
try { | |||||
var modListData = data['mod_list'][0]['data']; | |||||
if (!EmptyUtil.isEmpty(modListData)) { | |||||
FeedbackRecordStyleModel model = FeedbackRecordStyleModel.fromJson(modListData is String ? jsonDecode(modListData) : modListData); | |||||
if (!EmptyUtil.isEmpty(model)) { | |||||
_styleModel = model; | |||||
return _styleModel; | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 刷新 | |||||
Future<dynamic> fetchRefreshData() async { | |||||
_hasMore = true; | |||||
_currentPage = 1; | |||||
return _fetchBaseRequest(); | |||||
} | |||||
/// 加载更多 | |||||
Future<dynamic> fetchLoadData() async { | |||||
if (_hasMore) { | |||||
return _fetchBaseRequest(); | |||||
} | |||||
return null; | |||||
} | |||||
/// 基础加载方法 | |||||
Future<dynamic> _fetchBaseRequest() async { | |||||
try { | |||||
var result = await NetUtil.post('/api/v1/feedback/list', method: NetMethod.GET, queryParameters: {'page': _currentPage.toString()}); | |||||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||||
FeedbackRecordDataModel model = FeedbackRecordDataModel.fromJson(result); | |||||
if (!EmptyUtil.isEmpty(model) && !EmptyUtil.isEmpty(model?.data)) { | |||||
_dataModel.data.addAll(model.data); | |||||
_hasMore = true; | |||||
++_currentPage; | |||||
return _dataModel; | |||||
} | |||||
} | |||||
_hasMore = false; | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
import 'package:meta/meta.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_data_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_style_model.dart'; | |||||
@immutable | |||||
abstract class FeedbackRecordState {} | |||||
class FeedbackRecordInitial extends FeedbackRecordState {} | |||||
/// 数据加载成功 | |||||
class FeedbackRecordLoadedState extends FeedbackRecordState { | |||||
FeedbackRecordDataModel dataModel; | |||||
FeedbackRecordStyleModel styleModel; | |||||
FeedbackRecordLoadedState({this.dataModel, this.styleModel}); | |||||
} | |||||
/// 初始化失败 | |||||
class FeedbackRecordInitErrorState extends FeedbackRecordState{} | |||||
/// 刷新成功与失败 | |||||
class FeedbackRecordRefreshSuccessState extends FeedbackRecordState{} | |||||
class FeedbackRecordRefreshErrorState extends FeedbackRecordState{} | |||||
/// 加载更多成功与失败 | |||||
class FeedbackRecordLoadSuccessState extends FeedbackRecordState{} | |||||
class FeedbackRecordLoadErrorState extends FeedbackRecordState{} |
@@ -1,21 +1,42 @@ | |||||
import 'dart:convert'; | import 'dart:convert'; | ||||
import 'dart:io'; | |||||
import 'package:path/path.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_model.dart'; | import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_model.dart'; | ||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
class FeedBackRepository { | class FeedBackRepository { | ||||
/// 获取缓存样式数据 | /// 获取缓存样式数据 | ||||
Future<FeedbackModel> fetchCachedData(final Map<String, dynamic> data) async { | |||||
try { | |||||
String skipIdentifier = | |||||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.feedback'; | |||||
var result = await NetUtil.getRequestCachedData('/api/v1/mod/$skipIdentifier'); | |||||
if (!EmptyUtil.isEmpty(result)) { | |||||
var modListData = result['mod_list'][0]['data']; | |||||
if (!EmptyUtil.isEmpty(modListData)) { | |||||
FeedbackModel model = FeedbackModel.fromJson(jsonDecode(modListData)); | |||||
model.feedbackTypes.last.isSelect = true; | |||||
return model; | |||||
} | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 获取网络样式数据 | /// 获取网络样式数据 | ||||
Future<FeedbackModel> fetchData(final Map<String, dynamic> data) async { | Future<FeedbackModel> fetchData(final Map<String, dynamic> data) async { | ||||
try { | try { | ||||
String skip_identifier = !EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.feedback'; | |||||
String skipIdentifier = | |||||
!EmptyUtil.isEmpty(data) && data.containsKey('skip_identifier') && !EmptyUtil.isEmpty(data['skip_identifier']) ? data['skip_identifier'] : 'pub.flutter.feedback'; | |||||
var result = await NetUtil.post('/api/v1/mod/$skip_identifier', method: NetMethod.GET, cache: true); | |||||
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])) { | if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | ||||
var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | var modListData = result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]['mod_list'][0]['data']; | ||||
if (!EmptyUtil.isEmpty(modListData)) { | if (!EmptyUtil.isEmpty(modListData)) { | ||||
FeedbackModel model = FeedbackModel.fromJson(jsonDecode(modListData)); | FeedbackModel model = FeedbackModel.fromJson(jsonDecode(modListData)); | ||||
model.feedbackTypes.last.isSelect = true; | |||||
return model; | return model; | ||||
} | } | ||||
} | } | ||||
@@ -25,6 +46,71 @@ class FeedBackRepository { | |||||
return null; | return null; | ||||
} | } | ||||
/// 获取网络数据 | |||||
/// 提交反馈 | |||||
Future<dynamic> saveFeedback(final Map<String, dynamic> data) async { | |||||
try { | |||||
List<File> files = data['files']; | |||||
List<String> imageList = []; | |||||
if(!EmptyUtil.isEmpty(files)) { | |||||
// files.forEach((element) async { | |||||
// String fileName = await updateFile(element); | |||||
// if (!EmptyUtil.isEmpty(fileName)) { | |||||
// imageList.add(fileName); | |||||
// } | |||||
// }); | |||||
for(int i = 0 ; i < files.length; i++){ | |||||
String imgName = await updateFile(files[i]); | |||||
if(!EmptyUtil.isEmpty(imgName)){ | |||||
imageList.add(imgName); | |||||
} | |||||
} | |||||
if (imageList.length != files.length) { | |||||
return null; | |||||
} | |||||
} | |||||
var result = await NetUtil.post('/api/v1/feedback/save', method: NetMethod.POST, params: { | |||||
'type': data['type']?.toString(), | |||||
'title': data['title']?.toString(), | |||||
'content': data['content']?.toString(), | |||||
'image_list': imageList, | |||||
}); | |||||
if (NetUtil.isSuccess(result) && !EmptyUtil.isEmpty(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { | |||||
return result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; | |||||
} | |||||
} catch (e, s) { | |||||
Logger.error(e, s); | |||||
} | |||||
return null; | |||||
} | |||||
/// 上传图片 | |||||
Future<String> updateFile(final File imageFile) async { | |||||
try { | |||||
List<int> originBytes = await imageFile.readAsBytes(); | |||||
var result1 = await NetUtil.post('/api/v1/img/upload', params: {'dir': 'feedback', '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<String, dynamic> 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; | |||||
} | |||||
} | } |
@@ -13,3 +13,9 @@ class FeedbackLoadedState extends FeedbackState{ | |||||
} | } | ||||
class FeedbackErrorState extends FeedbackState{} | class FeedbackErrorState extends FeedbackState{} | ||||
/// 保存反馈成功 | |||||
class FeedbackSaveSuccessState extends FeedbackState{} | |||||
/// 保存反馈失败 | |||||
class FeedbackSaveErrorState extends FeedbackState{} |
@@ -1,4 +1,5 @@ | |||||
import 'dart:io'; | import 'dart:io'; | ||||
import 'dart:math'; | |||||
import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
@@ -55,6 +56,9 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
TextEditingController _title; | TextEditingController _title; | ||||
// 是否上传中 | |||||
bool isUpLoading = false; | |||||
@override | @override | ||||
void initState() { | void initState() { | ||||
_feedback = TextEditingController(); | _feedback = TextEditingController(); | ||||
@@ -69,7 +73,6 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
super.dispose(); | super.dispose(); | ||||
} | } | ||||
/// 选择图片 | /// 选择图片 | ||||
void _onAddImage() async { | void _onAddImage() async { | ||||
if (_images.length >= 4) { | if (_images.length >= 4) { | ||||
@@ -107,9 +110,13 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
if (file == null) return; | if (file == null) return; | ||||
setState(() { | |||||
_images.add(File(file.path)); | |||||
}); | |||||
if (_images.length <= 4) { | |||||
setState(() { | |||||
_images.add(File(file.path)); | |||||
}); | |||||
} else { | |||||
Fluttertoast.showToast(msg: '最多只能选择4张'); | |||||
} | |||||
// File resultFile = await EncodeUtil.compressImage(file, 800); | // File resultFile = await EncodeUtil.compressImage(file, 800); | ||||
} | } | ||||
@@ -120,6 +127,19 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
return BlocConsumer<FeedbackBloc, FeedbackState>( | return BlocConsumer<FeedbackBloc, FeedbackState>( | ||||
listener: (context, state) {}, | listener: (context, state) {}, | ||||
buildWhen: (prev, current) { | 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; | return true; | ||||
}, | }, | ||||
builder: (context, state) { | builder: (context, state) { | ||||
@@ -169,14 +189,7 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
Center( | Center( | ||||
child: GestureDetector( | child: GestureDetector( | ||||
behavior: HitTestBehavior.opaque, | behavior: HitTestBehavior.opaque, | ||||
onTap: () { | |||||
Navigator.push( | |||||
context, | |||||
CupertinoPageRoute( | |||||
builder: (_) => FeedbackRecordPage(), | |||||
), | |||||
); | |||||
}, | |||||
onTap: () => RouterUtil.route(model, model.toJson(), context), | |||||
child: Container( | child: Container( | ||||
width: 120, | width: 120, | ||||
height: 30, | height: 30, | ||||
@@ -273,6 +286,7 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
), | ), | ||||
), | ), | ||||
const SizedBox(height: 2), | const SizedBox(height: 2), | ||||
/// 异常选项 | /// 异常选项 | ||||
Padding( | Padding( | ||||
padding: EdgeInsets.only(top: 4, bottom: 4), | padding: EdgeInsets.only(top: 4, bottom: 4), | ||||
@@ -281,16 +295,15 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
child: Row( | child: Row( | ||||
children: model.feedbackTypes | children: model.feedbackTypes | ||||
.map((e) => Expanded( | .map((e) => Expanded( | ||||
child: GestureDetector( | |||||
child: GestureDetector( | |||||
behavior: HitTestBehavior.opaque, | behavior: HitTestBehavior.opaque, | ||||
onTap: (){ | |||||
onTap: () { | |||||
setState(() { | setState(() { | ||||
model.feedbackTypes.forEach((element) { | model.feedbackTypes.forEach((element) { | ||||
element.isSelect = false; | element.isSelect = false; | ||||
}); | }); | ||||
e.isSelect = true; | e.isSelect = true; | ||||
}); | }); | ||||
}, | }, | ||||
child: Container( | child: Container( | ||||
margin: EdgeInsets.only(left: 2, right: 2), | margin: EdgeInsets.only(left: 2, right: 2), | ||||
@@ -311,9 +324,8 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
e.name ?? '', | e.name ?? '', | ||||
style: TextStyle( | style: TextStyle( | ||||
fontSize: 12, | fontSize: 12, | ||||
color: HexColor.fromHex(e.isSelect | |||||
? model?.feedbackTypeSelectedTextColor | |||||
: model?.feedbackTypeNoSelectedTextColor) //e.isSelect ? Colors.redAccent : Color(0xff999999), | |||||
color: HexColor.fromHex( | |||||
e.isSelect ? model?.feedbackTypeSelectedTextColor : model?.feedbackTypeNoSelectedTextColor) //e.isSelect ? Colors.redAccent : Color(0xff999999), | |||||
), | ), | ||||
), | ), | ||||
), | ), | ||||
@@ -401,8 +413,9 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
child: FeedbackImageWidget( | child: FeedbackImageWidget( | ||||
file: file, | file: file, | ||||
onDelete: () { | onDelete: () { | ||||
_images.remove(file); | |||||
setState(() {}); | |||||
setState(() { | |||||
_images.remove(file); | |||||
}); | |||||
}, | }, | ||||
), | ), | ||||
)); | )); | ||||
@@ -425,6 +438,8 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
} | } | ||||
return Column( | return Column( | ||||
mainAxisAlignment: MainAxisAlignment.center, | |||||
crossAxisAlignment: CrossAxisAlignment.start, | |||||
children: <Widget>[ | children: <Widget>[ | ||||
Row( | Row( | ||||
children: <Widget>[ | children: <Widget>[ | ||||
@@ -448,9 +463,18 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
), | ), | ||||
], | ], | ||||
), | ), | ||||
Row( | |||||
// Row( | |||||
// children: images, | |||||
// ) | |||||
Wrap( | |||||
crossAxisAlignment: WrapCrossAlignment.center, | |||||
textDirection: TextDirection.ltr, | |||||
spacing: 0, | |||||
runSpacing: 0, | |||||
runAlignment: WrapAlignment.center, | |||||
alignment: WrapAlignment.start, | |||||
children: images, | children: images, | ||||
) | |||||
), | |||||
], | ], | ||||
); | ); | ||||
} | } | ||||
@@ -461,9 +485,27 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
if (!_submitable) { | if (!_submitable) { | ||||
return; | return; | ||||
} | } | ||||
if(isUpLoading){ | |||||
// Fluttertoast.showToast(msg: '提交中...'); | |||||
return; | |||||
} | |||||
setState(() { | |||||
isUpLoading = true; | |||||
}); | |||||
Logger.debug('提交:${_feedback.text.toString()}'); | Logger.debug('提交:${_feedback.text.toString()}'); | ||||
Fluttertoast.showToast(msg: '提交成功~'); | |||||
Navigator.pop(context); | |||||
String selectId; | |||||
model.feedbackTypes.forEach((element) { | |||||
if (element.isSelect) { | |||||
selectId = element.typeId; | |||||
} | |||||
}); | |||||
BlocProvider.of<FeedbackBloc>(context) | |||||
.add(FeedbackSubmitEvent(model: {'title': _title?.text?.toString(), 'content': _feedback?.text?.toString(), 'type': selectId, 'files': _images})); | |||||
// Fluttertoast.showToast(msg: '提交成功~'); | |||||
// Navigator.pop(context); | |||||
}, | }, | ||||
child: Container( | child: Container( | ||||
margin: EdgeInsets.only(top: 24, bottom: 4), | margin: EdgeInsets.only(top: 24, bottom: 4), | ||||
@@ -474,7 +516,7 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
), | ), | ||||
child: Center( | child: Center( | ||||
child: Text( | child: Text( | ||||
model?.feedbackPostBtnText ?? '提交意见', | |||||
isUpLoading ? '提交意见...' : model?.feedbackPostBtnText ?? '提交意见', | |||||
style: TextStyle( | style: TextStyle( | ||||
fontSize: 14, | fontSize: 14, | ||||
color: HexColor.fromHex(model?.feedbackPostBtnTextColor ?? '#FFFFFF'), | color: HexColor.fromHex(model?.feedbackPostBtnTextColor ?? '#FFFFFF'), | ||||
@@ -484,6 +526,4 @@ class __FeedbackPageContainerState extends State<_FeedbackPageContainer> { | |||||
), | ), | ||||
); | ); | ||||
} | } | ||||
} | } |
@@ -1,36 +1,167 @@ | |||||
import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/bloc/feedback_record_bloc.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/bloc/feedback_record_repository.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_data_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_style_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/widgets/feedback_record_item.dart'; | import 'package:zhiying_base_widget/pages/feedback_page/widgets/feedback_record_item.dart'; | ||||
import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart'; | import 'package:zhiying_base_widget/widgets/empty/empty_widget.dart'; | ||||
import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
import 'bloc/feedback_record_event.dart'; | |||||
import 'bloc/feedback_record_state.dart'; | |||||
class FeedbackRecordPage extends StatelessWidget { | |||||
final Map<String, dynamic> data; | |||||
FeedbackRecordPage(this.data); | |||||
class FeedbackRecordPage extends StatefulWidget { | |||||
@override | @override | ||||
_FeedbackRecordPageState createState() => _FeedbackRecordPageState(); | |||||
Widget build(BuildContext context) { | |||||
return BlocProvider<FeedbackRecordBloc>( | |||||
create: (_) => FeedbackRecordBloc(FeedbackRecordRepository(data))..add(FeedbackRecordInitEvent()), | |||||
child: _FeedbackRecordPage(), | |||||
); | |||||
} | |||||
} | } | ||||
class _FeedbackRecordPageState extends State<FeedbackRecordPage> { | |||||
class _FeedbackRecordPage extends StatefulWidget { | |||||
@override | |||||
__FeedbackRecordPageState createState() => __FeedbackRecordPageState(); | |||||
} | |||||
class __FeedbackRecordPageState extends State<_FeedbackRecordPage> { | |||||
RefreshController _controller; | |||||
/// 点击详情 | |||||
/// 刷新 | |||||
void _refresh() { | |||||
BlocProvider.of<FeedbackRecordBloc>(context).add(FeedbackRecordRefreshEvent()); | |||||
} | |||||
/// 加载更多 | |||||
void _load() { | |||||
BlocProvider.of<FeedbackRecordBloc>(context).add(FeedbackRecordLoadEvent()); | |||||
} | |||||
@override | |||||
void initState() { | |||||
_controller = RefreshController(); | |||||
super.initState(); | |||||
} | |||||
@override | |||||
void dispose() { | |||||
_controller?.dispose(); | |||||
super.dispose(); | |||||
} | |||||
@override | @override | ||||
Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
return BlocConsumer<FeedbackRecordBloc, FeedbackRecordState>( | |||||
listener: (context, state) {}, | |||||
buildWhen: (prev, current) { | |||||
if (current is FeedbackRecordRefreshSuccessState) { | |||||
_controller?.refreshCompleted(resetFooterState: true); | |||||
return false; | |||||
} | |||||
if (current is FeedbackRecordRefreshErrorState) { | |||||
_controller?.refreshFailed(); | |||||
return false; | |||||
} | |||||
if (current is FeedbackRecordLoadSuccessState) { | |||||
_controller?.loadComplete(); | |||||
return false; | |||||
} | |||||
if (current is FeedbackRecordLoadErrorState) { | |||||
_controller?.loadNoData(); | |||||
return false; | |||||
} | |||||
return true; | |||||
}, | |||||
builder: (context, state) { | |||||
/// 数据视图 | |||||
if (state is FeedbackRecordLoadedState) { | |||||
return _createDataWidget(state?.styleModel, state?.dataModel); | |||||
} | |||||
/// 初始化失败,空视图 | |||||
if (state is FeedbackRecordInitErrorState) { | |||||
return _createEmptyWidget(); | |||||
} | |||||
/// 加载中,骨架图 | |||||
return _createSkeletonWidget(); | |||||
}, | |||||
); | |||||
} | |||||
/// 有数据 | |||||
Widget _createDataWidget(FeedbackRecordStyleModel styleModel, FeedbackRecordDataModel dataModel) { | |||||
int length = dataModel?.data?.length ?? 0; | |||||
if(length == 0 ) return _createEmptyWidget(); | |||||
return Scaffold( | |||||
appBar: _createNav(styleModel), | |||||
body: GestureDetector( | |||||
onTap: () { | |||||
FocusScope.of(context).requestFocus(FocusNode()); | |||||
}, | |||||
child: SafeArea( | |||||
child: SmartRefresher( | |||||
controller: _controller, | |||||
enablePullUp: true, | |||||
enablePullDown: true, | |||||
onRefresh: _refresh, | |||||
onLoading: _load, | |||||
child: ListView.builder( | |||||
itemCount: length, | |||||
itemBuilder: (context, index) { | |||||
return FeedbackRecordItem(styleModel, dataModel.data[index]); | |||||
}), | |||||
), | |||||
), | |||||
), | |||||
); | |||||
} | |||||
/// 空数据 | |||||
Widget _createEmptyWidget() { | |||||
return Scaffold( | return Scaffold( | ||||
appBar: _createNav(), | |||||
appBar: _createNav(null), | |||||
body: GestureDetector( | body: GestureDetector( | ||||
onTap: () { | onTap: () { | ||||
FocusScope.of(context).requestFocus(FocusNode()); | FocusScope.of(context).requestFocus(FocusNode()); | ||||
}, | }, | ||||
child: SafeArea( | child: SafeArea( | ||||
child: Center(child: EmptyWidget()), | |||||
// child: ListView.builder( | |||||
// itemCount: 10, | |||||
// itemBuilder: (context, index) { | |||||
// return FeedbackRecordItem(); | |||||
// }), | |||||
child: SmartRefresher( | |||||
controller: _controller, | |||||
enablePullDown: true, | |||||
enablePullUp: false, | |||||
onRefresh: _refresh, | |||||
child: Center(child: EmptyWidget()), | |||||
), | |||||
), | ), | ||||
), | ), | ||||
); | ); | ||||
} | } | ||||
// 导航栏 | |||||
Widget _createNav() { | |||||
/// 骨架图 | |||||
Widget _createSkeletonWidget() { | |||||
return Scaffold( | |||||
appBar: _createNav(null), | |||||
body: Container(), | |||||
); | |||||
} | |||||
/// 导航栏 | |||||
Widget _createNav(FeedbackRecordStyleModel styleModel) { | |||||
return CupertinoNavigationBar( | return CupertinoNavigationBar( | ||||
border: Border( | border: Border( | ||||
bottom: BorderSide( | bottom: BorderSide( | ||||
@@ -38,7 +169,7 @@ class _FeedbackRecordPageState extends State<FeedbackRecordPage> { | |||||
style: BorderStyle.none, | style: BorderStyle.none, | ||||
), | ), | ||||
), | ), | ||||
backgroundColor: Colors.white, | |||||
backgroundColor: HexColor.fromHex(styleModel?.appBarBgColor ?? '#FFFFFF'), | |||||
leading: Navigator.canPop(context) | leading: Navigator.canPop(context) | ||||
? GestureDetector( | ? GestureDetector( | ||||
child: Container( | child: Container( | ||||
@@ -56,10 +187,10 @@ class _FeedbackRecordPageState extends State<FeedbackRecordPage> { | |||||
) | ) | ||||
: Container(), | : Container(), | ||||
middle: Text( | middle: Text( | ||||
'反馈列表', | |||||
styleModel?.appBarName ?? '反馈列表', | |||||
style: TextStyle( | style: TextStyle( | ||||
fontSize: 15, | fontSize: 15, | ||||
color: Color(0xff333333), | |||||
color: HexColor.fromHex(styleModel?.appBarNameColor ?? '#FF333333'), | |||||
), | ), | ||||
), | ), | ||||
); | ); | ||||
@@ -1,4 +1,6 @@ | |||||
class FeedbackModel { | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FeedbackModel extends SkipModel{ | |||||
String appBarName; | String appBarName; | ||||
String appBarNameColor; | String appBarNameColor; | ||||
String appBarBgColor; | String appBarBgColor; | ||||
@@ -73,6 +75,7 @@ class FeedbackModel { | |||||
this.skipIdentifier}); | this.skipIdentifier}); | ||||
FeedbackModel.fromJson(Map<String, dynamic> json) { | FeedbackModel.fromJson(Map<String, dynamic> json) { | ||||
super.fromJson(json); | |||||
appBarName = json['app_bar_name']; | appBarName = json['app_bar_name']; | ||||
appBarNameColor = json['app_bar_name_color']; | appBarNameColor = json['app_bar_name_color']; | ||||
appBarBgColor = json['app_bar_bg_color']; | appBarBgColor = json['app_bar_bg_color']; | ||||
@@ -121,7 +124,7 @@ class FeedbackModel { | |||||
} | } | ||||
Map<String, dynamic> toJson() { | Map<String, dynamic> toJson() { | ||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
final Map<String, dynamic> data = super.toJson(); | |||||
data['app_bar_name'] = this.appBarName; | data['app_bar_name'] = this.appBarName; | ||||
data['app_bar_name_color'] = this.appBarNameColor; | data['app_bar_name_color'] = this.appBarNameColor; | ||||
data['app_bar_bg_color'] = this.appBarBgColor; | data['app_bar_bg_color'] = this.appBarBgColor; | ||||
@@ -0,0 +1,60 @@ | |||||
/// 反馈列表数据 | |||||
class FeedbackRecordDataModel { | |||||
List<FeedbackRecordDataItemModel> data; | |||||
FeedbackRecordDataModel({this.data}); | |||||
FeedbackRecordDataModel.fromJson(Map<String, dynamic> json) { | |||||
if (json['data'] != null) { | |||||
data = new List<FeedbackRecordDataItemModel>(); | |||||
json['data'].forEach((v) { | |||||
data.add(new FeedbackRecordDataItemModel.fromJson(v)); | |||||
}); | |||||
} | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
if (this.data != null) { | |||||
data['data'] = this.data.map((v) => v.toJson()).toList(); | |||||
} | |||||
return data; | |||||
} | |||||
} | |||||
class FeedbackRecordDataItemModel { | |||||
String id; | |||||
String type; | |||||
String typeText; | |||||
String state; | |||||
String title; | |||||
String content; | |||||
List<String> imageList; | |||||
String createTime; | |||||
FeedbackRecordDataItemModel({this.id, this.type, this.typeText, this.state, this.title, this.content, this.imageList, this.createTime}); | |||||
FeedbackRecordDataItemModel.fromJson(Map<String, dynamic> json) { | |||||
id = json['id']; | |||||
type = json['type']; | |||||
typeText = json['type_text']; | |||||
state = json['state']; | |||||
title = json['title']; | |||||
content = json['content']; | |||||
imageList = json['image_list'].cast<String>(); | |||||
createTime = json['create_time']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['id'] = this.id; | |||||
data['type'] = this.type; | |||||
data['type_text'] = this.typeText; | |||||
data['state'] = this.state; | |||||
data['title'] = this.title; | |||||
data['content'] = this.content; | |||||
data['image_list'] = this.imageList; | |||||
data['create_time'] = this.createTime; | |||||
return data; | |||||
} | |||||
} |
@@ -0,0 +1,140 @@ | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
/// 反馈列表样式 | |||||
class FeedbackRecordStyleModel extends SkipModel{ | |||||
String appBarName; | |||||
String appBarNameColor; | |||||
String appBarBgColor; | |||||
String bgColor; | |||||
ItemStyle itemStyle; | |||||
List<FeedbackTypes> feedbackTypes; | |||||
List<StateImages> stateImages; | |||||
String requiredLogin; | |||||
String requiredTaobaoAuth; | |||||
String skipIdentifier; | |||||
FeedbackRecordStyleModel( | |||||
{this.appBarName, | |||||
this.appBarNameColor, | |||||
this.appBarBgColor, | |||||
this.bgColor, | |||||
this.itemStyle, | |||||
this.feedbackTypes, | |||||
this.stateImages, | |||||
this.requiredLogin, | |||||
this.requiredTaobaoAuth, | |||||
this.skipIdentifier}); | |||||
FeedbackRecordStyleModel.fromJson(Map<String, dynamic> json) { | |||||
super.fromJson(json); | |||||
appBarName = json['app_bar_name']; | |||||
appBarNameColor = json['app_bar_name_color']; | |||||
appBarBgColor = json['app_bar_bg_color']; | |||||
bgColor = json['bg_color']; | |||||
itemStyle = json['item_style'] != null ? new ItemStyle.fromJson(json['item_style']) : null; | |||||
if (json['feedback_types'] != null) { | |||||
feedbackTypes = new List<FeedbackTypes>(); | |||||
json['feedback_types'].forEach((v) { | |||||
feedbackTypes.add(new FeedbackTypes.fromJson(v)); | |||||
}); | |||||
} | |||||
if (json['state_images'] != null) { | |||||
stateImages = new List<StateImages>(); | |||||
json['state_images'].forEach((v) { | |||||
stateImages.add(new StateImages.fromJson(v)); | |||||
}); | |||||
} | |||||
requiredLogin = json['required_login']; | |||||
requiredTaobaoAuth = json['required_taobao_auth']; | |||||
skipIdentifier = json['skip_identifier']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = super.toJson(); | |||||
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; | |||||
if (this.itemStyle != null) { | |||||
data['item_style'] = this.itemStyle.toJson(); | |||||
} | |||||
if (this.feedbackTypes != null) { | |||||
data['feedback_types'] = this.feedbackTypes.map((v) => v.toJson()).toList(); | |||||
} | |||||
if (this.stateImages != null) { | |||||
data['state_images'] = this.stateImages.map((v) => v.toJson()).toList(); | |||||
} | |||||
data['required_login'] = this.requiredLogin; | |||||
data['required_taobao_auth'] = this.requiredTaobaoAuth; | |||||
data['skip_identifier'] = this.skipIdentifier; | |||||
return data; | |||||
} | |||||
} | |||||
class ItemStyle { | |||||
String bgColor; | |||||
String typeTextColor; | |||||
String typeBgColor; | |||||
String titleTextColor; | |||||
String contentTextColor; | |||||
String timeTextColor; | |||||
ItemStyle({this.bgColor, this.typeTextColor, this.typeBgColor, this.titleTextColor, this.contentTextColor, this.timeTextColor}); | |||||
ItemStyle.fromJson(Map<String, dynamic> json) { | |||||
bgColor = json['bg_color']; | |||||
typeTextColor = json['type_text_color']; | |||||
typeBgColor = json['type_bg_color']; | |||||
titleTextColor = json['title_text_color']; | |||||
contentTextColor = json['content_text_color']; | |||||
timeTextColor = json['time_text_color']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['bg_color'] = this.bgColor; | |||||
data['type_text_color'] = this.typeTextColor; | |||||
data['type_bg_color'] = this.typeBgColor; | |||||
data['title_text_color'] = this.titleTextColor; | |||||
data['content_text_color'] = this.contentTextColor; | |||||
data['time_text_color'] = this.timeTextColor; | |||||
return data; | |||||
} | |||||
} | |||||
class FeedbackTypes { | |||||
String typeId; | |||||
String name; | |||||
FeedbackTypes({this.typeId, this.name}); | |||||
FeedbackTypes.fromJson(Map<String, dynamic> json) { | |||||
typeId = json['type_id']; | |||||
name = json['name']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['type_id'] = this.typeId; | |||||
data['name'] = this.name; | |||||
return data; | |||||
} | |||||
} | |||||
class StateImages { | |||||
String stateId; | |||||
String img; | |||||
StateImages({this.stateId, this.img}); | |||||
StateImages.fromJson(Map<String, dynamic> json) { | |||||
stateId = json['state_id']; | |||||
img = json['img']; | |||||
} | |||||
Map<String, dynamic> toJson() { | |||||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
data['state_id'] = this.stateId; | |||||
data['img'] = this.img; | |||||
return data; | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
import 'dart:io'; | |||||
class FeedbackSaveModel { | |||||
String type; | |||||
String title; | |||||
String content; | |||||
List<File> files; | |||||
FeedbackSaveModel({this.type, this.title, this.content, this.files}); | |||||
} |
@@ -1,6 +1,14 @@ | |||||
import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_data_model.dart'; | |||||
import 'package:zhiying_base_widget/pages/feedback_page/model/feedback_record_style_model.dart'; | |||||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||||
class FeedbackRecordItem extends StatelessWidget { | class FeedbackRecordItem extends StatelessWidget { | ||||
FeedbackRecordStyleModel styleModel; | |||||
FeedbackRecordDataItemModel dataModel; | |||||
FeedbackRecordItem(this.styleModel, this.dataModel); | |||||
@override | @override | ||||
Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
return Container( | return Container( | ||||
@@ -8,7 +16,7 @@ class FeedbackRecordItem extends StatelessWidget { | |||||
padding: EdgeInsets.all(15), | padding: EdgeInsets.all(15), | ||||
width: double.infinity, | width: double.infinity, | ||||
decoration: BoxDecoration( | decoration: BoxDecoration( | ||||
color: Colors.white, | |||||
color: HexColor.fromHex(styleModel?.itemStyle?.bgColor ?? '#FFFFFF'), | |||||
borderRadius: BorderRadius.circular(7.5), | borderRadius: BorderRadius.circular(7.5), | ||||
), | ), | ||||
child: Row( | child: Row( | ||||
@@ -31,40 +39,53 @@ class FeedbackRecordItem extends StatelessWidget { | |||||
width: 60, | width: 60, | ||||
height: 60, | height: 60, | ||||
decoration: BoxDecoration( | decoration: BoxDecoration( | ||||
color: Colors.green, | |||||
// color: Colors.green, | |||||
borderRadius: BorderRadius.circular(30), | borderRadius: BorderRadius.circular(30), | ||||
), | ), | ||||
child: CachedNetworkImage( | |||||
imageUrl: getStateImageUrl(), | |||||
), | |||||
) | ) | ||||
], | ], | ||||
), | ), | ||||
); | ); | ||||
} | } | ||||
String getStateImageUrl(){ | |||||
String result = ''; | |||||
int length = styleModel?.stateImages?.length ?? 0; | |||||
if(length > 0){ | |||||
styleModel.stateImages.forEach((element) { | |||||
if(element.stateId == dataModel.state){ | |||||
result = element.img; | |||||
} | |||||
}); | |||||
} | |||||
return result; | |||||
} | |||||
Widget _createTitle() { | Widget _createTitle() { | ||||
List<InlineSpan> list = List(); | List<InlineSpan> list = List(); | ||||
list.add(WidgetSpan( | list.add(WidgetSpan( | ||||
child: Container( | child: Container( | ||||
padding: EdgeInsets.only(left: 2, right: 2, top: 3, bottom: 3), | |||||
padding: EdgeInsets.only(left: 4.5, right: 4.5, top: 3, bottom: 3), | |||||
margin: EdgeInsets.only(right: 4), | margin: EdgeInsets.only(right: 4), | ||||
child: Text( | child: Text( | ||||
'功能异常', | |||||
dataModel?.typeText ?? '其它', | |||||
style: TextStyle( | style: TextStyle( | ||||
fontSize: 9, | fontSize: 9, | ||||
height: 1, | height: 1, | ||||
// color: HexColor.fromHex(style.providerNameColor), | |||||
color: Colors.white, | |||||
color: HexColor.fromHex(styleModel?.itemStyle?.typeTextColor ?? '#FFFFFF'), | |||||
), | ), | ||||
), | ), | ||||
decoration: BoxDecoration( | |||||
color: Colors.redAccent, borderRadius: BorderRadius.circular(2.5)), | |||||
decoration: BoxDecoration(color: HexColor.fromHex(styleModel?.itemStyle?.typeBgColor ?? '#FF4242'), borderRadius: BorderRadius.circular(2.5)), | |||||
), | ), | ||||
)); | )); | ||||
list.add(TextSpan( | list.add(TextSpan( | ||||
text: '关于关闭提现功能的反馈', | |||||
style: TextStyle( | |||||
fontSize: 14, color: Color(0xff333333), fontWeight: FontWeight.bold), | |||||
text: dataModel?.title ?? '', | |||||
style: TextStyle(fontSize: 14, color: HexColor.fromHex(styleModel?.itemStyle?.titleTextColor ?? '#333333'), fontWeight: FontWeight.bold), | |||||
)); | )); | ||||
return RichText( | return RichText( | ||||
maxLines: 2, | maxLines: 2, | ||||
@@ -76,32 +97,44 @@ class FeedbackRecordItem extends StatelessWidget { | |||||
Widget _createDesc() { | Widget _createDesc() { | ||||
return Container( | return Container( | ||||
child: Text( | child: Text( | ||||
'我今天想使用我的提现功能的时候,发现官方已经把这个功能给暂时关闭了,所以我很伤心,不开心不开心不开心,所以我很伤心,不开心不开心不开心', | |||||
style: TextStyle(fontSize: 11, color: Color(0xff999999)), | |||||
dataModel?.content ?? '', | |||||
style: TextStyle(fontSize: 11, color: HexColor.fromHex(styleModel?.itemStyle?.contentTextColor ?? '#999999')), | |||||
), | ), | ||||
); | ); | ||||
} | } | ||||
Widget _createImage() { | Widget _createImage() { | ||||
return Container( | |||||
margin: EdgeInsets.only(top: 4, bottom: 4), | |||||
child: Wrap( | |||||
children: <Widget>[ | |||||
List<Widget> images = []; | |||||
int length = dataModel?.imageList?.length ?? 0; | |||||
if (length > 0) { | |||||
for (int i = 0; i < length; i++) { | |||||
images.add( | |||||
Container( | Container( | ||||
width: 60, | width: 60, | ||||
height: 60, | height: 60, | ||||
color: Colors.redAccent, | |||||
child: CachedNetworkImage( | |||||
imageUrl: dataModel?.imageList[i] ?? '', | |||||
), | |||||
), | ), | ||||
], | |||||
), | |||||
); | |||||
); | |||||
} | |||||
return Container( | |||||
margin: EdgeInsets.only(top: 4, bottom: 4), | |||||
child: Wrap( | |||||
children: images, | |||||
), | |||||
); | |||||
} else { | |||||
return Container(); | |||||
} | |||||
} | } | ||||
Widget _createTime() { | Widget _createTime() { | ||||
return Container( | return Container( | ||||
child: Text( | child: Text( | ||||
'2020-06-23 01:00:06', | |||||
style: TextStyle(fontSize: 11, color: Color(0xffd8d8d8)), | |||||
dataModel?.createTime ?? '', | |||||
style: TextStyle(fontSize: 11, color: HexColor.fromHex(styleModel?.itemStyle?.timeTextColor ?? '#D8D8D8')), | |||||
), | ), | ||||
); | ); | ||||
} | } | ||||
@@ -6,6 +6,7 @@ import 'package:sharesdk_plugin/sharesdk_register.dart'; | |||||
import 'package:zhiying_base_widget/pages/about_us_page/about_us_page.dart'; | import 'package:zhiying_base_widget/pages/about_us_page/about_us_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/bil_detail_page/bil_detail_page.dart'; | import 'package:zhiying_base_widget/pages/bil_detail_page/bil_detail_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/feedback_page/feedback_page.dart'; | import 'package:zhiying_base_widget/pages/feedback_page/feedback_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/feedback_page/feedback_record_page.dart'; | |||||
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | ||||
import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page.dart'; | import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page.dart'; | ||||
@@ -58,6 +59,7 @@ import 'package:zhiying_base_widget/widgets/wallet_bil_detail/wallet_bil_detail. | |||||
import 'package:zhiying_comm/util/defalut_widget_creater.dart'; | import 'package:zhiying_comm/util/defalut_widget_creater.dart'; | ||||
import 'package:zhiying_comm/zhiying_comm.dart'; | import 'package:zhiying_comm/zhiying_comm.dart'; | ||||
import 'pages/custom_page/custom_page.dart'; | |||||
import 'pages/favorites_page/favorites_page.dart'; | import 'pages/favorites_page/favorites_page.dart'; | ||||
import 'pages/message_notice_page/message_notice_page.dart'; | import 'pages/message_notice_page/message_notice_page.dart'; | ||||
import 'pages/privacy_settings_page/privacy_settings_page.dart'; | import 'pages/privacy_settings_page/privacy_settings_page.dart'; | ||||
@@ -139,6 +141,7 @@ class BaseWidgetRegister { | |||||
PageFactory.regist( | PageFactory.regist( | ||||
'search_result_item', (model) => SearchResultItemPage(model)); | 'search_result_item', (model) => SearchResultItemPage(model)); | ||||
PageFactory.regist('pub.flutter.feedback', (model) => FeedbackPage(model)); | PageFactory.regist('pub.flutter.feedback', (model) => FeedbackPage(model)); | ||||
PageFactory.regist('pub.flutter.feedback_list', (model) => FeedbackRecordPage(model)); | |||||
PageFactory.regist( | PageFactory.regist( | ||||
'pub.flutter.wechat_teacher', (model) => WechatTeacherPage()); | 'pub.flutter.wechat_teacher', (model) => WechatTeacherPage()); | ||||
PageFactory.regist('pub.flutter.cash_out', (model) => WithdrawPage(model)); | PageFactory.regist('pub.flutter.cash_out', (model) => WithdrawPage(model)); | ||||
@@ -199,7 +202,7 @@ class BaseWidgetRegister { | |||||
'pub.flutter.my_wallet_detail', (model) => BilDetailPage(model)); | 'pub.flutter.my_wallet_detail', (model) => BilDetailPage(model)); | ||||
/// 通用模块 | /// 通用模块 | ||||
PageFactory.regist('pub.flutter.custom', (model) => EmptyPage()); | |||||
PageFactory.regist('pub.flutter.custom', (model) => CustomPage(model)); | |||||
} | } | ||||
// 注册控件 | // 注册控件 | ||||