|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
|
import 'package:dio/dio.dart';
|
|
|
//屏幕适配 flutter_screenutil 库与 flustars(获取网络图片尺寸要用到其 WidgetUtil) 库使用的 ScreenUtil() 类名冲突
|
|
|
// 解决办法是将 flustars 库取个别名 as flustars
|
|
|
import 'package:flustars/flustars.dart' as flustars;
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/services.dart';
|
|
|
import 'package:flutter_drag_scale/flutter_drag_scale.dart';
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
|
import 'package:hyzp_ybqx511528_xingwen/widget/my_superplayer.dart';
|
|
|
import 'package:keyboard_avoider/keyboard_avoider.dart';
|
|
|
import 'package:photo_view/photo_view.dart';
|
|
|
|
|
|
import '../../../components/commonFun.dart';
|
|
|
import '../../../components/dioFun.dart';
|
|
|
import '../../../components/doJSON.dart';
|
|
|
import '../../../components/hyxx_data_handle.dart';
|
|
|
import '../../../config/service_url.dart';
|
|
|
import '../../../services/EventBus.dart';
|
|
|
//import 'package:hyzp_ybqx511528_xingwen/widget/player_pro_new.dart';
|
|
|
|
|
|
import '../../../widget/CarNumberAndCpysItems.dart';
|
|
|
import 'hysh_group.dart';
|
|
|
|
|
|
class HyshContentNew extends StatefulWidget {
|
|
|
HyshContentNew({
|
|
|
@required this.hyshlx,
|
|
|
@required this.title,
|
|
|
this.indexRecord,
|
|
|
this.id,
|
|
|
Key key,
|
|
|
}) : super(key: key);
|
|
|
String title;
|
|
|
int indexRecord = 0;
|
|
|
int id = -1;
|
|
|
String hyshlx;
|
|
|
|
|
|
_HyshPageState createState() => _HyshPageState();
|
|
|
}
|
|
|
|
|
|
//用TabController实现顶部tab切换
|
|
|
class _HyshPageState extends State<HyshContentNew> with SingleTickerProviderStateMixin {
|
|
|
//try_setState(); //避免如下异常报错
|
|
|
try_setState() {
|
|
|
try {
|
|
|
setState(() {});
|
|
|
} catch (e) {
|
|
|
print('setState(() {})异常:${e}');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//获取黑烟初审单条数据
|
|
|
//接口地址:http://49.235.208.235:9001/?s=App.Car_Yjxx.Get
|
|
|
//接口参数
|
|
|
// 参数名字 类型 是否必须 默认值 其他 说明
|
|
|
// id 字符串 必须 最小:1 ID
|
|
|
|
|
|
//List<TextEditingController> listController = [];
|
|
|
|
|
|
//List<List<TextEditingController>> listZpljController = [];
|
|
|
List ratioList = [];
|
|
|
|
|
|
//用TabController实现顶部tab切换
|
|
|
TabController _tabController;
|
|
|
|
|
|
//监听登录页面销毁的事件
|
|
|
dispose() {
|
|
|
_tabController?.dispose();
|
|
|
super.dispose();
|
|
|
//eventBus.fire(UserEvent('登录成功...'));
|
|
|
}
|
|
|
|
|
|
//int listLen = 0;
|
|
|
String nums = '';
|
|
|
bool bModifiable = false;
|
|
|
String cpysText = '';
|
|
|
String myCpys = '蓝色';
|
|
|
|
|
|
void initState() {
|
|
|
// TODO: implement initState
|
|
|
fh_hyc = true;
|
|
|
tsjj = true;
|
|
|
_context = context;
|
|
|
getListFlields();
|
|
|
|
|
|
// //监听违章信息数据更新事件
|
|
|
// eventBus.on<HycsDataUpdateEvent>().listen((event) {
|
|
|
// print(event.str);
|
|
|
// getListFlields();
|
|
|
// });
|
|
|
|
|
|
// //监听违章信息数据审核事件
|
|
|
// eventBus.on<WzxxDataAuditEvent>().listen((event) {
|
|
|
// print('HycsContentModify: ' + event.str);
|
|
|
// getListFlields();
|
|
|
// });
|
|
|
|
|
|
//黑监听烟初审数据审核Radio选项改变事件
|
|
|
eventBus.on<HycsDataAuditRadioEvent>().listen((event) {
|
|
|
print(event.str);
|
|
|
print('event.selectedRadio = ${event.selectedRadio.toString()}');
|
|
|
if (null != _tabController) {
|
|
|
topTabs_map['auditTitle'][_tabController.index] =
|
|
|
(event.selectedRadio == 0) ? hyc_text : fhyc_text;
|
|
|
topTabs_map['auditShuoming_Controller_List'][_tabController.index].text =
|
|
|
((widget.hyshlx == 'hyfh') ? '初审为' + mapGetHycsShenheData['title'] + '。复审' : '') +
|
|
|
((event.selectedRadio == 0) ? hyc_shyj : fhyc_shyj);
|
|
|
|
|
|
//解决 setState(() {}); 抛异常Unhandled Exception: setState() called after dispose():
|
|
|
try_setState(); //避免如下异常报错
|
|
|
}
|
|
|
});
|
|
|
|
|
|
//黑烟审核推送交警Checkbox改变事件
|
|
|
eventBus.on<HycsDataAuditCheckboxButton>().listen((event) {
|
|
|
print(event.str);
|
|
|
if (null != _tabController) {
|
|
|
//解决 setState(() {}); 抛异常Unhandled Exception: setState() called after dispose():
|
|
|
try_setState(); //避免如下异常报错
|
|
|
}
|
|
|
});
|
|
|
|
|
|
//黑烟初审数据审核Dropdown选项改变事件
|
|
|
eventBus.on<HycsDataAuditDropdownEvent>().listen((event) {
|
|
|
print(event.str);
|
|
|
print('event.selectedValue = ${event.selectedValue}');
|
|
|
print('_tabController.index = ${_tabController.index}');
|
|
|
//topTabs_map['cpysText_List'][_tabController.index] = event.selectedValue; //这样报错如下
|
|
|
myCpys = event.selectedValue;
|
|
|
|
|
|
try_setState(); //避免如下异常报错
|
|
|
|
|
|
//This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer inc
|
|
|
// ludes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
|
|
|
// topTabs_map['carNumberAndCpys_List'][_tabController.index] =
|
|
|
// getCarNumberAndCpys(_tabController.index);
|
|
|
//延时500毫秒执行
|
|
|
// Future.delayed(const Duration(milliseconds: 10), () {
|
|
|
// print('延时后输出:_tabController.index = ${_tabController.index}');
|
|
|
// //延时执行的代码
|
|
|
// //延时更新状态
|
|
|
// setState(() {});
|
|
|
// });
|
|
|
});
|
|
|
|
|
|
super.initState();
|
|
|
}
|
|
|
|
|
|
//避免如下异常报错
|
|
|
// try {
|
|
|
// setState(() {});
|
|
|
// } catch (e) {}
|
|
|
//E/flutter (12227): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: setState() called after dispose(): _LoginPageState#c4f60(lifecycle state: defunct, not mo
|
|
|
// unted, ticker inactive)
|
|
|
// E/flutter (12227): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer inc
|
|
|
// ludes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
|
|
|
// E/flutter (12227): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" prop
|
|
|
// erty of this object before calling setState() to ensure the object is still in the tree.
|
|
|
// E/flutter (12227): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has bee
|
|
|
// n removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
|
|
|
// E/flutter (12227): #0 State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1208:9)
|
|
|
// E/flutter (12227): #1 State.setState (package:flutter/src/widgets/framework.dart:1243:6)
|
|
|
// E/flutter (12227): #2 _LoginPageState.getZpjlFields (package:hyzp_ybqx511528_xingwen/pages/Works/HYSH/hysh_content.dart:163:7)
|
|
|
// E/flutter (12227): #3 _rootRunUnary (dart:async/zone.dart:1198:47)
|
|
|
// E/flutter (12227): #4 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
|
|
|
// E/flutter (12227): #5 _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
|
|
|
// E/flutter (12227): #6 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
|
|
|
// E/flutter (12227): #7 Future._propagateToListeners (dart:async/future_impl.dart:725:32)
|
|
|
// E/flutter (12227): #8 Future._completeWithValue (dart:async/future_impl.dart:529:5)
|
|
|
// E/flutter (12227): #9 Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
|
|
|
// E/flutter (12227): #10 _rootRun (dart:async/zone.dart:1190:13)
|
|
|
// E/flutter (12227): #11 _CustomZone.run (dart:async/zone.dart:1093:19)
|
|
|
// E/flutter (12227): #12 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
|
|
|
// E/flutter (12227): #13 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
|
|
|
// E/flutter (12227): #14 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
|
|
|
// E/flutter (12227): #15 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
|
|
|
// E/flutter (12227):
|
|
|
// E/flutter (12227): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: 'package:flutter/src/widgets/media_query.dart': Failed assertion: line 812 pos 12: 'conte
|
|
|
// xt != null': is not true.
|
|
|
// E/flutter (12227): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
|
|
|
// E/flutter (12227): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
|
|
|
// E/flutter (12227): #2 MediaQuery.of (package:flutter/src/widgets/media_query.dart:812:12)
|
|
|
// E/flutter (12227): #3 _LoginPageState.getTopTabsMap (package:hyzp_ybqx511528_xingwen/pages/Works/HYSH/hysh_content.dart:415:41)
|
|
|
// E/flutter (12227): #4 _LoginPageState.getZpjlFields (package:hyzp_ybqx511528_xingwen/pages/Works/HYSH/hysh_content.dart:162:7)
|
|
|
|
|
|
//getListFlields({bool b = true}) async {
|
|
|
getListFlields() async {
|
|
|
//await getHycsGetData();
|
|
|
//Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<dynamic, dynamic>'
|
|
|
//print('getListFlields().mapGetHycsGetData = ${mapGetHycsGetData}');
|
|
|
//if (b) {
|
|
|
//listZpljController.clear();
|
|
|
listGetZpjl.clear(); //必须先行清空,否则会出现记录数据错位问题
|
|
|
listFieldModify.clear();
|
|
|
mapGetHycsGetData.clear();
|
|
|
|
|
|
//1、获取指定id的抓拍记录列表存入listGetZpjl
|
|
|
//2、如果是黑烟复审,还需获取指定id的违章记录审核信息存入mapGetShenheData
|
|
|
await getItemData(widget.id);
|
|
|
//}
|
|
|
print('getListFlields().listGetZpjl = ${listGetZpjl}');
|
|
|
//print('getListFlields().mapGetHycsGetData = ${mapGetHycsGetData}');
|
|
|
|
|
|
await getZpjlFields();
|
|
|
|
|
|
//nums = '${(widget.indexRecord + 1).toString()} / $listLen';
|
|
|
try {
|
|
|
// nums = '(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})id:${listHycsGetList2[widget.indexRecord]['id']}';
|
|
|
nums = '(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})';
|
|
|
setState(() {});
|
|
|
} catch (e) {}
|
|
|
//setState(() {}); //刚进入时,执行该语句会会抛异常
|
|
|
//print('mapGetHycsGetData = \n${mapGetHycsGetData}');
|
|
|
}
|
|
|
|
|
|
Future getZpjlFields() async {
|
|
|
if (listGetZpjl.isNotEmpty) {
|
|
|
int len = listGetZpjl.length;
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
// 获取网络图片尺寸
|
|
|
Rect rect =
|
|
|
await flustars.WidgetUtil.getImageWH(url: getMediaUrl(listGetZpjl[i]['pic_url']));
|
|
|
ratioList.add(rect.height / rect.width);
|
|
|
print("rect: " + rect.toString());
|
|
|
print("ratio: " + ratioList[i].toString());
|
|
|
}
|
|
|
await getTopTabsMap();
|
|
|
|
|
|
//用TabController实现顶部tab切换
|
|
|
_tabController = TabController(vsync: this, length: topTabs_map['listView_List'].length);
|
|
|
_tabController.addListener(() {
|
|
|
print('_tabController.index = ${_tabController.index}');
|
|
|
|
|
|
//Tab切换时,设置 sfyc 和 tsjj,只处理当前选中的抓拍记录 _tabController.index
|
|
|
set_sfyc_tsjj(int.parse(listGetZpjl[_tabController.index]['zpsj']));
|
|
|
|
|
|
//Tab切换时,初始化所有审核意见
|
|
|
int len = listGetZpjl.length;
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
topTabs_map['auditShuoming_Controller_List'][i].text =
|
|
|
((widget.hyshlx == 'hyfh') ? '初审为' + mapGetHycsShenheData['title'] + '。复审' : '') +
|
|
|
hyc_shyj;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
print('first : _tabController.index = ${_tabController.index}');
|
|
|
set_sfyc_tsjj(int.parse(listGetZpjl[_tabController.index]['zpsj']));
|
|
|
|
|
|
//避免如下异常报错
|
|
|
try_setState(); //避免如下异常报错
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 使用 cached_network_image 插件实现网络图片缓存
|
|
|
// 使用 flutter_drag_scale 实现可缩放可拖拽双击放大的图片功能。PhotoView插件不好用,有问题
|
|
|
Widget getNetworkImage(String url) {
|
|
|
return CachedNetworkImage(
|
|
|
imageUrl: url,
|
|
|
alignment: Alignment.topCenter,
|
|
|
imageBuilder: (context, imageProvider) => DragScaleContainer(
|
|
|
doubleTapStillScale: true, child: Image(image: imageProvider)
|
|
|
// child: Image(
|
|
|
// image: NetworkImage(
|
|
|
// 'http://h.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=0d023672312ac65c67506e77cec29e27/9f2f070828381f30dea167bbad014c086e06f06c.jpg'),
|
|
|
// ),
|
|
|
),
|
|
|
// imageBuilder: (context, imageProvider) => PhotoView(
|
|
|
// imageProvider: imageProvider,
|
|
|
// ),
|
|
|
//placeholder: (context, url) => CircularProgressIndicator(),
|
|
|
placeholder: (context, url) =>
|
|
|
getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0),
|
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//使用 cached_network_image 插件实现网络图片缓存
|
|
|
Widget getNetworkImage1(String url) {
|
|
|
return CachedNetworkImage(
|
|
|
imageUrl: url,
|
|
|
alignment: Alignment.topCenter,
|
|
|
//placeholder: (context, url) => CircularProgressIndicator(),
|
|
|
imageBuilder: (context, imageProvider) => PhotoView(
|
|
|
imageProvider: imageProvider,
|
|
|
),
|
|
|
placeholder: (context, url) =>
|
|
|
getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0),
|
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//3、得到违章图片说明信息组件
|
|
|
Widget getWztpSmxx(int index) {
|
|
|
return Container(
|
|
|
width: ScreenUtil().setWidth(1022),
|
|
|
height: ScreenUtil().setHeight(141),
|
|
|
decoration: BoxDecoration(
|
|
|
color: Colors.white,
|
|
|
borderRadius: BorderRadius.all(
|
|
|
Radius.circular(12),
|
|
|
),
|
|
|
),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
children: [
|
|
|
getWztpSmxx1(index),
|
|
|
getWztpSmxx2(index),
|
|
|
],
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//3.1、得到违章图片说明信息1:黑度、抓拍时间组件
|
|
|
Widget getWztpSmxx1(int index) {
|
|
|
return Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: <Widget>[
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
padding: EdgeInsets.only(left: ScreenUtil().setWidth(_marginLeft)),
|
|
|
width: ScreenUtil().setWidth(_preItem),
|
|
|
child:
|
|
|
Text('黑度:' + listGetZpjl[index]['lgmzs'].toString(), overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
|
|
|
Icon(
|
|
|
Icons.query_builder,
|
|
|
size: ScreenUtil().setWidth(_iconSize),
|
|
|
color: _iconColor,
|
|
|
),
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
width: ScreenUtil().setWidth(1022 - _preItem - _marginLeft - _iconSize),
|
|
|
child: Text(
|
|
|
' :' +
|
|
|
getDate((listGetZpjl[index]['zpsj'] is int)
|
|
|
? listGetZpjl[index]['zpsj']
|
|
|
: int.parse(listGetZpjl[index]['zpsj'])),
|
|
|
textAlign: TextAlign.left,
|
|
|
overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//3.2、得到违章图片说明信息:车型、抓拍地点组件
|
|
|
Widget getWztpSmxx2(int index) {
|
|
|
return Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: <Widget>[
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
padding: EdgeInsets.only(left: ScreenUtil().setWidth(_marginLeft)),
|
|
|
width: ScreenUtil().setWidth(_preItem),
|
|
|
child: Text('车型:' + listGetZpjl[index]['clfl'], overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
|
|
|
Icon(
|
|
|
Icons.location_on_outlined,
|
|
|
size: ScreenUtil().setWidth(_iconSize),
|
|
|
color: _iconColor,
|
|
|
),
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
width: ScreenUtil().setWidth(1022 - _preItem - _marginLeft - _iconSize),
|
|
|
child: Text(' :' + listGetZpjl[index]['dwms'],
|
|
|
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis)),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//4、得到黑烟初审结果组件,在复审页面需要
|
|
|
Widget getHycsResult(int index) {
|
|
|
double _radio = 2.2;
|
|
|
return Column(
|
|
|
children: [
|
|
|
Container(
|
|
|
width: ScreenUtil().setWidth(1022),
|
|
|
height: ScreenUtil().setHeight(141),
|
|
|
decoration: BoxDecoration(
|
|
|
color: Colors.white,
|
|
|
borderRadius: BorderRadius.all(
|
|
|
Radius.circular(12),
|
|
|
),
|
|
|
),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
children: [
|
|
|
Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: <Widget>[
|
|
|
Container(
|
|
|
alignment: Alignment(-1, 0),
|
|
|
width: ScreenUtil().setWidth(1022 / _radio),
|
|
|
//height: ScreenUtil().setHeight(my_listTileHeight2),
|
|
|
child: Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: <Widget>[
|
|
|
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
|
|
|
Text('初审结果: ' + mapGetHycsShenheData['title'],
|
|
|
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
|
|
|
SizedBox(width: ScreenUtil().setWidth(6)),
|
|
|
Container(
|
|
|
width: ScreenUtil().setWidth(_iconSize),
|
|
|
height: ScreenUtil().setHeight(_iconSize),
|
|
|
decoration: BoxDecoration(
|
|
|
//color: Colors.white,
|
|
|
image: DecorationImage(
|
|
|
image: AssetImage(mapGetHycsShenheData['title'] == "黑烟车"
|
|
|
? "assets/images/hyc.png"
|
|
|
: "assets/images/fhyc.png"),
|
|
|
fit: BoxFit.contain),
|
|
|
),
|
|
|
alignment: Alignment.center,
|
|
|
//child:
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
SizedBox(width: ScreenUtil().setWidth(10)),
|
|
|
Expanded(
|
|
|
child: Text('意见: ' + mapGetHycsShenheData['shuoming'],
|
|
|
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: <Widget>[
|
|
|
Container(
|
|
|
alignment: Alignment(-1, 0),
|
|
|
width: ScreenUtil().setWidth(1022 / _radio),
|
|
|
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
|
|
|
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
|
|
|
Text('初审用户: ' + mapGetHycsShenheData['uname'],
|
|
|
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
|
|
|
]),
|
|
|
),
|
|
|
SizedBox(width: ScreenUtil().setWidth(10)),
|
|
|
Expanded(
|
|
|
child: Text('时间: ' + mapGetHycsShenheData['addtime'],
|
|
|
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// 167 50 3.34
|
|
|
Widget getLgmzs(int index, int lgmzs, {double width = 127, double height = 127}) {
|
|
|
int _rgb = (255 * (5 - lgmzs)) ~/ 5;
|
|
|
return Stack(
|
|
|
children: [
|
|
|
Container(
|
|
|
width: ScreenUtil().setWidth(width),
|
|
|
height: ScreenUtil().setHeight(height),
|
|
|
padding: EdgeInsets.only(
|
|
|
right: ScreenUtil().setWidth(6), left: ScreenUtil().setWidth(6), top: 0, bottom: 4),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
children: [
|
|
|
Text('$lgmzs级${lgmzs * 20}%', style: TextStyle(fontSize: 10)),
|
|
|
//SizedBox(height: 0),
|
|
|
Container(
|
|
|
width: ScreenUtil().setWidth(66),
|
|
|
height: ScreenUtil().setHeight(66),
|
|
|
decoration: BoxDecoration(
|
|
|
border: Border.all(color: Colors.grey),
|
|
|
color: Color.fromRGBO(_rgb, _rgb, _rgb, 1.0),
|
|
|
borderRadius: new BorderRadius.circular(0),
|
|
|
),
|
|
|
)
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
Positioned(
|
|
|
top: ScreenUtil().setHeight(4),
|
|
|
child: Container(
|
|
|
width: ScreenUtil().setWidth(width),
|
|
|
height: ScreenUtil().setHeight(height - 8),
|
|
|
padding: EdgeInsets.only(
|
|
|
right: ScreenUtil().setWidth(6), left: ScreenUtil().setWidth(6), top: 0, bottom: 0),
|
|
|
decoration: BoxDecoration(
|
|
|
border: Border.all(
|
|
|
color: (lgmzs == listGetZpjl[index]['lgmzs'])
|
|
|
? Colors.red
|
|
|
: Color.fromRGBO(244, 244, 244, 1),
|
|
|
width: 2),
|
|
|
//color: Colors.lightBlue,
|
|
|
borderRadius: new BorderRadius.circular(3.0),
|
|
|
),
|
|
|
),
|
|
|
)
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//1、得到格林曼黑度标准和视频播放按钮组件
|
|
|
Widget getHdAndPlay(int index) {
|
|
|
return Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
children: <Widget>[
|
|
|
getLgmzs(index, 0),
|
|
|
getLgmzs(index, 1),
|
|
|
getLgmzs(index, 2),
|
|
|
getLgmzs(index, 3),
|
|
|
getLgmzs(index, 4),
|
|
|
getLgmzs(index, 5, width: 153),
|
|
|
getIconBtnSizeX(
|
|
|
height: 104,
|
|
|
//getIconBtnSizeX 中已经使用ScreenUtil().setHeight(126),此处不能传 ScreenUtil().setHeight(126) ,否则严重错位
|
|
|
width: 168,
|
|
|
text: "视频",
|
|
|
textSize: 12,
|
|
|
circular: 4,
|
|
|
color: Color.fromRGBO(52, 157, 237, 1),
|
|
|
onTop: () async {
|
|
|
if (Playing) {
|
|
|
//禁止同时启动两次播放器
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
Playing = true; //禁止同时启动两次播放器
|
|
|
urlnew = getMediaUrl(listGetZpjl[index]['video_url']);
|
|
|
|
|
|
//获取视频地址失败
|
|
|
if (!isVideoUrl(urlnew)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
Navigator.of(_context).push(MaterialPageRoute(
|
|
|
builder: (context) => SuperPlayerPage(
|
|
|
loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
|
|
url: urlnew,
|
|
|
title:
|
|
|
'违章视频: ${listGetZpjl[index]["car_number"]}(抓拍${index + 1})\n${listGetZpjl[index]['dwms']}')));
|
|
|
|
|
|
// Navigator.of(_context).push(MaterialPageRoute(
|
|
|
// builder: (context) => PlayerProNew(
|
|
|
// loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
|
|
// url: urlnew,
|
|
|
// title:
|
|
|
// '违章视频: ${listGetZpjl[index]["car_number"]}(抓拍${index + 1})\n${listGetZpjl[index]['dwms']}')));
|
|
|
},
|
|
|
),
|
|
|
SizedBox(width: ScreenUtil().setWidth(15)),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//2、得到违章图片组件
|
|
|
Widget getWztp(int index) {
|
|
|
print('ratioList[index] = ${ratioList[index]}');
|
|
|
//ratioList[index] = 0.5714285714285714
|
|
|
return Stack(
|
|
|
children: [
|
|
|
Container(
|
|
|
width: ScreenUtil().setWidth(1022),
|
|
|
//height: ScreenUtil().setHeight(639),
|
|
|
height: ScreenUtil().setHeight(22 + 1022 * (9 / 16)), // 兴文县的违章图片无法获取,暂时调整
|
|
|
// height: ScreenUtil()
|
|
|
// .setHeight(22 + 1022 * (ratioList.isNotEmpty ? ratioList[index] : 9 / 16)),
|
|
|
decoration: BoxDecoration(
|
|
|
//color: Colors.white,
|
|
|
borderRadius: BorderRadius.all(
|
|
|
Radius.circular(12),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
Positioned(
|
|
|
//left: ScreenUtil().setWidth(25),
|
|
|
top: ScreenUtil().setHeight(11),
|
|
|
child: Container(
|
|
|
width: ScreenUtil().setWidth(1022),
|
|
|
// height:
|
|
|
// ScreenUtil().setHeight(1022 * (ratioList.isNotEmpty ? ratioList[index] : 9 / 16)),
|
|
|
height: ScreenUtil().setHeight(1022 * (9 / 16)),
|
|
|
// 兴文县的违章图片无法获取,暂时调整
|
|
|
child: getNetworkImage(getMediaUrl(listGetZpjl[index]['pic_url'])),
|
|
|
),
|
|
|
)
|
|
|
],
|
|
|
);
|
|
|
}
|
|
|
|
|
|
double _fontSize = 16;
|
|
|
double _listTileHeight = 30;
|
|
|
double _iconSize = 55;
|
|
|
Color _iconColor = Colors.blue;
|
|
|
double _textFieldHeight = 8;
|
|
|
double _preItem = 360;
|
|
|
double _marginLeft = 33;
|
|
|
double _marginVer = 6;
|
|
|
BuildContext _context;
|
|
|
|
|
|
double _marginVertical1 = 3;
|
|
|
double _marginVertical2 = 5;
|
|
|
|
|
|
//double _marginVertical3 = 6;
|
|
|
double _marginVertical3 = 3;
|
|
|
|
|
|
//double _marginVertical4 = 10;
|
|
|
double _marginVertical4 = 6;
|
|
|
double _marginVertical5 = 10;
|
|
|
double _marginVertical6 = 20;
|
|
|
|
|
|
Future getTopTabsMap() async {
|
|
|
//map遍历,清空数据
|
|
|
topTabs_map.forEach((key, value) {
|
|
|
topTabs_map[key].clear();
|
|
|
});
|
|
|
|
|
|
int len = listGetZpjl.length;
|
|
|
for (int index = 0; index < len; index++) {
|
|
|
//顶部Tab标题
|
|
|
//topTabs_map['tabs_list'].add(Tab(text: '抓拍ID:${listGetZpjl[index]['id']}'));
|
|
|
topTabs_map['tabs_list'].add(Tab(text: '抓拍 ${(index + 1).toString()}'));
|
|
|
//可供用户修改的车牌号码
|
|
|
topTabs_map['car_number_List'].add(listGetZpjl[index]['car_number']);
|
|
|
//可供用户修改的车牌颜色
|
|
|
topTabs_map['cpysText_List'].add(listGetZpjl[index]['cpys']);
|
|
|
//可供用户修改的审核意见
|
|
|
topTabs_map['auditShuoming_Controller_List'].add(
|
|
|
TextEditingController.fromValue(TextEditingValue(
|
|
|
text: ((widget.hyshlx == 'hyfh') ? '初审为' + mapGetHycsShenheData['title'] + '。复审' : '') +
|
|
|
hyc_shyj,
|
|
|
// 保持光标在最后
|
|
|
selection: TextSelection.fromPosition(
|
|
|
TextPosition(affinity: TextAffinity.downstream, offset: hyc_shyj.length)))),
|
|
|
);
|
|
|
//可供用户修改的审核结果
|
|
|
topTabs_map['auditTitle'].add(hyc_text);
|
|
|
//车牌号码、车牌颜色
|
|
|
topTabs_map['carNumberAndCpys_List']
|
|
|
.add(CarNumberAndCpysItems(index, topTabs_map['cpysText_List'][index]));
|
|
|
|
|
|
//Tab页面
|
|
|
topTabs_map['listView_List'].add(
|
|
|
//flutter开发弹起键盘出现Overflow问题的解决方法,我出现的情况,这三种方法就可以解决。
|
|
|
KeyboardAvoider(
|
|
|
autoScroll: true,
|
|
|
child: Container(
|
|
|
decoration: new BoxDecoration(
|
|
|
color: Color.fromRGBO(244, 244, 244, 1),
|
|
|
),
|
|
|
child: Column(
|
|
|
children: <Widget>[
|
|
|
//1、得到格林曼黑度标准和视频播放按钮组件
|
|
|
getHdAndPlay(index),
|
|
|
//2、得到违章图片组件
|
|
|
getWztp(index),
|
|
|
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
|
|
|
//3、得到违章图片说明信息组件
|
|
|
getWztpSmxx(index),
|
|
|
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
|
|
|
//4、得到黑烟初审结果组件,在复审页面需要
|
|
|
widget.hyshlx == 'hyfh' ? getHycsResult(index) : SizedBox.shrink(),
|
|
|
//为了用户在切换审核结果Radio时显示不同图片,必须将以下组件都移入到RadioListItems类中
|
|
|
//5-6、得到黑烟审核组件、审核确认组件
|
|
|
HyshGroup(
|
|
|
index: index,
|
|
|
hyshlx: hyshlx,
|
|
|
fontSize: _fontSize,
|
|
|
size: Size(_listTileHeight, _listTileHeight),
|
|
|
id: widget.id),
|
|
|
//为了用户在切换审核结果Radio时显示不同图片,必须将以下组件都移入到RadioListItems类中
|
|
|
// SizedBox(height: 6),
|
|
|
// Divider(height: 1.0, color: Colors.blue),
|
|
|
// SizedBox(height: 10),
|
|
|
// //9、得到审核确认组件
|
|
|
// getShqr(index),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//flutter开发弹起键盘出现Overflow问题的解决方法
|
|
|
// 方法1:
|
|
|
// //Scaffold节点下添加resizeToAvoidBottomPadding: false,这样页面就不会随着键盘弹起而滚动。
|
|
|
// Scaffold(
|
|
|
// resizeToAvoidBottomPadding: false,
|
|
|
// body: Column()
|
|
|
// );
|
|
|
// 方法2:
|
|
|
// //外层使用SingleChildScrollView包裹一层,这样页面回随着键盘弹起而向上滚动。
|
|
|
// SingleChildScrollView(
|
|
|
// child: Column(
|
|
|
// children: [
|
|
|
// TextField()
|
|
|
// ],
|
|
|
// ),
|
|
|
// ),
|
|
|
// 方法3:
|
|
|
// //使用第三方库:keyboard_avoider,并且设置autoScroll为true
|
|
|
// pubspec.yaml文件下添加依赖:
|
|
|
// dependencies:
|
|
|
// keyboard_avoider: ^0.1.2
|
|
|
// 外层使用KeyboardAvoider包裹,设置autoScroll为true
|
|
|
// KeyboardAvoider(
|
|
|
// autoScroll: true
|
|
|
// child: Column(
|
|
|
// children: [
|
|
|
// TextField()
|
|
|
// ],
|
|
|
// )
|
|
|
// ),
|
|
|
// 我出现的情况,这三种方法就可以解决。
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
print('topTabs_map[\'tabs_list\'].length = ${topTabs_map['tabs_list'].length}');
|
|
|
print('topTabs_map[\'listViewList\'].length = ${topTabs_map['listView_List'].length}');
|
|
|
|
|
|
return DefaultTabController(
|
|
|
//length: 8, //必须使用常数
|
|
|
//length: topTabs_map['tabs_list'].length,
|
|
|
length: topTabs_map['listView_List'].length,
|
|
|
//报错:Another exception was thrown: A RenderFlex overflowed by 99896 pixels on the bottom
|
|
|
//length: g_tabs, //报错: Another exception was thrown: RangeError (index): Invalid value: Valid value range is empty: 0
|
|
|
child: Scaffold(
|
|
|
//resizeToAvoidBottomPadding: false,
|
|
|
appBar: PreferredSize(
|
|
|
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
|
|
|
child: AppBar(
|
|
|
//backgroundColor: Colors.black12,
|
|
|
// title: Text("${mapHyshlx[hyshlx]['text']}详情$nums",
|
|
|
// style: TextStyle(
|
|
|
// fontSize: _fontSize, color: myCpys == '绿色' ? Colors.green : Colors.blue)),
|
|
|
|
|
|
// title: Text("${mapHyshlx[hyshlx]['text']}详情$nums",
|
|
|
// style: TextStyle(fontSize: _fontSize)),
|
|
|
|
|
|
automaticallyImplyLeading: false,
|
|
|
centerTitle: true,
|
|
|
//leading: Text(''),
|
|
|
titleSpacing: 0.0,
|
|
|
//设置title的左边距
|
|
|
flexibleSpace: Container(
|
|
|
//SizedBox(height: ScreenUtil().statusBarHeight), //显示顶部状态栏
|
|
|
// SizedBox(height: ScreenUtil().setHeight(10)), //显示顶部状态栏
|
|
|
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight), //留出顶部状态栏高度
|
|
|
child: Container(
|
|
|
//height: ScreenUtil().setHeight(173),
|
|
|
decoration: BoxDecoration(
|
|
|
gradient: LinearGradient(
|
|
|
begin: Alignment.centerLeft,
|
|
|
end: Alignment.centerRight,
|
|
|
colors: [
|
|
|
Color.fromRGBO(12, 186, 156, 1),
|
|
|
Color.fromRGBO(39, 127, 235, 1),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
// decoration: BoxDecoration(
|
|
|
// gradient: LinearGradient(colors: [
|
|
|
// Color(0xFF0018EB),
|
|
|
// Color(0xFF01C1D9),
|
|
|
// ], begin: Alignment.bottomCenter, end: Alignment.topCenter),
|
|
|
// ),
|
|
|
),
|
|
|
),
|
|
|
title: Padding(
|
|
|
padding: EdgeInsets.only(left: 0, right: 0),
|
|
|
child: Row(
|
|
|
//mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: [
|
|
|
//1.1、返回按钮
|
|
|
getIconAndTextButton(
|
|
|
iconColor: Colors.white,
|
|
|
iconData: Icons.chevron_left_outlined,
|
|
|
onPress: () {
|
|
|
Navigator.pop(context);
|
|
|
},
|
|
|
),
|
|
|
Expanded(
|
|
|
// child: Text("${mapHyshlx[hyshlx]['text']}",
|
|
|
// textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
|
|
|
child: Text("${mapHyshlx[hyshlx]['text']}详情$nums",
|
|
|
style: TextStyle(color: Colors.white, fontSize: 20),
|
|
|
textAlign: TextAlign.center,
|
|
|
overflow: TextOverflow.ellipsis),
|
|
|
),
|
|
|
SizedBox(width: 30),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
body: Scaffold(
|
|
|
appBar: PreferredSize(
|
|
|
preferredSize: Size.fromHeight(ScreenUtil().setHeight(99)), // 设置appBar高度
|
|
|
child: AppBar(
|
|
|
automaticallyImplyLeading: false,
|
|
|
centerTitle: true,
|
|
|
//leading: Text(''),
|
|
|
titleSpacing: 0.0,
|
|
|
//设置title的左边距
|
|
|
title: Padding(
|
|
|
padding: EdgeInsets.only(left: 0, right: 0),
|
|
|
),
|
|
|
//bottom必须要套PreferredSize,否则会报错:The argument type 'Container' can't be assigned to the parameter type 'PreferredSizeWidget'.
|
|
|
bottom: PreferredSize(
|
|
|
preferredSize: Size.fromHeight(30.0), // 设置TabBar高度
|
|
|
child: Container(
|
|
|
//color: Colors.blueAccent,
|
|
|
alignment: Alignment.centerLeft, //左对齐,有效
|
|
|
height: 30, // 设置TabBar高度
|
|
|
child: listGetZpjl.isNotEmpty
|
|
|
? TabBar(
|
|
|
//labelColor: Colors.blueAccent,
|
|
|
controller: _tabController,
|
|
|
//注意:用TabController实现顶部tab切换,必须添加该行
|
|
|
isScrollable: true,
|
|
|
//如果多个按钮的话可以自动左右移动
|
|
|
tabs: (topTabs_map['listView_List'].isNotEmpty)
|
|
|
? topTabs_map['tabs_list']
|
|
|
: [],
|
|
|
)
|
|
|
: PreferredSize(
|
|
|
preferredSize: Size.fromHeight(48.0),
|
|
|
child: Theme(
|
|
|
data: Theme.of(context).copyWith(accentColor: Colors.white),
|
|
|
child: Container(),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
//: Container(),
|
|
|
//type 'Container' is not a subtype of type 'PreferredSizeWidget'
|
|
|
body: listGetZpjl.isNotEmpty
|
|
|
? TabBarView(
|
|
|
controller: _tabController, //注意:用TabController实现顶部tab切换,必须添加该行
|
|
|
physics: NeverScrollableScrollPhysics(), //必须放到TabBarView下面,禁止TabBarView左右滑动-OK
|
|
|
children:
|
|
|
(topTabs_map['listView_List'].isNotEmpty) ? topTabs_map['listView_List'] : [],
|
|
|
)
|
|
|
: getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0), //显示加载中的圈圈
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
Widget getBtnSizeX({@required text, width = 70.0, height = 35.0, onPressedFun}) {
|
|
|
return Container(
|
|
|
color: Colors.white12, //onPressedFun为null时无效
|
|
|
width: width,
|
|
|
height: height,
|
|
|
child: RaisedButton(
|
|
|
padding: EdgeInsets.all(0),
|
|
|
textColor: Colors.black,
|
|
|
child: Text(text),
|
|
|
onPressed: onPressedFun,
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// App.Car_Yjxx.Workflow
|
|
|
// 审核数据
|
|
|
// 接口地址:http://49.235.208.235:9001/?s=App.Car_Yjxx.Workflow
|
|
|
// 接口文档
|
|
|
// 根据ID审核数据库中的一条纪录数据
|
|
|
//
|
|
|
// 接口参数
|
|
|
// 参数名字 类型 是否必须 默认值 其他 说明
|
|
|
// id 整型 必须 最小:1 ID
|
|
|
// workflow 整型 必须 2 最小:1 审核标记: 2=>初审通过 | 999=>复审通过 | 1000=>确认为非黑烟车
|
|
|
// shuoming 字符串 必须 最小:1 审核意见:如 黑烟超标,交由交警处罚
|
|
|
// uid 字符串 必须 最小:1 审核用户ID
|
|
|
// 返回结果
|
|
|
// 返回字段 类型 说明
|
|
|
// code 整型 更新的结果,1表示成功,0表示无更新,false表示失败
|
|
|
|
|
|
//违章信息审核
|
|
|
Future<bool> auditWzxxData() async {
|
|
|
var api = ServicePath.auditWzxxUrl;
|
|
|
print(api);
|
|
|
|
|
|
try {
|
|
|
print('开始处理网络请求...');
|
|
|
Response response;
|
|
|
Dio dio = Dio();
|
|
|
|
|
|
await copyMapUpdateWzxxData(mapGetHycsGetData);
|
|
|
response = await dio.post(api, data: mapUpdateWzxxData);
|
|
|
print('response = ${response.toString()}');
|
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
print('违章信息更新网络请求过程正常完成');
|
|
|
return true;
|
|
|
} else {
|
|
|
throw Exception('后端接口出现异常,请检测代码和服务器情况.........');
|
|
|
}
|
|
|
} catch (e) {
|
|
|
print('网络请求过程异常e:${e}');
|
|
|
Fluttertoast.showToast(
|
|
|
msg: 'ERROR:======>${e}',
|
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
|
gravity: ToastGravity.CENTER,
|
|
|
);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
}
|