hyzp_ybqx-Commit001:代码刚转换好,编译通过

This commit is contained in:
WinUser01
2021-12-09 20:24:36 +08:00
commit 8c74b14e5c
800 changed files with 66912 additions and 0 deletions
+514
View File
@@ -0,0 +1,514 @@
import 'package:flutter/material.dart';
import 'package:flutter_bmfbase/BaiduMap/bmfmap_base.dart';
import 'package:flutter_bmfmap/BaiduMap/bmfmap_map.dart';
import 'package:flutter_screenutil/screen_util.dart';
import 'package:hyzp_ybqx/components/commonFun.dart';
import 'package:hyzp_ybqx/components/hyxx_data_handle.dart';
import '../../../components/dioFun.dart';
import 'dwInfoDialog.dart';
import 'dwInfo_data.dart';
class BasicMap extends StatefulWidget {
BasicMap({this.hyshlx = 'dwdt', this.title = "点位地图"});
String hyshlx;
String title;
@override
_BasicMapState createState() => _BasicMapState();
}
class _BasicMapState extends State<BasicMap> {
Size screenSize;
BMFMapOptions mapOptions;
BMFMapController myMapController;
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void initState() {
super.initState();
mapOptions = BMFMapOptions(
//center: BMFCoordinate(39.965, 116.404),//北京市
//30 116.395645038,39.9299857781 北京-北京市
//center: BMFCoordinate(34.263161, 108.948024), //西安市
/// 设置地图显示中心点坐标,必须是百度官方发布的百度地图-城市中心点坐标
/// 为宜宾市白塔山: BMFCoordinate(104.644079, 28.77914)
//center: BMFCoordinate(104.644079, 28.77914), //宜宾市白塔山,无效,经纬度搞反了
//52 104.633019062,28.7696747963 四川省-宜宾市
///Flutter百度地图采坑注意:
// BMFCoordinate(this.latitude, this.longitude);
// BMFCoordinate 构造方法参数是纬度在前、经度在后,latitude 纬度,longitude 经度
// 百度官方发布的城市中心点坐标是经度在前、纬度在后,必须对调才行,否则无法正确显示指定城市的地图
// 比如://52 104.633019062,28.7696747963 四川省-宜宾市
// 必须将经纬度对调才行:center: BMFCoordinate(28.7696747963, 104.633019062), //四川省-宜宾市
//center: BMFCoordinate(28.7696747963, 104.633019062), //四川省-宜宾市
center: BMFCoordinate(28.77914, 104.644079),
//宜宾市白塔山
//宜宾市白塔山
showMapPoi: _showMapPoi,
//设定地图是否显示底图poi标注(不包含室内图标注),默认true
zoomLevel: g_zoomLevel,
maxZoomLevel: 16,
minZoomLevel: 12,
mapPadding: BMFEdgeInsets(left: 30, top: 0, right: 30, bottom: 0),
//showMapScaleBar: true,
);
iPage = 0;
listDwspGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList(theHyshlx: widget.hyshlx, bShowToast: false).then((value) async {
//mapHyshlx[hyshlx]['api'];
listDwspGetList2 = value;
listDwinfoGetList2 = value;
//try_setState();
//按照用户选择的_selectedValue、_descending对listDwspGetList2进行排序,并延时更新
// int len = listDwspGetList2.length;
// for (int i = 0; i < len; i++) {
// getDwspUrl(index: listDwspGetList2[i]['id']).then((value) {
// listDwspGetList2[i]['dwsp_ok'] = true;
// if (value == '' || value == null) {
// listDwspGetList2[i]['dwsp_ok'] = false;
// }
// setState(() {});
// });
// }
});
//为播放点位视频读取数据
//在 Page1_Works 页面,获取 startGetStatisData() 时,便已经获取了 listDwinfoGetList2
// ///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
// getPageList(theHyshlx: 'dwxx', bShowToast: false).then((value) async {
// //mapHyshlx[hyshlx]['api'];
// listDwspGetList2 = value;
//
// //按_selectedValue排序,升序
// listDwspGetList2
// .sort((a, b) => (a[mapWzxxDataText['点位编号']]).compareTo(b[mapWzxxDataText['点位编号']]));
// });
}
//设定地图是否显示底图poi标注(不包含室内图标注),默认true
bool _showMapPoi = true;
/// 创建完成回调
void onBMFMapCreated(BMFMapController controller) async {
myMapController = controller;
/// 设置地图状态改变完成后回调接口
myMapController?.setMapStatusDidChangedCallback(callback: () {
myMapController.getZoomLevel().then((zoomLevel) {
print('Current zoomLevel = $zoomLevel');
g_zoomLevel = zoomLevel; //缩放倍数
getListBMFMarker().then((value) async {
///先清除地图上的所有Marker
await myMapController?.removeMarkers(g_listBMFMarker);
///批量添加定位标记
await myMapController?.addMarkers(g_listBMFMarker);
///批量添加文字标记,作为定位标记的说明文字
for (var text in g_listBMFText) {
//text.setMethodChannel(MethodChannel());
await myMapController?.addText(text);
}
//加在此处无效
//点击Marker时会回调BaiduMap.OnMarkerClickListener,监听器的实现方式示例如下:
/// 地图marker点击回调
//myMapController?.setMapClickedMarkerCallback(callback: _markerCallback);
});
setState(() {});
});
});
/// 地图加载回调
myMapController?.setMapDidLoadCallback(callback: () {
print('mapDidLoad-地图加载完成');
});
///批量添加定位标记
getListBMFMarker().then((value) {
myMapController?.addMarkers(g_listBMFMarker);
///批量添加文字标记,作为定位标记的说明文字
for (var text in g_listBMFText) {
myMapController?.addText(text);
}
///1、底图标注 点击回调:
// 点中底图标注后会回调此接口
myMapController?.setMapOnClickedMapPoiCallback(callback: (BMFMapPoi mapPoi) async {
print('mapPoi = ${mapPoi.toMap().toString()}');
myMapController.getZoomLevel().then((value) {
g_zoomLevel = value;
print('myMapController.getZoomLevel() = ${value.toString()}');
});
//I/flutter (11895): mapPoi = {text: 森林小区, pt: {latitude: 28.765632464539106, longitude: 104.60481101089357}, uid: ea4cae6307501c5f4d2fdfe9}
onMarkerClicked(mapPoi.pt);
});
///2、底图空白处 点击回调
// 点中底图空白处会回调此接口
/// coordinate 经纬度
myMapController?.setMapOnClickedMapBlankCallback(callback: (BMFCoordinate coordinate) {
print('点击底图空白处响应:coordinate = ${coordinate.toMap().toString()}');
myMapController.getZoomLevel().then((value) {
g_zoomLevel = value;
print('myMapController.getZoomLevel() = ${value.toString()}');
});
onMarkerClicked(coordinate);
});
//3、Marker 点击响应,点击文本标签没反应,加在此处有效
//点击Marker时会回调BaiduMap.OnMarkerClickListener,监听器的实现方式示例如下:
/// 地图marker点击回调
myMapController?.setMapClickedMarkerCallback(callback: (String id, dynamic extra) async {
myMapController.getZoomLevel().then((value) {
g_zoomLevel = value;
print('myMapController.getZoomLevel() = ${value.toString()}');
});
print('点击 Marker 标签响应:id = ${id}');
//百度地图的脑残设计,需要在添加BMFMarker时自己保存ID
//g_listBMFMarkerIDmap.add({marker.getId(): listDwinfo[i]["id"]});
print('Marker的 标签响应:id = ${listDwinfoGetList2[g_map_BMFMarkerID_dwIndex[id]]["dwmc"]}');
_markerCallback(id, 'test'); //响应用户点击
});
});
//批量添加定位标记
}
Map mapBMFTextCoordinateList = {};
//1、江北振兴大道 估算坐标区域
// 左上角 coordinate = {latitude: 28.807221307340154, longitude: 104.60667948635371}
// 右下角 coordinate = {latitude: 28.805069070677582, longitude: 104.62110627283919}
// listMarkerCoordinate是包含13个Map点位标记的List,每个Map元素包括4个子元素,
// 分别是左上角坐标(纬度 latitude,经度 longitude)、右下角坐标(纬度 latitude,经度 longitude)
List listMarkerCoordinate1 = [
{
'topLatitude': 28.807221307340154,
'leftLongitude': 104.60667948635371,
'bottomLatitude': 28.805069070677582,
'rightLongitude': 104.62110627283919
}
];
//12、大麦坝
//左上角 coordinate = coordinate = {latitude: 28.8044360513459, longitude: 104.63110441316194}
//右下角 coordinate = coordinate = {latitude: 28.803415299489192, longitude: 104.63598221207951}
// listMarkerCoordinate是包含13个Map点位标记的List,每个Map元素包括4个子元素,
// 分别是左上角坐标(纬度 latitude,经度 longitude)、右下角坐标(纬度 latitude,经度 longitude)
//15倍放大时设置,地图放到18倍时,点击没有问题,
//缩小到13倍时,不行了
//15倍放大
//左下角coordinate = {latitude: 28.79913436190729, longitude: 104.66847392236468}
//左上角coordinate = {latitude: 28.806612039019615, longitude: 104.62731356391107}
List listMarkerCoordinate = [
{
'topLatitude': 28.80778309701711,
'leftLongitude': 104.63028695514814,
'bottomLatitude': 28.79801859852449,
'rightLongitude': 104.66974951618843
}
];
//以13倍放大时的数据设置
//左下角coordinate = {latitude: 28.80399293550177, longitude: 104.63028695514814}
//左上角coordinate = {latitude: 28.79801859852449, longitude: 104.66974951618843}
// 中国在世界地图上的经纬度范围? // 2019-04-14 · 把复杂的事情简单说给你听
// top 北起黑龙江省漠河以北的黑龙江主航道的中心线 北纬 53°31′
// bottom 南达南海南沙群岛的曾母内暗沙 北纬 4°15′
// left 西起新容疆维吾尔自治区乌恰县以西的帕米尔高原 东经 73°
// right 东至黑龙江省抚远县境内的黑龙江与乌苏里江汇合处 东经 135°。
//
// 中国位于地球的东半球北半部、亚欧大陆的东南部、亚洲的东部和中部、太平洋的西岸。
int i = 0;
//纬度 latitude,经度 longitude
Future onMarkerClicked(BMFCoordinate coordinate) {
//double scale = g_zoomLevel / 15;
if (listMarkerCoordinate[i]['topLatitude'] > coordinate.latitude &&
coordinate.latitude > listMarkerCoordinate[i]['bottomLatitude'] &&
listMarkerCoordinate[i]['rightLongitude'] > coordinate.longitude &&
coordinate.longitude > listMarkerCoordinate[i]['leftLongitude']) {
_markerCallback('123', 'test');
} //响应用户点击
}
bool isDoing = false;
Future _markerCallback(String id, dynamic extra) async {
if (isDoing) {
print('正在处理中...,不能重复进入');
return;
}
print('开始处理');
print('mapClickedMarker--\n marker = $id');
//已经能够弹出Flutter对话框。但只有点击 Marker 标签有反应,点击文本标签没反应。
//百度地图的脑残设计,需要在添加BMFMarker时自己保存ID
//g_listBMFMarkerIDmap.add({marker.getId(): listDwinfo[i]["id"]});
int dwIndex = g_map_BMFMarkerID_dwIndex[id];
print('Marker的 标签响应:id = ${listDwinfoGetList2[dwIndex]["dwmc"]}');
getStatisData(statisType: 'zptj', ip: listDwinfoGetList2[dwIndex]['dwip'])
.then((mapStatisData) async {
String title =
listDwinfoGetList2[dwIndex]["id"].toString() + '、' + listDwinfoGetList2[dwIndex]["dwmc"];
List listCoordinate = listDwinfoGetList2[dwIndex]["dwzb"].trim().split('|');
String content = listDwinfoGetList2[dwIndex]["dwms"] +
'。\n经度:${listCoordinate[0]}\n纬度:${listCoordinate[1]}' +
'\n今日抓拍:${mapStatisData['today']['total']}, 累计抓拍:${mapStatisData['all']}' +
'\n运行状态:${listDwinfoGetList2[dwIndex]['dwzt']}';
await Navigator.of(context)
.push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
dwInfoDialog(id: id, dwIndex: dwIndex, title: title, content: content),
),
)
.then((value) async {
print('value = $value');
if (value) {
print('用户已确认,开始处理推送交警!');
//return;
} else {
print('用户取消了推送交警操作');
}
});
setState(() {
// _markerID = id;
// _action = "点击";
});
isDoing = false;
});
}
double _widthBtn = 45;
double _heightBtn = 45;
double _edge = 16;
@override
Widget build(BuildContext context) {
screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(widget.title + '(${g_zoomLevel}倍)',
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 10),
],
),
actions: <Widget>[
Row(
children: [
//SizedBox(width: ScreenUtil().setWidth(45)),
InkWell(
onTap: () {
//Navigator.pushNamed(context, '/registerFirst');
this.setState(() {
_showMapPoi = !_showMapPoi;
myMapController?.updateMapOptions(BMFMapOptions(showMapPoi: _showMapPoi));
});
},
child: Container(
alignment: Alignment(0, 0),
//width: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('标注:', style: TextStyle(fontSize: 20, color: Colors.white)),
Container(
alignment: Alignment(0, 0),
height: 25,
width: 25,
padding: EdgeInsets.only(top: ScreenUtil().setHeight(6)),
child: _showMapPoi
? Icon(Icons.check_box, color: Colors.white)
: Icon(Icons.check_box_outline_blank, color: Colors.white),
),
SizedBox(width: ScreenUtil().setWidth(65)),
],
),
),
),
],
),
],
),
),
body: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Container(
height: screenSize.height,
width: screenSize.width,
child: BMFMapWidget(
onBMFMapCreated: (controller) {
onBMFMapCreated(controller);
},
mapOptions: mapOptions,
),
),
),
Align(
alignment: Alignment(1, 1),
child: Padding(
padding: EdgeInsets.only(bottom: 5, right: _edge),
child: Container(
width: _widthBtn,
height: _heightBtn * 2 + 3,
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(2.0)),
border: new Border.all(width: 1, color: Colors.blue),
),
child: Column(
children: [
Container(
width: _widthBtn,
height: _heightBtn,
//color: Colors.white,
child: InkWell(
// child: Icon(Icons.my_location_outlined, color: Colors.black45),
child: Icon(Icons.add, color: g_zoomLevel < 16 ? Colors.blue : Colors.grey),
onTap: g_zoomLevel < 16
? () {
//放大按钮,缩放限制12-16
if (g_zoomLevel < 16) {
g_zoomLevel++;
myMapController
?.updateMapOptions(BMFMapOptions(zoomLevel: g_zoomLevel));
}
}
: null,
),
),
Divider(height: 1.0, color: Colors.blue),
Container(
width: _widthBtn,
height: _heightBtn,
//color: Colors.white,
child: InkWell(
// child: Icon(Icons.my_location_outlined, color: Colors.black45),
child: Icon(Icons.horizontal_rule,
color: g_zoomLevel > 12 ? Colors.blue : Colors.grey),
onTap: g_zoomLevel > 12
? () {
//缩小按钮,缩放限制12-16
g_zoomLevel--;
myMapController
?.updateMapOptions(BMFMapOptions(zoomLevel: g_zoomLevel));
}
: null,
),
),
],
),
),
),
),
Align(
alignment: Alignment(-1, 1),
child: Padding(
padding: EdgeInsets.only(bottom: 50, left: _edge),
child: Container(
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(2.0)),
border: new Border.all(width: 1, color: Colors.blue),
),
width: _widthBtn,
height: _heightBtn,
//color: Colors.white,
child: InkWell(
// child: Icon(Icons.my_location_outlined, color: Colors.black45),
// 没有
child: Icon(Icons.radio_button_checked_rounded,
color: g_zoomLevel == 14 ? Colors.grey : Colors.blue),
onTap: () {
g_zoomLevel = 14;
//还原按钮,重新设置中心位置、缩放级别
//myMapController.setCenterCoordinate(coordinate, animated);
//没有myMapController.getCenterCoordinate,无法简单地获取当前中心坐标;
myMapController?.updateMapOptions(
BMFMapOptions(center: BMFCoordinate(28.77914, 104.644079)));
myMapController?.updateMapOptions(BMFMapOptions(zoomLevel: g_zoomLevel));
},
),
),
),
),
],
),
);
}
}
+118
View File
@@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:hyzp_ybqx/components/dioFun.dart';
//import 'package:hyzp_ybqx/widget/player_pro.dart';
import '../../../components/commonFun.dart';
//确认对话框
class dwInfoDialog extends Dialog {
dwInfoDialog({@required this.id, this.title = "", @required this.dwIndex, this.content});
int dwIndex;
String id;
String title;
String content;
bool ret = false;
@override
Widget build(BuildContext context) {
Size mediaSize = MediaQuery.of(context).size;
return WillPopScope(
child: Material(
type: MaterialType.transparency,
child: Container(
padding: EdgeInsets.only(top: 116),
alignment: Alignment(0, -1),
color: Colors.black12,
child: Container(
// height: 260,
// width: 300,
height: mediaSize.height * 0.51,
width: mediaSize.width * 0.95,
//color: Colors.white, //Cannot provide both a color and a decoration
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.blue, width: 2.0),
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Text(
"${this.title}",
style: TextStyle(
fontSize: 20.0,
),
),
),
Align(
alignment: Alignment.centerRight,
child: InkWell(
child: Icon(Icons.close),
onTap: () {
getingDwVideo = false;
Navigator.pop(context, ret);
},
),
)
],
),
),
Divider(color: Colors.blue),
Container(
padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
width: double.infinity,
height: mediaSize.height * 0.28,
child: SingleChildScrollView(
child: Text(content, style: TextStyle(fontSize: 18.0, color: Colors.blue)),
),
),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
onPressed: () {
ret = true;
//getDwspUrl(index: dwIndex, context: context);
getDwspUrlNew(indexRecord: dwIndex, context: context);
},
child: Text("视频"),
),
RaisedButton(
onPressed: () async {
ret = true;
getingDwVideo = false;
Navigator.pop(context, ret); //关闭弹框,返回sRet
},
child: Text("确认"),
),
RaisedButton(
child: Text("取消"),
onPressed: () async {
getingDwVideo = false;
Navigator.pop(context, ret); //关闭弹框,返回sRet
},
)
],
),
],
),
),
),
),
onWillPop: () {
// 屏蔽点击返回键的操作
getingDwVideo = false;
Navigator.pop(context, ret);
},
);
}
}
+120
View File
@@ -0,0 +1,120 @@
import 'package:flutter/material.dart';
import 'package:flutter_bmfbase/BaiduMap/bmfmap_base.dart';
import 'package:flutter_bmfmap/BaiduMap/bmfmap_map.dart';
import 'package:hyzp_ybqx/components/hyxx_data_handle.dart';
///批量添加定位标记
bool enable = true;
bool dragable = true;
int g_zoomLevel = 14; //缩放倍数
///批量添加定位标记
List<BMFMarker> g_listBMFMarker = [];
Map g_map_BMFMarkerID_dwIndex = {};
List<BMFText> g_listBMFText = [];
//https://www.cnblogs.com/ybmj/p/14408263.html
//百度地图的脑残设计,附上代码,为后来的码农们...
Future getListBMFMarker({List listDwinfo}) async {
if (null == listDwinfo) {
listDwinfo = listDwinfoGetList2;
}
//double _scale = 9900 / 10000; //自己控制off_latitude、off_longitude效果不好
// BMFMarker marker1 = BMFMarker(
// position: BMFCoordinate(28.807061, 104.607091),
// title: '1、江北振兴大道',
// subtitle: 'test',
// identifier: 'flutter_marker',
// icon: 'assets/images/location.png',
// enabled: enable,
// draggable: dragable);
int len = listDwinfo.length;
for (int i = 0; i < len; i++) {
BMFMarker marker = BMFMarker(
position: getBMFCoordinate(listDwinfo[i]["dwzb"]),
title: '${listDwinfo[i]["id"].toString()}、${listDwinfo[i]["dwmc"]}',
subtitle: 'test',
identifier: '${listDwinfo[i]["id"].toString()}、${listDwinfo[i]["dwmc"]}',
icon: 'assets/images/location.png',
/// 默认情况下, annotation view的中心位于annotation的坐标位置,
/// 可以设置centerOffset改变view的位置,正的偏移使view朝右下方移动,负的朝左上方,单位是像素
/// 目前Android只支持Y轴设置偏移量对应SDK的 yOffset(int yOffset) 方法
/// 添加标记 BMFMarker 百度官方有 centerOffset 偏移参数,
/// 文本标签 BMFText 官方没有 centerOffset 偏移参数,我取消了 BMFMarker 的偏移。你看这样行吗?
/// 按公司要求,为更准确定位,取消 BMFMarker 的偏移
centerOffset: BMFPoint(0, 0),
//标记中心偏移
enabled: enable,
draggable: dragable);
// 百度地图的脑残设计,用Flutter添加多个BMFMarker时,必须在添加BMFMarker时自己保存ID,
// 否则响应点击时无法确定用户点击的是哪个定位标注
// 代码不会自动返回,也没有任何文档说明,是花了一天时间搜索网络无果,是自己翻江倒海摸索出来的
// 下一句是关键代码,将添加的每个BMFMarker的id保存到一个map中,
// 这样在用setMapClickedMarkerCallback添加BMFMarker的通用响应函数中,便可以根据id号来判断用户点击的是哪一个定位标注
g_map_BMFMarkerID_dwIndex[marker.getId()] = i;
g_listBMFMarker.add(marker);
g_listBMFText.add(BMFText(
text: '${listDwinfo[i]["id"].toString()}、${listDwinfo[i]["dwmc"]}',
//纬度偏移-上下 off_latitude, 经度偏移-左右 off_longitude
//已经在zoomLevel = 15时调整好定位标记与文本标记的相对位置
// ,当地图缩放时,会发生位置变化,必须使用 Provider 或者 EventBus 进行跟踪更新
//https://time.geekbang.org/column/article/131890
//老师,provider、eventBus的用途有啥区别吗,都可以做状态的通知
// 作者回复: Provider 主要是用来做数据读写共享;event_bus主要是用来做数据状态通知、实现组件间单向数据传递。
//如果我们的应用足够简单,数据流动的方向和顺序是清晰的,我们只需要将数据映射成视图就可以了。
// 作为声明式的框架,Flutter 可以自动处理数据到渲染的全过程,通常并不需要 Provider 状态管理。
// position: getBMFCoordinate(listDwinfo[i]["dwzb"],
// off_latitude: -0.0002 * g_zoomLevel * _scale,
// off_longitude: -0.00009 * g_zoomLevel * _scale),
position: getBMFCoordinate(listDwinfo[i]["dwzb"]),
//自己控制off_latitude、off_longitude效果不好
bgColor: Colors.yellow,
fontColor: Colors.black,
fontSize: 35,
// typeFace:
// BMFTypeFace(familyName: BMFFamilyName.sMonospace, textStype: BMFTextStyle.BOLD_ITALIC),
typeFace: BMFTypeFace(familyName: BMFFamilyName.sMonospace, textStype: BMFTextStyle.BOLD),
alignY: BMFVerticalAlign.ALIGN_TOP,
alignX: BMFHorizontalAlign.ALIGN_LEFT,
rotate: 0.0,
zIndex: 99));
}
}
//文字覆盖物
// 文字(Text)在地图上也是一种覆盖物,由BMFText类定义,示例代码如下:
//
// /// text经纬度信息
// BMFCoordinate position = new BMFCoordinate(39.73235, 116.350338);
//
// /// 构造text
// BMFText bmfText = BMFText(
// text: 'hello world',
// position: position,
// bgColor: Colors.blue,
// fontColor: Colors.red,
// fontSize: 40,
// typeFace: BMFTypeFace( familyName: BMFFamilyName.sMonospace,
// textStype: BMFTextStyle.BOLD_ITALIC),
// alignY: BMFVerticalAlign.ALIGN_TOP,
// alignX: BMFHorizontalAlign.ALIGN_LEFT,
// rotate: 30.0);
//
// /// 添加text
// myMapController.addText(bmfText);
//从"dwzb": "104.607091|28.807061",得到BMFCoordinate(28.807061, 104.607091)
//纬度偏移-上下 off_latitude, 经度偏移-左右 off_longitude
//自己控制off_latitude、off_longitude效果不好
BMFCoordinate getBMFCoordinate(String dwzb, {double off_latitude = 0, double off_longitude = 0}) {
off_latitude = 0; //取消偏移
off_longitude = 0; //取消偏移
List _listCoordinateItem = dwzb.trim().split('|');
return BMFCoordinate(double.parse(_listCoordinateItem[1]) - off_latitude,
double.parse(_listCoordinateItem[0]) - off_longitude);
}
+567
View File
@@ -0,0 +1,567 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hyzp_ybqx/widget/my_delay_toast.dart';
import '../../../components/commonFun.dart';
//import 'package:hyzp_ybqx/widget/player_pro.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../services/EventBus.dart';
//dwsp是本项目中“点位视频”的统一缩写
class DwspGetList extends StatefulWidget {
//hyshlx为黑烟审核类型,处理dwsp信息。mapHyshlx[hyshlx]获取为各种类型的设置数据
DwspGetList({this.hyshlx = 'dwxx', Key key}) : super(key: key);
String hyshlx;
_DwspPageState createState() => _DwspPageState();
}
class _DwspPageState extends State<DwspGetList> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void dispose() {
_controller.dispose(); //销毁控制器
super.dispose();
}
@override
void initState() {
hyshlx = widget.hyshlx;
iPage = 0;
listDwspGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList(theHyshlx: hyshlx, bShowToast: false).then((value) async {
//mapHyshlx[hyshlx]['api'];
listDwspGetList2 = value;
//按照用户选择的_selectedValue、_descending对listDwspGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
listDwinfoGetList2 = listDwspGetList2;
// int len = listDwspGetList2.length;
// for (int i = 0; i < len; i++) {
// getDwspUrl(index: listDwspGetList2[i]['id']).then((value) {
// listDwspGetList2[i]['dwsp_ok'] = true;
// if (value == '' || value == null) {
// listDwspGetList2[i]['dwsp_ok'] = false;
// }
// setState(() {});
// });
// }
});
// ///从接口 mapHyshlx[theHyshlx]['api'] 获取指定类型第 page 页的列表数据,返回 list
// ///获取点位信息数据
// listDwinfoGetList2.clear();
// getThePageList(theHyshlx: 'dwxx').then((value) {
// listDwinfoGetList2 = value;
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// });
//监听点位视频信息数据更新事件
eventBus.on<DwspUpdateEvent>().listen((event) async {
print(event.str);
try_setState();
});
super.initState();
}
//点位信息数据
//{
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆",
// "dwzt": "正常"
//},
// Widget getDropdownButton() {
// //DropdownMenuItem项目文本list
// List<String> itemList = [
// '主键ID',
// '点位IP',
// '点位名称',
// '点位编号',
// '点位信息',
// '点位坐标',
// '点位描述',
// '点位状态',
// ];
Widget _getMonitorImage(String _image, int indexRecord,
{double width = 140, double height = 140}) {
return Container(
margin: EdgeInsets.only(),
width: ScreenUtil().setWidth(width),
height: ScreenUtil().setHeight(height),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(
_image,
fit: BoxFit.cover,
//color: listDwspGetList2[indexRecord]['dwsp_ok'] ? null : Theme.of(context).disabledColor
),
);
}
Widget _getListTile(BuildContext context, int indexRecord) {
List listCoordinate = listDwspGetList2[indexRecord]["dwzb"].trim().split('|');
return Column(
children: <Widget>[
Container(
decoration: getingIndex == indexRecord
? BoxDecoration(
border: Border.all(width: 3, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(5.0)),
)
: null,
child: ListTile(
//leading: new Icon(Icons.phone),
contentPadding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 0),
title: Text(
"${listDwspGetList2[indexRecord]['dwbh'].toString()}. ${listDwspGetList2[indexRecord]['dwmc']}",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
// subtitle: Text(
// 'dwIP:${listDwspGetList2[indexRecord]['dwip']},${listDwspGetList2[indexRecord]['dwzt']}',
// style: TextStyle(fontSize: 10)),
trailing: Container(
width: 200,
child: Row(
children: [
_getMonitorImage('assets/images/monitor.png', indexRecord),
SizedBox(width: 20),
Container(
width: 120,
child: Text(
'${listDwspGetList2[indexRecord]['dwms']}' +
', 经纬度:${listCoordinate[0]}、${listCoordinate[1]}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 14),
),
)
],
),
),
enabled: true,
onTap: () async {
// int ret = await Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => DwspContent(
// title: '点位视频信息详情',
// index: indexRecord,
// hyshlx: widget.hyshlx,
// ),
// ),
// );
//{
// "ret": 200,
// "data": {
// "id": 13,
// "dwip": "172.16.3.13",
// "dwmc": "外江路",
// "dwbh": 13,
// "dwinfo": "外江路往高铁站方向",
// "dwzb": "104.623547|28.74798",
// "dwms": "外江路往高铁站方向,识别中坝大桥往高铁站排放黑烟车辆",
// "dwzt": "正常",
// "video12": null,
// "video13": null,
// "video14": null,
// "video15": null,
// "video16": "/rtp/gb_play_34020000001320013016_34020000001320013016/hls.m3u8",
// "play_urlhead": "http://125.64.218.67:9903"
// },
// "msg": ""
// }
//getDwspUrl(index: indexRecord, context: context);
getDwspUrlNew(indexRecord: indexRecord, context: context);
//@山不在高水不在深 我用PC播放这个地址也等了45秒才开始,
// http://125.64.218.67:9903/rtp/gb_play_34020000001320013016_34020000001320013016/hls.m3u8
// getDwspUrl(index: indexRecord + 1).then((url) {
// print('index = ${(indexRecord + 1).toString()}, url = $url');
// urlnew = url;
//
// //获取视频地址失败
// if (!isVideoUrl(urlnew)) {
// return;
// }
//
// var ret = Navigator.of(context).push(MaterialPageRoute(
// builder: (context) => PlayerPro(
// url: urlnew,
// title:
// '点位视频\n${(indexRecord + 1)}、${listDwinfoGetList2[indexRecord]['dwmc']}',
// //initVideoSize: Size(704.0, 576.0), //16比13
// //initVideoSize: Size(16, 9),
// )));
// print('ret = $ret');
// });
},
),
),
Divider(height: 1.0),
],
);
}
ScrollController _controller = ScrollController(); //ListView控制器
bool isLoading = false; //正在处理下载数据、跳转到首项、跳转到尾项等操作
int firstIndex = 0; //ListView当前显示页面首项0基序号
int lastIndex = 0; //ListView当前显示页面末项0基序号
int itemOnPage = 8; //估计一屏显示的项目数量
Widget getIconButton({IconData iconData, var onPressed, double iconSize = 22}) {
return SizedBox(
height: iconSize,
width: iconSize + 10,
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: Icon(iconData, size: iconSize),
onPressed: onPressed,
),
);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
getingDwVideo = false;
Navigator.pop(context);
},
),
Expanded(
child: Text("${mapHyshlx[hyshlx]['text']}",
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 50),
],
),
),
),
),
body: (0 == listDwspGetList2.length)
? getMoreWidget(color: Colors.black38)
: ListView.custom(
//itemExtent: 75.0, //列表项高度
controller: _controller,
cacheExtent: 1.0, // 只有设置了1.0 才能够准确的标记 position 位置
childrenDelegate: MyChildrenDelegate(
_getListTile,
childCount: listDwspGetList2.length,
),
),
),
onWillPop: () {
// 屏蔽点击返回键的操作
getingDwVideo = false;
Navigator.pop(context);
},
);
}
//DropdownButton需要设置初始值的时候,初始值必须是显示列表里面的值,否则会导致弹出框异常。
// 比如说:你的DropdownButton的items属性使用的是list这个列表里面的值,那么你的初始值应该在list[index]里面取,要不就会报错。
//
// There should be exactly one item with [DropdownButton]'s value: 0.0.
// Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
// 'package:flutter/src/material/dropdown.dart':
// Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
// items.where((DropdownMenuItem<T> item) {
// return item.value == value;
// }).length == 1'
String _selectedValue = '点位编号';
bool _descending = false; //默认升序排列
Widget _getImage(String _image) {
return Container(
margin: EdgeInsets.only(),
height: ScreenUtil().setWidth(38),
width: ScreenUtil().setWidth(38),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(_image,
fit: BoxFit.cover, color: isLoading ? Theme.of(context).disabledColor : null));
}
//按照用户选择的_selectedValue、_descending对listDwspGetList2进行排序,并延时更新
Future _listSort({bool bShowToast = false}) {
if (!isLoading && listDwspGetList2.length > 0) {
isLoading = true;
try_setState();
switch (_selectedValue) {
default:
if (_descending) {
//按_selectedValue排序,降序
listDwspGetList2.sort((a, b) =>
(b[mapWzxxDataText[_selectedValue]]).compareTo(a[mapWzxxDataText[_selectedValue]]));
} else {
//按_selectedValue排序,升序
listDwspGetList2.sort((a, b) =>
(a[mapWzxxDataText[_selectedValue]]).compareTo(b[mapWzxxDataText[_selectedValue]]));
}
break;
}
Future.delayed(const Duration(milliseconds: 1000), () {
if (bShowToast) {
Fluttertoast.showToast(
msg: '按“${_selectedValue}”${_descending ? '降序' : '升序'}排列完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
}
isLoading = false;
try_setState(); //避免如下异常报错
});
}
}
Widget getDropdownButtonItemText(String item) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment(0, 0.28),
child: item == _selectedValue
? _descending
? _getImage('assets/images/descending.png')
: _getImage('assets/images/ascending.png')
// ? Icon(Icons.arrow_downward_outlined, size: 20)
// : Icon(Icons.arrow_upward_outlined, size: 20)
: SizedBox(),
),
SizedBox(
width: 3,
),
Container(
//alignment: Alignment(0, -1),
child: Text(item,
style: isLoading
? TextStyle(color: Theme.of(context).disabledColor)
: (item == _selectedValue ? TextStyle(color: Colors.blue) : null)),
),
],
);
}
//点位信息数据
//{
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆",
// "dwzt": "正常"
//},
Widget getDropdownButton() {
//DropdownMenuItem项目文本list
List<String> itemList = [
'主键ID',
'点位IP',
'点位名称',
'点位编号',
'点位信息',
'点位坐标',
'点位描述',
'点位状态',
];
//添加按'推送状态'排序
if (hyshlx != 'dwxx') {
// itemList.removeLast();
// itemList.addAll(['推送状态', '主键ID']);
}
//获取DropdownMenuItem项目组件list
List<DropdownMenuItem<String>> _dropDownMenuItems =
itemList.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>(
value: item,
child: getDropdownButtonItemText(item),
);
}).toList();
return Padding(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: Container(
alignment: Alignment(0.7, 0),
width: 125,
margin: EdgeInsets.only(bottom: 0),
padding: EdgeInsets.only(left: 0, bottom: 0),
decoration: BoxDecoration(
border: Border.all(width: 0),
//边框圆角设置
borderRadius:
BorderRadius.vertical(top: Radius.elliptical(2, 2), bottom: Radius.elliptical(2, 2)),
),
//DropdownButton默认有一条下划线,DropdownButtonHideUnderline去除下划线
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
isDense: true,
value: _selectedValue,
items: _dropDownMenuItems,
onChanged: (String selectedValue) {
if (isLoading) {
return;
}
if (_selectedValue == selectedValue) {
_descending = !_descending;
} else {
_descending = true;
}
_selectedValue = selectedValue;
print('_selectedValue = $_selectedValue');
//按照用户选择的_selectedValue、_descending对listDwspGetList2进行排序,并延时更新
_listSort(bShowToast: true);
},
),
),
),
);
}
}
//https://blog.csdn.net/u014803467/article/details/103750018
//Flutter 使用SliverChildBuilderDelegate获取ListView的第一个和最后一个可见Item序号
// 秋名山交警X 2019-12-28 23:52:52
class _SaltedValueKey extends ValueKey<Key> {
const _SaltedValueKey(Key key)
: assert(key != null),
super(key);
}
class MyChildrenDelegate extends SliverChildBuilderDelegate {
MyChildrenDelegate(
Widget Function(BuildContext, int) builder, {
int childCount,
bool addAutomaticKeepAlive = true,
bool addRepaintBoundaries = true,
}) : super(builder,
childCount: childCount,
addAutomaticKeepAlives: addAutomaticKeepAlive,
addRepaintBoundaries: addRepaintBoundaries);
// Return a Widget for the given Exception
Widget _createErrorWidget(dynamic exception, StackTrace stackTrace) {
final FlutterErrorDetails details = FlutterErrorDetails(
exception: exception,
stack: stackTrace,
library: 'widgets library',
context: ErrorDescription('building'),
);
FlutterError.reportError(details);
return ErrorWidget.builder(details);
}
@override
Widget build(BuildContext context, int index) {
assert(builder != null);
if (index < 0 || (childCount != null && index >= childCount)) return null;
Widget child;
try {
child = builder(context, index);
} catch (exception, stackTrace) {
child = _createErrorWidget(exception, stackTrace);
}
if (child == null) return null;
final Key key = child.key != null ? _SaltedValueKey(child.key) : null;
if (addRepaintBoundaries) child = RepaintBoundary(child: child);
if (addSemanticIndexes) {
final int semanticIndex = semanticIndexCallback(child, index);
if (semanticIndex != null)
child = IndexedSemantics(index: semanticIndex + semanticIndexOffset, child: child);
}
if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child);
return KeyedSubtree(child: child, key: key);
}
@override
void didFinishLayout(int _firstIndex, int _lastIndex) {
// TODO: implement didFinishLayout
super.didFinishLayout(_firstIndex, _lastIndex);
}
///监听 在可见的列表中 显示的第一个位置和最后一个位置
@override
double estimateMaxScrollOffset(
int _firstIndex, int _lastIndex, double _leadingScrollOffset, double _trailingScrollOffset) {
//违章信息Listview滚动广播
eventBus.fire(WzxxDataScrollEvent(_firstIndex, _lastIndex));
return super.estimateMaxScrollOffset(
_firstIndex, _lastIndex, _leadingScrollOffset, _trailingScrollOffset);
}
}
+828
View File
@@ -0,0 +1,828 @@
//import '../../../widget/player_pro.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flustars/flustars.dart'
as flustars; //该组件中有ScreenUtil,// 获取网络图片尺寸flustars.WidgetUtil
import 'package:flutter/material.dart';
import 'package:flutter_drag_scale/flutter_drag_scale.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hyzp_ybqx/widget/my_superplayer.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
//
import '../../../components/commonFun.dart';
//import 'package:hyzp_ybqx/widget/player_pro_new.dart';
import '../../../components/dioFun.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
class FhycxContentNew extends StatefulWidget {
FhycxContentNew({
@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;
_FhycxPageState createState() => _FhycxPageState();
}
//用TabController实现顶部tab切换
class _FhycxPageState extends State<FhycxContentNew> {
//try_setState(); //避免如下异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
dispose() {
super.dispose();
}
BuildContext _context;
String _title = '';
//flutter_screenUtil 4.x 用法,ScreenUtil.screenWidth (sdk>=2.6 : 1.sw) //设备宽度
double _screenWidth = 1.sw;
double _marginLeft = 25;
double _marginCenter = 20;
double _fontSize = 16;
double _widthLeft = 40; // = _screenWidth / 3;
double _iconSize = 18;
double _stampSize = 100;
double _listTileHeight = 30;
Color _iconColor = Colors.blue;
double _marginVer = 10;
Map _mapTsjjGetTsStatus = {};
void initState() {
super.initState();
_context = context;
_widthLeft = _screenWidth / 2.6;
getListFlields();
}
Map _mapGetTsjjGetData = {
"ret": 200,
"data": {
"id": 1203,
"plate_id": "川QS9661",
"plate_color": "蓝色",
"zpsj": 1612770967,
"yjxx_id": "1379",
"workflow": 2,
"video_url": "video/9_6063_20210208_155607_川QS9661.mp4",
"pic_url": "/wwwroot/admin/Api/wwwroot/public/uploads/926f5168f1fe109a9b8ec88dcac7ac2c.jpg",
"clfl": "皮卡车",
"dwip": "172.16.3.9",
"dwms": "宜长路出城方向",
"lgmzs": 3,
"jczxd": "863",
"sfhy": "黑烟车"
},
"msg": ""
};
double _radioImage = 9 / 16;
getListFlields() async {
_mapGetTsjjGetData = await getWzxxItemData(widget.id); //获取指定id的违章信息返回 _mapGetTsjjGetData
print('_mapGetTsjjGetData = ${_mapGetTsjjGetData}');
await getShenheData(widget.id); //获取指定id的审核信息存入 listGetShenheData
await getMapGetShenheData(); //从listGetShenheData中取出数据分别存入mapGetHycsShenheData、mapGetHyfhShenheData
// 获取推送交警状态信息
// tsjjGetTsStatus返回字段 类型 说明
// id 整型 违章记录ID
// checkid 整型 推送的抓拍记录ID
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 3-推送成功
// ts_time 字符串 推送时间
//Future tsjjGetTsStatus(int _wzxxID)
_mapTsjjGetTsStatus = await tsjjGetTsStatus(widget.id);
// 获取网络图片尺寸
flustars.WidgetUtil.getImageWH(url: getMediaUrl(_mapGetTsjjGetData['pic_url'])).then((rect) {
if (null != rect) {
_radioImage = rect.height / rect.width;
}
});
imageWztp = getWztp(); //得到违章图片
//下面读取的是全局数据,该模块不需要修改
// 川Q565H4
try {
//_title = '${widget.title}(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})id:${listHycsGetList2[widget.indexRecord]['id']}';
//_title = '${widget.title}(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length}):${listHycsGetList2[widget.indexRecord]["plate_id"]}(${listHycsGetList2[widget.indexRecord]["plate_color"]})';
_title =
'${widget.title}(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})';
setState(() {});
} catch (e) {}
}
// 使用 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),
);
}
// 167 50 3.34
Widget getLgmzs(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 == _mapGetTsjjGetData['lgmzs'])
? Colors.red
: Color.fromRGBO(244, 244, 244, 1),
width: 2),
//color: Colors.lightBlue,
borderRadius: new BorderRadius.circular(3.0),
),
),
)
],
);
}
//得到tsjj页面组件
//1、得到格林曼黑度标准和视频播放按钮组件
Widget getHdAndPlay() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getLgmzs(0),
getLgmzs(1),
getLgmzs(2),
getLgmzs(3),
getLgmzs(4),
getLgmzs(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(_mapGetTsjjGetData['video_url']);
//获取视频地址失败
if (!isVideoUrl(urlnew)) {
return;
}
Navigator.of(_context).push(MaterialPageRoute(
builder: (context) => SuperPlayerPage(
loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
url: urlnew,
title:
'违章视频: ${_mapGetTsjjGetData["plate_id"]}\n${_mapGetTsjjGetData['dwms']}')));
// Navigator.of(_context).push(MaterialPageRoute(
// builder: (context) => PlayerProNew(
// loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
// url: urlnew,
// title:
// '违章视频: ${_mapGetTsjjGetData["plate_id"]}\n${_mapGetTsjjGetData['dwms']}')));
},
),
SizedBox(width: ScreenUtil().setWidth(15)),
],
);
}
Widget imageWztp;
//2、得到违章图片组件
Widget getWztp() {
//ratioList[index] = 0.5714285714285714
return Stack(
children: [
Container(
width: ScreenUtil().setWidth(1022),
//height: ScreenUtil().setHeight(639),
//height: ScreenUtil().setHeight(22 + 1022 * _radioImage),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
decoration: BoxDecoration(
//color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
),
Positioned(
//left: ScreenUtil().setWidth(_marginLeft),
top: ScreenUtil().setHeight(_marginLeft),
child: Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
child: getNetworkImage(getMediaUrl(_mapGetTsjjGetData['pic_url'])),
),
)
],
);
}
// void printScreenInformation() {
// print('Device width dp:${1.sw}dp');
// print('Device height dp:${1.sh}dp');
// print('Device pixel density:${ScreenUtil().pixelRatio}');
// print('Bottom safe zone distance dp:${ScreenUtil().bottomBarHeight}dp');
// print('Status bar height dp:${ScreenUtil().statusBarHeight}dp');
// print('The ratio of actual width to UI design:${ScreenUtil().scaleWidth}');
// print(
// 'The ratio of actual height to UI design:${ScreenUtil().scaleHeight}');
// print('System font scaling:${ScreenUtil().textScaleFactor}');
// print('0.5 times the screen width:${0.5.sw}dp');
// print('0.5 times the screen height:${0.5.sh}dp');
// }
void printScreenInformation() {
print('ScreenUtil().screenWidth = ${ScreenUtil().screenWidth}');
print('设备宽度:${1.sw}dp');
print('"1.w" = ${1.w}');
print('"1.sw" = ${1.sw}');
print('设备高度:${1.sh}dp');
print('设备的像素密度:${ScreenUtil().pixelRatio}');
print('底部安全区距离:${ScreenUtil().bottomBarHeight}dp');
print('状态栏高度:${ScreenUtil().statusBarHeight}dp');
print('实际宽度的dp与设计稿px的比例:${ScreenUtil().scaleWidth}');
print('实际高度的dp与设计稿px的比例:${ScreenUtil().scaleHeight}');
print('宽度和字体相对于设计稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil().pixelRatio}');
print('高度相对于设计稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil().pixelRatio}');
print('系统的字体缩放比例:${ScreenUtil().textScaleFactor}');
print('屏幕宽度的0.5:${0.5.sw}dp');
print('屏幕高度的0.5:${0.5.sh}dp');
}
//3、得到违章图片说明信息组件
Widget getWztpSmxx() {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(280),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
getWzxxPart1(),
getWzxxPart2(),
getWzxxPart3(),
],
),
);
}
// I/flutter (22989): ScreenUtil().screenWidth = 360.0
// I/flutter (22989): 设备宽度:360.0dp
// I/flutter (22989): "1.w" = 0.3333333333333333
// I/flutter (22989): "1.sw" = 360.0
// I/flutter (22989): 设备高度:640.0dp
// I/flutter (22989): 设备的像素密度:3.0
// I/flutter (22989): 底部安全区距离:0.0dp
// I/flutter (22989): 状态栏高度:24.0dp
// I/flutter (22989): 实际宽度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 实际高度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 宽度和字体相对于设计稿放大的比例:1.0
// I/flutter (22989): 高度相对于设计稿放大的比例:1.0
// I/flutter (22989): 系统的字体缩放比例:1.0
// I/flutter (22989): 屏幕宽度的0.5:180.0dp
// I/flutter (22989): 屏幕高度的0.5:320.0dp
//3、得到违章信息组件1:车牌号码、车牌颜色
//车牌颜色Map cpysMap = {
// '蓝色': cpysItem(
// cpysText: '蓝色',
// cpysBackground: Colors.blue,
// cpysFont: Colors.white,
// cpysBorder: Colors.orange),
// }
Widget getWzxxPart1() {
//printScreenInformation();
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
getTitleText('车牌号码:'),
getBoderText(_mapGetTsjjGetData['plate_id'].toString(),
width: ScreenUtil().setWidth(1022 / 3.2)),
SizedBox(width: ScreenUtil().setWidth(_marginCenter)),
getTitleText('颜色:'),
getBoderText(_mapGetTsjjGetData['plate_color'], width: ScreenUtil().setWidth(1022 / 4.8)),
],
);
}
Widget getTitleText(String text, {double fontSize = 16}) {
return Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis);
}
Widget getTrailText(String text, {double fontSize = 16, double off = 0}) {
return Container(
width: _screenWidth - _widthLeft - off - (2 * ScreenUtil().setWidth(_marginLeft)),
child: Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
);
}
Widget getBoderText(String text, {double width = 40}) {
cpysItem _cpysItem = cpysMap[_mapGetTsjjGetData['plate_color']];
return Container(
//color: _cpysItem.cpysBackground,
alignment: Alignment(0, -1),
width: width,
decoration: BoxDecoration(
border: Border.all(color: _cpysItem.cpysBorder, width: 2),
color: _cpysItem.cpysBackground,
borderRadius: BorderRadius.circular(3),
),
child: Padding(
padding: EdgeInsets.only(bottom: 3),
child: Text(text,
style: TextStyle(fontSize: _fontSize, color: _cpysItem.cpysFont),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
),
);
}
//I/flutter (17555): _mapGetTsjjGetData = {
// id: 1222, plate_id: 川Q736X2, plate_color: 蓝色, zpsj: 1612857077, yjxx_id: 1399, workflow: 999,
// video_url: video/9_6063_20210209_155117_川Q736X2.mp4,
// pic_url: /wwwroot/admin/Api/wwwroot/public/uploads/9d2f45fd24b41f2b94abe42b30970d75.jpg,
// clfl: 集装箱卡车, dwip: 172.16.3.9, dwms: 宜长路出城方向, lgmzs: 3, jczxd: 994, sfhy: 黑烟车
// }
Widget getIcon(IconData _iconData) {
return Container(
width: _iconSize - 2,
height: _iconSize,
child: Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(_iconData, size: _iconSize, color: _iconColor),
),
);
}
//4、得到违章信息组件2:抓拍时间组件
Widget getWzxxPart2() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - ScreenUtil().setWidth(_marginLeft),
child: getTitleText(
'抓拍时间:' +
getDate(
(_mapGetTsjjGetData['zpsj'] is int)
? _mapGetTsjjGetData['zpsj']
: int.parse(_mapGetTsjjGetData['zpsj']),
),
),
),
],
);
}
Widget getWzxxPart3() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - ScreenUtil().setWidth(_marginLeft),
child: getTitleText('抓拍地点:' + _mapGetTsjjGetData['dwms']),
),
],
);
}
//6、得到审核信息组件4:违章类型、格林曼黑度组件
Widget getWzxxPart4() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: _widthLeft,
child: getTitleText('违章类型:' + _mapGetTsjjGetData['sfhy']),
),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
//getIcon(Icons.location_on_outlined),
Container(
width: _iconSize,
height: _iconSize,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(image: AssetImage("assets/images/hyc.png"), fit: BoxFit.contain),
),
alignment: Alignment.center,
//child:
),
getTrailText(':' + _mapGetTsjjGetData['lgmzs'].toString(), off: _iconSize),
],
);
}
//从listGetShenheData中取出数据分别存入mapGetHycsShenheData、mapGetHyfhShenheData
//7、得到审核信息组件5:初审人员,初审时间
Widget getWzxxPart5() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: _widthLeft,
child: getTitleText('初审人员:' + mapGetHycsShenheData['uname']),
),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
getIcon(Icons.query_builder),
getTrailText(':' + mapGetHycsShenheData['addtime'], off: _iconSize),
],
);
}
//8、得到审核信息组件6:复审人员,复审时间
Widget getWzxxPart6() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: _widthLeft,
child: getTitleText('复审人员:' + mapGetHyfhShenheData['uname']),
),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
getIcon(Icons.query_builder),
getTrailText(':' + mapGetHyfhShenheData['addtime'], off: _iconSize),
],
);
}
//5、得到黑烟初审'hycsInfo'、或者黑烟'hyfhInfo'複核信息组件
//style: TextStyle(fontSize: _fontSize),
Widget getHyshInfo(String _hyshInfo) {
String _hyshlx = '初审';
Map _hyshMap = mapGetHycsShenheData;
if (_hyshInfo == 'hyfhInfo') {
_hyshlx = '复审';
if (mapGetHyfhShenheData.isNotEmpty) {
_hyshMap = mapGetHyfhShenheData;
} else {
//保留_hyshMap所有字段,但遍历清空所有字段的值
_hyshMap.forEach((var key, var value) {
_hyshMap[key] = '';
});
}
}
double _radio = 2.2;
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(161),
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,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Text('$_hyshlx结果:' + _hyshMap['title'],
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
SizedBox(width: ScreenUtil().setWidth(6)),
Container(
width: my_iconSize,
height: my_iconSize,
decoration: _hyshMap['title'] == ''
? null
: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
image: AssetImage(_hyshMap['title'] == "黑烟车"
? "assets/images/hyc.png"
: "assets/images/fhyc.png"),
fit: BoxFit.contain),
),
alignment: Alignment.center,
//child:
),
],
),
),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Expanded(
child: Text('意见:' + _hyshMap['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('$_hyshlx用户:' + _hyshMap['uname'],
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
]),
),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Expanded(
child: Text('时间:' + _hyshMap['addtime'],
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
),
],
),
],
),
);
}
//9、得到推送交警状态信息组件7:推送状态
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 3-推送成功
//_mapTsjjGetTsStatus['tszt']
Widget getWzxxPart7() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: _screenWidth - ScreenUtil().setWidth(_marginLeft),
child: getTitleText('推送状态:' + mapTsztText[_mapTsjjGetTsStatus['tszt']]),
),
],
);
}
//10、得到推送交警确认组件
Widget getTsjjQr() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getBtnSizeX(
text: "返回",
onPressedFun: () async {
Navigator.pop(context);
},
width: 90.0),
],
);
}
bool showMoreWidget = false;
@override
Widget build(BuildContext context) {
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: showMoreWidget
? null
: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(_title,
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 30),
],
),
),
),
),
body: null == imageWztp
// 显示加载中的圈圈
? getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0)
: Stack(
children: [
//SizedBox.shrink() 创建父类允许最小尺寸的约束Box
showMoreWidget
? Align(
alignment: Alignment(0, 0.8),
child: Container(
height: 200,
width: 200,
child: getMoreWidget2(
text: '推送中...',
color: Colors.red,
size: 40.0,
strokeWidth: 3.0), //显示加载中的圈圈,
),
)
: SizedBox.shrink(),
KeyboardAvoider(
autoScroll: true,
child: Container(
color: Color.fromRGBO(244, 244, 244, 1),
child: Column(
children: <Widget>[
//1、得到格林曼黑度标准和视频播放按钮组件
getHdAndPlay(),
//2、得到违章图片组件
imageWztp,
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//3、得到违章图片说明信息组件
getWztpSmxx(),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//7、得到黑烟初审信息组件
getHyshInfo('hycsInfo'),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//8、得到黑烟复审信息组件
getHyshInfo('hyfhInfo'),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
// //7、得到审核信息组件5:初审人员,初审时间
// getWzxxPart5(),
// //8、得到审核信息组件6:复审人员,复审时间
// getWzxxPart6(),
// SizedBox(height: 6),
// Divider(height: 1.0, color: Colors.blue),
// SizedBox(height: 6),
//6、得到推送交警状态信息组件7:推送状态
//getWzxxPart7(),
// SizedBox(height: 8),
// Divider(height: 1.0, color: Colors.blue),
SizedBox(height: 18),
//9、得到推送交警确认组件
getTsjjQr(),
SizedBox(height: 10),
],
),
),
),
Positioned(
//alignment: Alignment(0.9, 0.35),
//alignment: Alignment(0.8, 0.45),
right: ScreenUtil().setWidth(80),
top: ScreenUtil().setHeight(1045),
child: Container(
//alignment: Alignment(0.5, -0.5),
width: _stampSize,
height: _stampSize,
//color: Colors.black12,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
//image: AssetImage("assets/images/jkzx_stamp.png"), fit: BoxFit.contain),
image: AssetImage("assets/images/fhyc.png"),
fit: BoxFit.contain),
),
//child:
),
),
],
),
);
}
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,
),
);
}
}
+919
View File
@@ -0,0 +1,919 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hyzp_ybqx/widget/JdButton.dart';
//import 'package:hyzp_ybqx/widget/player_pro_new.dart';
import '../../../widget/CarNumberAndCpysItems.dart';
import '../../../components/dioFun.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../services/EventBus.dart';
import '../../../components/commonFun.dart';
import '../../../config/service_url.dart';
//import '../../../widget/player_pro.dart';
import '../../../widget/customRadioWidget.dart';
import 'package:dio/dio.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:photo_view/photo_view.dart';
//屏幕适配 flutter_screenutil 库与 flustars(获取网络图片尺寸要用到其 WidgetUtil) 库使用的 ScreenUtil() 类名冲突
// 解决办法是将 flustars 库取个别名 as flustars
import 'package:flustars/flustars.dart' as flustars;
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
import 'package:flutter_drag_scale/flutter_drag_scale.dart';
import 'hysh_group.dart';
import 'package:hyzp_ybqx/widget/my_superplayer.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_ybqx/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_ybqx/pages/Works/HYSH/hysh_content.dart:415:41)
// E/flutter (12227): #4 _LoginPageState.getZpjlFields (package:hyzp_ybqx/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 * (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)),
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;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+538
View File
@@ -0,0 +1,538 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/screen_util.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hyzp_ybqx/components/EncryptUtil.dart';
import 'package:hyzp_ybqx/components/customDialogF.dart';
import 'package:hyzp_ybqx/components/customDialogHysh.dart';
import 'package:hyzp_ybqx/components/dioFun.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../services/EventBus.dart';
import '../../../widget/CheckboxButtonItem.dart';
class HyshGroup extends StatefulWidget {
HyshGroup(
{@required this.index,
@required this.hyshlx,
this.size = const Size(30, 30),
this.fontSize = 16,
this.selectedRadio = 0,
this.id = -1});
//I don't know what is this index for but I will put it in anyway
final int index;
Size size;
double fontSize;
String hyshlx;
int selectedRadio;
int id;
@override
_HyshGroupState createState() => _HyshGroupState();
}
class _HyshGroupState extends State<HyshGroup> {
//try_setState(); //避免如下异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
int _selectedRadio = 0;
String _sfcyTextTrue = '当前时间 > 抓拍时间 + 审核间隔,只能审核,不推送交警';
String _sfcyTextFalse = '当前时间 < 抓拍时间 + 审核间隔,复审后可以推送交警';
void initState() {
_selectedRadio = widget.selectedRadio;
//黑烟审核推送交警Checkbox改变事件
eventBus.on<HycsDataAuditSfyc>().listen((event) {
print(event.str);
try_setState(); //避免如下异常报错
});
super.initState();
}
Widget getRadio(int index, Size size) {
return Container(
alignment: Alignment(-1, 1),
width: size.width,
height: size.height,
child: Radio(
value: index,
onChanged: (value) {
_selectedRadio = value;
//黑烟初审数据审核Radio选项改变广播
eventBus.fire(HycsDataAuditRadioEvent('黑烟初审数据审核Radio选项已改变', _selectedRadio));
setState(() {});
print('selectedRadio = ${_selectedRadio.toString()}');
},
groupValue: _selectedRadio,
),
);
}
//Couldn't infer type parameter 'T'. Tried to infer 'dynamic' for 'T' which doesn't work:
// Parameter 'onChanged' declared as 'void Function(T)' but argument is 'Null Function(String)'.
// The type 'dynamic' was inferred from: Parameter 'value' declared as 'T' but argument is 'String'.
// Parameter 'groupValue' declared as 'T' but argument is 'dynamic'.
// Consider passing explicit type argument(s) to the generic.
//原因是selectedRadio的类型为int,示例中_radValue为String
//无法推断类型参数“t”。试图推断“T”的“dynamic”无效:参数“onChanged”声明为“void Function(T)”,
// 但参数为“Null Function(String)”。类型“dynamic”的推断依据:参数“value”声明为“T”,
// 但参数为“String”。参数“groupValue”声明为“T”,但参数为“dynamic”。考虑将显式类型参数传递给泛型。
//5、得到黑烟审核组件
getHyshItems(int index) {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(550),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: ScreenUtil().setHeight(20)),
//5.1、车牌号码、车牌颜色
topTabs_map['carNumberAndCpys_List'][index],
SizedBox(height: ScreenUtil().setHeight(15)),
//5.2、审核意见
getShyj(widget.index),
//SizedBox(height: ScreenUtil().setHeight(25)),
//5.3、得到审核结果组件
getShjg(widget.index),
],
),
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
//5、得到黑烟审核组件
getHyshItems(widget.index),
SizedBox(height: ScreenUtil().setHeight(6)),
//6、得到审核确认组件
getShqr(widget.index),
],
);
}
//6、得到审核确认组件
Widget getShqr(int index) {
return Container(
//padding: EdgeInsets.only(top: ScreenUtil().setWidth(6)),
width: ScreenUtil().setWidth(1022),
height: ScreenUtil()
.setHeight(widget.hyshlx == 'hyfh' ? (1 == sfyc ? 215 : 150) : (1 == sfyc ? 215 : 150)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
children: [
SizedBox(height: ScreenUtil().setHeight(20)),
1 == sfyc
? Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: ScreenUtil().setWidth(30)),
child: Text(
_sfcyTextTrue,
textAlign: TextAlign.left,
style: TextStyle(color: Colors.blue, fontSize: 13),
))
: SizedBox.shrink(),
SizedBox(height: ScreenUtil().setHeight(1 == sfyc ? 6 : 0)),
widget.hyshlx == 'hyfh'
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CheckboxButtonItem(widget.index),
//_getShjgImage(widget.tabController, _selectedRadio, 35),
Container(
width: ScreenUtil().setWidth(100),
height: ScreenUtil().setHeight(100),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(_selectedRadio == 0
? "assets/images/hyc.png"
: "assets/images/fhyc.png"),
fit: BoxFit.contain),
),
),
getBtnSizeX(
text: '复审提交',
fontColor: 0 == _selectedRadio ? Colors.red : Colors.green,
onPressedFun: 1 == sfyc
? null
: () async {
int ret = -1;
print('等待复审提交确认');
await Navigator.of(context)
.push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
CustomDialogHysh(
shjg: 0 == _selectedRadio ? hyc_text : fhyc_text,
title: '复审',
content:
'是否进行复审提交${tsjj && 0 == sfyc ? '、同时推送交警' : ''}?\n${1 == sfyc ? _sfcyTextTrue : ''}'),
),
)
.then((value) async {
print('value = $value');
if (value) {
print('用户已确认,开始处理复审提交!');
//复审接口增加是否延迟字段 sfyc (是否延迟)整型 必须 是否延误,0-正常 1-延误。延误状态的不推送
// 初审不用判断,sfyc 直接提交0即可。只有复审的时候才判断时间
// A、若在规定时间内,则 int sfyc = 0,审核完毕后正常推送交警。
// B、若超出规定时间,即当前时间>抓拍时间+间隔时间,则 sfyc = 1,不推送交警。
//设置 sfyc 和 tsjj
set_sfyc_tsjj(int.parse(listGetZpjl[widget.index]['zpsj']))
.then((value) async {
hyshContentFirstAudit(
widget.id,
widget.index,
mapHyshlx[hyshlx]['audit_workflow'],
topTabs_map['auditShuoming_Controller_List'][widget.index]
.text,
topTabs_map['auditTitle'][widget.index],
sfyc: sfyc,
).then((value) {
eventBus.fire(HycsDataUpdateEvent(
'${mapHyshlx[hyshlx]['text']}数据已更新'));
//必须等待审核过程完成后,再处理同时推送交警,否则推送交警总是失败
print('tsjj = $tsjj');
if (tsjj) {
print('before tsjjFun(widget.id, _plateAndID)');
String _plateAndID =
topTabs_map['car_number_List'].toString() +
'(ID:${widget.id.toString()})';
tsjjFun(widget.id, _plateAndID);
print('after tsjjFun(widget.id, _plateAndID)');
Fluttertoast.showToast(
msg: '$_plateAndID 已推送交警,请等待返回结果。',
gravity: ToastGravity.CENTER);
}
});
});
} else {
print('用户取消了复审提交');
}
});
Navigator.pop(context, ret);
},
width: 90.0,
height: 34.0), //'复审提交'
getBtnSizeX(
text: "取消",
onPressedFun: () async {
Navigator.pop(context);
},
width: 60.0,
height: 34.0), //'取消'
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
//_getShjgImage(widget.tabController, _selectedRadio, 35),
Container(
width: 35,
height: 35,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(_selectedRadio == 0
? "assets/images/hyc.png"
: "assets/images/fhyc.png"),
fit: BoxFit.contain),
),
),
getBtnSizeX(
text: '初审提交',
fontColor: 0 == _selectedRadio ? Colors.red : Colors.green,
onPressedFun: 1 == sfyc
? null
: () async {
int ret = -1;
print('等待初审提交确认');
await Navigator.of(context)
.push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
CustomDialogHysh(
shjg: 0 == _selectedRadio ? hyc_text : fhyc_text,
title: '初审',
content: '是否进行初审提交?'),
),
)
.then((value) async {
print('value = $value');
if (value) {
print('用户已确认,开始处理初审提交!');
//return;
hyshContentFirstAudit(
widget.id,
widget.index,
mapHyshlx[hyshlx]['audit_workflow'],
topTabs_map['auditShuoming_Controller_List'][widget.index]
.text,
topTabs_map['auditTitle'][widget.index],
sfyc: 0,
).then((value) {
eventBus.fire(
HycsDataUpdateEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
});
} else {
print('用户取消了初审提交');
}
});
Navigator.pop(context, ret);
},
width: 90.0), //'初审提交'
getBtnSizeX(
text: "取消",
onPressedFun: () async {
Navigator.pop(context);
},
width: 60.0), //'取消'
],
),
],
),
);
}
//5.3、得到审核结果组件
Widget getShjg(int index) {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(175),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: my_marginLeft),
Text((widget.hyshlx == 'hyfh' ? '复审' : '初审') + '结果: ',
style: TextStyle(
fontSize: widget.fontSize,
color: 0 == _selectedRadio ? Colors.red : Colors.green)),
CustomRadioWidget(
value: 0,
title: mapHyshlx[hyshlx]['nick_text'] + "为黑烟车",
fontSize: widget.fontSize,
width: ScreenUtil().setWidth(400),
groupValue: _selectedRadio,
onChanged: (int value) {
_selectedRadio = value;
fh_hyc = true; //复审为黑烟车
tsjj = true; //同时推送交警
//黑烟初审数据审核Radio选项改变广播
eventBus.fire(HycsDataAuditRadioEvent('黑烟初审数据审核Radio选项已改变', _selectedRadio));
setState(() {});
print('selectedRadio = ${_selectedRadio.toString()}');
},
),
],
),
SizedBox(height: ScreenUtil().setHeight(15)),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: my_marginLeft),
Text((widget.hyshlx == 'hyfh' ? '复审' : '初审') + '结果: ',
style: TextStyle(fontSize: widget.fontSize, color: Colors.white)),
CustomRadioWidget(
value: 1,
title: "非黑烟车",
fontSize: widget.fontSize,
width: ScreenUtil().setWidth(400),
groupValue: _selectedRadio,
onChanged: (int value) {
_selectedRadio = value;
fh_hyc = false; //复审为黑烟车
tsjj = false; //同时推送交警
//黑烟初审数据审核Radio选项改变广播
eventBus.fire(HycsDataAuditRadioEvent('黑烟初审数据审核Radio选项已改变', _selectedRadio));
setState(() {});
print('selectedRadio = ${_selectedRadio.toString()}');
},
),
],
),
],
),
);
}
//5.2、得到审核意见组件
Widget getShyj(int index) {
// return ConstrainedBox(
// constraints: BoxConstraints(
// minWidth: double.infinity, //宽度尽可能大
// //minHeight: _listTileHeight, //最小高度
// maxHeight: my_listTileHeight, //最大高度
// ),
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(120),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.baseline,
children: <Widget>[
SizedBox(width: my_marginLeft),
Text((widget.hyshlx == 'hyfh' ? '复审' : '初审') + '意见: ',
style: TextStyle(
fontSize: my_fontSize, color: 0 == _selectedRadio ? Colors.red : Colors.green)),
Container(
alignment: Alignment(-1, 0),
height: 120,
//widthTrail = 400报错,360刚能显示,300换行,266
width: ScreenUtil().setWidth(775),
child: TextField(
//textAlign: TextAlign.right,
//style: TextStyle(fontSize: _fontSize, color: cpysList[getIndexOfCpysList(colorText: topTabs_map['cpysText_List'][i])].cpysFont),
//style: TextStyle(fontSize: _fontSize, color: cpysList[getIndexOfCpysList(colorText: myCpys)].cpysFont),
style: TextStyle(fontSize: my_fontSize),
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: '請輸入审核意见',
//border: InputBorder.none, //TextField去掉下划线
//contentPadding: EdgeInsets.only(right: 0),
//contentPadding: EdgeInsets.symmetric(vertical: my_textFieldHeight),
contentPadding: EdgeInsets.only(left: 4, right: 4), //这行代码是关键,设置这个之后,居中
//contentPadding: EdgeInsets.zero, //这行代码是关键,设置这个之后,居中
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey[600]),
//borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(3),
),
),
controller: topTabs_map['auditShuoming_Controller_List'][index],
maxLines: 1,
minLines: 1,
//maxLengthEnforced: false,
//maxLength: 10,
enabled: true,
//利用控制器初始化文本
onChanged: (value) {
topTabs_map['auditShuoming_Controller_List'][index].text = value;
},
),
),
],
),
);
}
Widget getBtnSizeX(
{@required text, width = 70.0, height = 35.0, onPressedFun, fontColor = Colors.black}) {
return Container(
color: Colors.white12, //onPressedFun为null时无效
width: width,
height: height,
child: RaisedButton(
padding: EdgeInsets.all(0),
textColor: Colors.black,
child: Text(text, style: TextStyle(color: fontColor)),
onPressed: onPressedFun,
),
);
}
}
class CustomRadioWidget<T> extends StatelessWidget {
final T value;
final String title;
final double fontSize;
final T groupValue;
final ValueChanged<T> onChanged;
final double width;
final double height;
CustomRadioWidget(
{this.value,
this.title = '',
this.fontSize = 16,
this.groupValue,
this.onChanged,
this.width = 25,
this.height = 25});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(0),
child: GestureDetector(
onTap: () {
onChanged(this.value);
},
child: Container(
//alignment: Alignment(0, 0),
height: this.height,
width: this.width,
child: value == groupValue
? Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(Icons.radio_button_checked_rounded,
color: onChanged == null ? Colors.grey : Colors.blue),
),
SizedBox(width: title.isEmpty ? 0 : 2),
Text(
title,
style: TextStyle(
fontSize: fontSize,
color: onChanged == null ? Colors.grey : Colors.blue,
fontWeight: FontWeight.bold,
),
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(Icons.radio_button_unchecked_rounded,
color: onChanged == null ? Colors.grey : Colors.black),
),
SizedBox(width: title.isEmpty ? 0 : 2),
Text(title,
style: TextStyle(
fontSize: fontSize,
color: onChanged == null ? Colors.grey : Colors.black)),
],
),
),
),
);
}
}
+926
View File
@@ -0,0 +1,926 @@
//import '../../../widget/player_pro.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flustars/flustars.dart' as flustars; //该组件中有ScreenUtil
import 'package:flutter/material.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_ybqx/components/customDialogF.dart';
import 'package:hyzp_ybqx/services/EventBus.dart';
import 'package:hyzp_ybqx/widget/my_superplayer.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
//
import '../../../components/commonFun.dart';
//import 'package:hyzp_ybqx/widget/player_pro_new.dart';
import '../../../components/dioFun.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
class TsjjContentNew extends StatefulWidget {
TsjjContentNew({
@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;
_LoginPageState createState() => _LoginPageState();
}
//用TabController实现顶部tab切换
class _LoginPageState extends State<TsjjContentNew> with SingleTickerProviderStateMixin {
//try_setState(); //避免如下异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
dispose() {
super.dispose();
}
BuildContext _context;
String _title = '';
//flutter_screenUtil 4.x 用法,ScreenUtil.screenWidth (sdk>=2.6 : 1.sw) //设备宽度
double _screenWidth = 1.sw;
double _marginLeft = 8;
double _marginCenter = 70;
double _fontSize = 16;
double _widthLeft = 40; // = _screenWidth / 3;
double _iconSize = 18;
double _stampSize = 100;
double _listTileHeight = 30;
double _marginVer = 10;
Color _iconColor = Colors.blue;
Map _mapTsjjGetTsStatus = {};
void initState() {
//黑烟审核推送交警Checkbox改变事件
eventBus.on<HycsDataAuditSfyc>().listen((event) {
print(event.str);
try_setState(); //避免如下异常报错
});
_widthLeft = _screenWidth / 2;
getListFlields();
_context = context;
super.initState();
}
Map _mapGetTsjjGetData = {
"id": 1203,
"plate_id": "川QS9661",
"plate_color": "蓝色",
"zpsj": 1612770967,
"yjxx_id": "1379",
"workflow": 2,
"video_url": "video/9_6063_20210208_155607_川QS9661.mp4",
"pic_url": "/wwwroot/admin/Api/wwwroot/public/uploads/926f5168f1fe109a9b8ec88dcac7ac2c.jpg",
"clfl": "皮卡车",
"dwip": "172.16.3.9",
"dwms": "宜长路出城方向",
"lgmzs": 3,
"jczxd": "863",
"sfhy": "黑烟车",
};
double _radioImage = 9 / 16;
Widget imageWztp;
getListFlields() async {
_mapGetTsjjGetData = await getWzxxItemData(widget.id); //获取指定id的违章信息返回 _mapGetTsjjGetData
print('_mapGetTsjjGetData = ${_mapGetTsjjGetData}');
await getShenheData(widget.id); //获取指定id的审核信息存入 listGetShenheData
await getMapGetShenheData(); //从listGetShenheData中取出数据分别存入mapGetHycsShenheData、mapGetHyfhShenheData
//Tab切换时,设置 sfyc 和 tsjj,只处理当前选中的抓拍记录 _tabController.index,zpsj抓拍时间
set_sfyc_tsjj(_mapGetTsjjGetData['zpsj']);
// 获取推送交警状态信息
// tsjjGetTsStatus返回字段 类型 说明
// id 整型 违章记录ID
// checkid 整型 推送的抓拍记录ID
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 3-推送成功
// 20210529更新:
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 2-推送成功 | 3-规定时间内已有违章记录,本次不推送 | 4-现场登记,不推送
// ts_time 字符串 推送时间
//Future tsjjGetTsStatus(int _wzxxID)
_mapTsjjGetTsStatus = await tsjjGetTsStatus(widget.id);
print('_mapTsjjGetTsStatus = $_mapTsjjGetTsStatus');
// 获取网络图片尺寸
flustars.WidgetUtil.getImageWH(url: getMediaUrl(_mapGetTsjjGetData['pic_url'])).then((rect) {
if (null != rect) {
_radioImage = rect.height / rect.width;
}
});
imageWztp = getWztp(); //得到违章图片
//下面读取的是全局数据,该模块不需要修改
// 川Q565H4
try {
//_title = '违章黑烟车详情(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})id:${listHycsGetList2[widget.indexRecord]['id']}';
//_title = '违章黑烟车(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length}):${listHycsGetList2[widget.indexRecord]["plate_id"]}(${listHycsGetList2[widget.indexRecord]["plate_color"]})';
_title = '推送交警详情(${(widget.indexRecord + 1).toString()} / ${listHycsGetList2.length})';
setState(() {});
} catch (e) {}
}
// 使用 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),
);
}
// 167 50 3.34
Widget getLgmzs(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 == _mapGetTsjjGetData['lgmzs'])
? Colors.red
: Color.fromRGBO(244, 244, 244, 1),
width: 2),
//color: Colors.lightBlue,
borderRadius: new BorderRadius.circular(3.0),
),
),
)
],
);
}
//1、得到格林曼黑度标准和视频播放按钮组件
Widget getHdAndPlay() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getLgmzs(0),
getLgmzs(1),
getLgmzs(2),
getLgmzs(3),
getLgmzs(4),
getLgmzs(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(_mapGetTsjjGetData['video_url']);
//获取视频地址失败
if (!isVideoUrl(urlnew)) {
return;
}
Navigator.of(_context).push(MaterialPageRoute(
builder: (context) => SuperPlayerPage(
loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
url: urlnew,
title:
'违章视频: ${_mapGetTsjjGetData["plate_id"]}\n${_mapGetTsjjGetData['dwms']}')));
// Navigator.of(_context).push(MaterialPageRoute(
// builder: (context) => PlayerProNew(
// loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
// url: urlnew,
// title:
// '违章视频: ${_mapGetTsjjGetData["plate_id"]}\n${_mapGetTsjjGetData['dwms']}')));
},
),
SizedBox(width: ScreenUtil().setWidth(15)),
],
);
}
//2、得到违章图片组件
Widget getWztp() {
//ratioList[index] = 0.5714285714285714
return Stack(
children: [
Container(
width: ScreenUtil().setWidth(1022),
//height: ScreenUtil().setHeight(639),
//height: ScreenUtil().setHeight(22 + 1022 * _radioImage),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
decoration: BoxDecoration(
//color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
),
Positioned(
//left: ScreenUtil().setWidth(25),
top: ScreenUtil().setHeight(25),
child: Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
child: getNetworkImage(getMediaUrl(_mapGetTsjjGetData['pic_url'])),
),
)
],
);
}
// void printScreenInformation() {
// print('Device width dp:${1.sw}dp');
// print('Device height dp:${1.sh}dp');
// print('Device pixel density:${ScreenUtil().pixelRatio}');
// print('Bottom safe zone distance dp:${ScreenUtil().bottomBarHeight}dp');
// print('Status bar height dp:${ScreenUtil().statusBarHeight}dp');
// print('The ratio of actual width to UI design:${ScreenUtil().scaleWidth}');
// print(
// 'The ratio of actual height to UI design:${ScreenUtil().scaleHeight}');
// print('System font scaling:${ScreenUtil().textScaleFactor}');
// print('0.5 times the screen width:${0.5.sw}dp');
// print('0.5 times the screen height:${0.5.sh}dp');
// }
void printScreenInformation() {
print('ScreenUtil().screenWidth = ${ScreenUtil().screenWidth}');
print('设备宽度:${1.sw}dp');
print('"1.w" = ${1.w}');
print('"1.sw" = ${1.sw}');
print('设备高度:${1.sh}dp');
print('设备的像素密度:${ScreenUtil().pixelRatio}');
print('底部安全区距离:${ScreenUtil().bottomBarHeight}dp');
print('状态栏高度:${ScreenUtil().statusBarHeight}dp');
print('实际宽度的dp与设计稿px的比例:${ScreenUtil().scaleWidth}');
print('实际高度的dp与设计稿px的比例:${ScreenUtil().scaleHeight}');
print('宽度和字体相对于设计稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil().pixelRatio}');
print('高度相对于设计稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil().pixelRatio}');
print('系统的字体缩放比例:${ScreenUtil().textScaleFactor}');
print('屏幕宽度的0.5:${0.5.sw}dp');
print('屏幕高度的0.5:${0.5.sh}dp');
}
//3、得到违章图片说明信息组件
Widget getWztpSmxx() {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(270),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
getWzxxPart1(),
getWzxxPart2(),
getWzxxPart3(),
],
),
);
}
// I/flutter (22989): ScreenUtil().screenWidth = 360.0
// I/flutter (22989): 设备宽度:360.0dp
// I/flutter (22989): "1.w" = 0.3333333333333333
// I/flutter (22989): "1.sw" = 360.0
// I/flutter (22989): 设备高度:640.0dp
// I/flutter (22989): 设备的像素密度:3.0
// I/flutter (22989): 底部安全区距离:0.0dp
// I/flutter (22989): 状态栏高度:24.0dp
// I/flutter (22989): 实际宽度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 实际高度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 宽度和字体相对于设计稿放大的比例:1.0
// I/flutter (22989): 高度相对于设计稿放大的比例:1.0
// I/flutter (22989): 系统的字体缩放比例:1.0
// I/flutter (22989): 屏幕宽度的0.5:180.0dp
// I/flutter (22989): 屏幕高度的0.5:320.0dp
//3、得到违章信息组件1:车牌号码、车牌颜色
//车牌颜色Map cpysMap = {
// '蓝色': cpysItem(
// cpysText: '蓝色',
// cpysBackground: Colors.blue,
// cpysFont: Colors.white,
// cpysBorder: Colors.orange),
// }
Widget getWzxxPart1() {
//printScreenInformation();
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getTitleText('车牌号码:'),
getBoderText(_mapGetTsjjGetData['plate_id'].toString(),
width: ScreenUtil().setWidth(1022 / 3.2)),
SizedBox(width: ScreenUtil().setWidth(_marginCenter)),
getTitleText('颜色:'),
getBoderText(_mapGetTsjjGetData['plate_color'], width: ScreenUtil().setWidth(1022 / 4.8)),
],
);
}
Widget getTitleText(String text, {double fontSize = 16, int lines = 1, Color color}) {
return Text(text,
style: TextStyle(fontSize: fontSize, color: color),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
maxLines: lines);
}
Widget getTrailText(String text, {double fontSize = 16, double off = 0}) {
return Container(
width: ScreenUtil().setWidth(1022) - _widthLeft - off - (2 * _marginLeft),
child: Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
);
}
Widget getBoderText(String text, {double width = 40}) {
cpysItem _cpysItem = cpysMap[_mapGetTsjjGetData['plate_color']];
return Container(
//color: _cpysItem.cpysBackground,
alignment: Alignment(0, -1),
width: width,
decoration: BoxDecoration(
border: Border.all(color: _cpysItem.cpysBorder, width: 2),
color: _cpysItem.cpysBackground,
borderRadius: BorderRadius.circular(3),
),
child: Padding(
padding: EdgeInsets.only(bottom: 3),
child: Text(text,
style: TextStyle(fontSize: _fontSize, color: _cpysItem.cpysFont),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
),
);
}
//I/flutter (17555): _mapGetTsjjGetData = {
// id: 1222, plate_id: 川Q736X2, plate_color: 蓝色, zpsj: 1612857077, yjxx_id: 1399, workflow: 999,
// video_url: video/9_6063_20210209_155117_川Q736X2.mp4,
// pic_url: /wwwroot/admin/Api/wwwroot/public/uploads/9d2f45fd24b41f2b94abe42b30970d75.jpg,
// clfl: 集装箱卡车, dwip: 172.16.3.9, dwms: 宜长路出城方向, lgmzs: 3, jczxd: 994, sfhy: 黑烟车
// }
Widget getIcon(IconData _iconData) {
return Container(
width: _iconSize - 2,
height: _iconSize,
child: Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(_iconData, size: _iconSize, color: _iconColor),
),
);
}
//4、得到违章信息组件2:抓拍时间组件
Widget getWzxxPart2() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - _marginLeft,
child: getTitleText(
'抓拍时间:' +
getDate(
(_mapGetTsjjGetData['zpsj'] is int)
? _mapGetTsjjGetData['zpsj']
: int.parse(_mapGetTsjjGetData['zpsj']),
),
),
),
],
);
}
Widget getWzxxPart3() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - _marginLeft,
child: getTitleText('抓拍地点:' + _mapGetTsjjGetData['dwms']),
),
],
);
}
//4、得到审核信息组件
Widget getShxx() {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(380),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
getWzxxPart4(),
getWzxxPart5(),
getWzxxPart6(),
],
),
);
}
//6、得到审核信息组件4:违章类型、格林曼黑度组件
Widget getWzxxPart4() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: _widthLeft,
child: getTitleText('违章类型:' + _mapGetTsjjGetData['sfhy']),
),
SizedBox(width: _marginLeft),
//getIcon(Icons.location_on_outlined),
Container(
width: _iconSize,
height: _iconSize,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(image: AssetImage("assets/images/hyc.png"), fit: BoxFit.contain),
),
alignment: Alignment.center,
//child:
),
getTrailText(':' + _mapGetTsjjGetData['lgmzs'].toString(), off: _iconSize),
],
);
}
//从listGetShenheData中取出数据分别存入mapGetHycsShenheData、mapGetHyfhShenheData
//7、得到审核信息组件5:初审人员,初审时间
Widget getWzxxPart5() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: 300,
child: getTitleText('初审人员:' + mapGetHycsShenheData['uname']),
),
// SizedBox(width: _marginLeft),
// getIcon(Icons.query_builder),
// getTrailText(':' + mapGetHycsShenheData['addtime'], off: _iconSize),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: 300,
child: getTitleText('初审时间:' + mapGetHycsShenheData['addtime']),
),
],
)
],
);
}
//8、得到审核信息组件6:复审人员,复审时间
Widget getWzxxPart6() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: 300,
child: getTitleText('复审人员:' + mapGetHyfhShenheData['uname']),
),
// SizedBox(width: _marginLeft),
// getIcon(Icons.query_builder),
// getTrailText(':' + mapGetHycsShenheData['addtime'], off: _iconSize),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: 300,
child: getTitleText('复审时间:' + mapGetHyfhShenheData['addtime']),
),
],
)
],
);
}
//5、得到推送交警状态组件
Widget getTsjjStatus() {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(1 == _mapTsjjGetTsStatus['tszt'] ||
2 == _mapTsjjGetTsStatus['tszt'] ||
2 != _mapTsjjGetTsStatus['tszt'] && 1 == sfyc
? 170
: 90),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
getWzxxPart7(),
],
),
);
}
//7、得到推送交警状态信息组件7:推送状态
// 20210529更新:
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 2-推送成功 | 3-规定时间内已有违章记录,本次不推送 | 4-现场登记,不推送
//_mapTsjjGetTsStatus['tszt']
Widget getWzxxPart7() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - _marginLeft,
child: Container(
child: getTitleText(
'推送状态:' +
mapTsztText[_mapTsjjGetTsStatus['tszt']] +
(1 == _mapTsjjGetTsStatus['tszt'] || 2 == _mapTsjjGetTsStatus['tszt']
? '\n推送时间:${getDate((_mapTsjjGetTsStatus['ts_time'] is int) ? _mapTsjjGetTsStatus['ts_time'] : int.parse(_mapTsjjGetTsStatus['ts_time']))}'
: '') +
(0 == _mapTsjjGetTsStatus['tszt'] && 1 == sfyc
? ',但已超时。当前时间 > 抓拍时间 + 审核间隔,不能推送交警!'
: ''),
lines: 2,
color: Colors.blue),
),
),
],
);
}
//10、得到推送交警确认组件
Widget getTsjjQr() {
Widget qxButton = getBtnSizeX(
text: "取消",
onPressedFun: showMoreWidget
? null
: () async {
Navigator.pop(context);
},
width: 90.0);
// App.Car_Hyc.GetTs接口返回值说明中没有tszt为2,但许多记录返回值都是2,返回值为2是否是推送成功?
// App.Car_Hyc.GetTs接口返回值说明有误,返回值为2表示推送成功、而不是3
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 3-推送成功
// 20210529更新:
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 2-推送成功 | 3-规定时间内已有违章记录,本次不推送 | 4-现场登记,不推送
//_mapTsjjGetTsStatus['tszt']
return Container(
//padding: EdgeInsets.only(top: ScreenUtil().setWidth(6)),
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(155),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: 2 == _mapTsjjGetTsStatus['tszt']
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('已推送', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
SizedBox(width: 2),
Padding(
padding: EdgeInsets.only(top: 3),
child: Icon(
Icons.check,
size: 18,
),
),
],
),
qxButton, //'取消'
],
)
: 1 == sfyc
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getBtnSizeX(text: '已超时', onPressedFun: null, width: 90.0), //'复审提交'
qxButton, //'取消'
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getBtnSizeX(
text: '推送',
onPressedFun: showMoreWidget
? null
: () async {
print('等待推送交警确认');
await Navigator.of(context)
.push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
CustomDialogF(title: '推送确认', content: '是否推送交警?'),
),
)
.then((value) async {
print('value = $value');
if (value) {
print('用户已确认,开始处理推送交警!');
//return;
print('before tsjjFun(widget.id)');
showMoreWidget = true;
try_setState();
String _plateAndID = _mapGetTsjjGetData['plate_id'].toString() +
'(ID:${widget.id.toString()})';
tsjjFun(widget.id, _plateAndID);
showMoreWidget = false;
try_setState();
Fluttertoast.showToast(
msg: '$_plateAndID 已推送交警,请等待返回结果。',
gravity: ToastGravity.CENTER);
} else {
print('用户取消了推送交警操作');
}
});
//Unhandled Exception: type 'String' is not a subtype of type 'int' of 'result'
Navigator.pop(context, -1);
},
width: 90.0), //'复审提交'
qxButton, //'取消'
],
),
);
}
bool showMoreWidget = false;
@override
Widget build(BuildContext context) {
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
titleSpacing: 0.0,
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的左边距
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(_title,
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 30),
],
),
),
),
),
body: null == imageWztp
// 显示加载中的圈圈
? getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0)
: Stack(
children: [
//SizedBox.shrink() 创建父类允许最小尺寸的约束Box
showMoreWidget
? Align(
alignment: Alignment(0, 0.8),
child: Container(
height: 200,
width: 200,
child: getMoreWidget2(
text: '加载中...',
color: Colors.red,
size: 40.0,
strokeWidth: 3.0), //显示加载中的圈圈,
),
)
: SizedBox.shrink(),
KeyboardAvoider(
autoScroll: true,
child: Container(
color: Color.fromRGBO(244, 244, 244, 1),
child: Column(
children: <Widget>[
//1、得到格林曼黑度标准和视频播放按钮组件
getHdAndPlay(),
//2、得到违章图片组件
//getWztp(),
imageWztp,
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//3、得到违章图片说明信息组件
getWztpSmxx(),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//4、得到审核信息组件
getShxx(),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//5、得到推送交警状态组件
getTsjjStatus(),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//9、得到推送交警确认组件
getTsjjQr(),
SizedBox(height: 10),
],
),
),
),
Positioned(
//alignment: Alignment(0.9, 0.35),
//alignment: Alignment(0.8, 0.48),
left: ScreenUtil().setWidth(80),
top: ScreenUtil().setHeight(1015),
child: Container(
//alignment: Alignment(0.5, -0.5),
width: _stampSize,
height: _stampSize,
//color: Colors.black12,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
image: AssetImage("assets/images/jkzx_stamp.png"), fit: BoxFit.contain),
),
//child:
),
),
Positioned(
//alignment: Alignment(0.9, 0.35),
//alignment: Alignment(0.8, 0.48),
right: ScreenUtil().setWidth(80),
top: ScreenUtil().setHeight(1015),
child: Container(
//alignment: Alignment(0.5, -0.5),
width: _stampSize,
height: _stampSize,
//color: Colors.black12,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
image: AssetImage("assets/images/hyc.png"), fit: BoxFit.contain),
),
//child:
),
),
],
),
);
}
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,
),
);
}
}
@@ -0,0 +1,676 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hyzp_ybqx/services/EventBus.dart';
import 'package:hyzp_ybqx/widget/JdButton.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
import '../../../components/commonFun.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../widget/DropdownItem.dart';
class LedXsxxContent extends StatefulWidget {
LedXsxxContent({
@required this.sbgllx, //sbgllx: 'led_xsxx', //设备管理类型:LED显示信息
@required this.title,
@required this.id,
Key key,
}) : super(key: key);
String title;
int id;
String sbgllx;
_LedXsxxPageState createState() => _LedXsxxPageState();
}
//用TabController实现顶部tab切换
class _LedXsxxPageState extends State<LedXsxxContent> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
dispose() {
super.dispose();
}
String _title = '';
//flutter_screenUtil 4.x 用法,ScreenUtil.screenWidth (sdk>=2.6 : 1.sw) //设备宽度
double _screenWidth = 1.sw;
double _marginLeft = 15;
double _marginCenter = 5;
double _marginCenterHeight = 20;
double _widgetHeight = 35;
double _fontSize = 16;
double _widthLeft = 40; // = _screenWidth / 3;
double _iconSize = 18;
double _stampSize = 100;
double _listTileHeight = 30;
Color _iconColor = Colors.blue;
double _titleWidth = 130;
//处理全部记录
bool _modifyAll = false;
void initState() {
super.initState();
// listLedXsxxGetList2.clear();
// ///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
// getPageList().then((value) {
// listLedXsxxGetList2 = value;
// //按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
// });
///从接口 mapHyshlx[theHyshlx]['api'] 获取指定类型第 page 页的列表数据,返回 list
///获取点位信息数据
listDwinfoGetList2.clear();
getThePageList(theHyshlx: 'dwxx').then((value) {
listDwinfoGetList2 = value;
print('listDwinfoGetList2 = \n$listDwinfoGetList2');
getListFlields();
});
//listDwinfoGetList2 = [{
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆"
//},
//{
// "id": 2,
// "dwip": "172.16.3.2",
// "dwmc": "宜飞路",
// "dwbh": 2,
// "dwinfo": "宜宾南收费站宜飞路入城方向",
// "dwzb": "104.589904|28.787078",
// "dwms": "宜宾南收费站宜飞路入城方向,识别屏山、菜坝入城排放黑烟车辆"
//},];
_widthLeft = _screenWidth / 2.6;
//监听 选择LED点位 更新事件
eventBus.on<SelectLedDwUpdateEvent>().listen((event) async {
//获取用户选择项对应的记录id
widget.id = _listItems.indexOf(event.selectedValue);
print('原生 widget.id = ${widget.id}');
if (widget.id < 1) {
_modifyAll = true; //处理全部记录
widget.id = 1;
} else {
_modifyAll = false; //处理全部记录
}
print('widget.id = ${widget.id}');
//刷新页面数据
await getListFlields();
//刷新 显示违章记录 Dropdown
// print('_mapGetLedXsxxGetData = ${_mapGetLedXsxxGetData}');
// print('_mapGetLedXsxxGetData["xsts"] = ${_mapGetLedXsxxGetData["xsts"]}');
// print(
// 'getWzjlString(_mapGetLedXsxxGetData["xsts"]) = ${getWzjlString(_mapGetLedXsxxGetData["xsts"])}');
eventBus.fire(SelectWzjlUpdateEvent(
'external_SelectWzjlUpdateEvent', getWzjlString(_mapGetLedXsxxGetData["xsts"])));
try_setState(); //避免异常报错
print(event.str);
});
//监听 选择显示违章记录 更新事件
eventBus.on<SelectWzjlUpdateEvent>().listen((event) async {
print('SelectWzjlUpdateEvent: ${event.str}');
print('SelectWzjlUpdateEvent: ${event.selectedValue}');
_selectedValue = event.selectedValue;
_xsts = getWzjlCount(event.selectedValue);
//只响应内部发送的'insider_SelectWzjlUpdateEvent'
//不响应外部发送的'external_SelectWzjlUpdateEvent'
if (event.str == 'external_SelectWzjlUpdateEvent') {
//刷新页面数据
try_setState(); //避免异常报错
}
});
}
//App.Car_Led.Get接口获取的记录数据结构(比App.Car_Led.GetList接口获取的丰富)
Map _mapGetLedXsxxGetData = {
"id": 2,
"dwip": "172.16.3.2",
"xsnr": "绿水青山就是金山银山 宜宾市生态环境局宣。",
"xsts": 0, //显示抓拍到的多少条违章记录
"stime": "07:00",
"etime": "23:00",
"addtime": "2021-01-20 10:16:07",
"updatetime": "2021-02-13 11:48:51"
};
//Web管理平台LED点位名称。除第一项外,估计后面都按ID号排列
// 全部
// 1 '江北振兴大道',
// 2 '宜飞路',
// 3 '宜宾南收费站',
// 4 '一曼路',
// 5 '柏溪收费站',
// 6 '七星路万达广场',
// 7 '宜宾财政局',
// 8 '宜威路南广镇',
// 9 '宜长路',
// 10 '宜南快速通道',
// 11 '观斗山隧道',
// 12 '大麦坝',
// 13 '外江路',
//LED点位名称List,除第一项外,后面都按ID号排列
List _listItems = [
// '全部',
// '1、江北振兴大道',
// '2、宜飞路',
// '3、宜宾南收费站',
// '4、一曼路',
// '5、柏溪收费站',
// '6、七星路万达广场',
// '7、宜宾财政局',
// '8、宜威路南广镇',
// '9、宜长路',
// '10、宜南快速通道',
// '11、观斗山隧道',
// '12、大麦坝',
// '13、外江路',
];
String _selectedValue = '不显示';
int _xsts = 0;
String _startTime = '07:00';
String _endTime = '23:00';
String _ledMessage = '绿水青山就是金山银山 宜宾市生态环境局宣。';
//App.Car_Led.Get接口获取的记录数据结构(比App.Car_Led.GetList接口获取的丰富)
// Map _mapGetLedXsxxGetData = {
// "id": 2,
// "dwip": "172.16.3.2",
// "xsnr": "绿水青山就是金山银山 宜宾市生态环境局宣。",
// "xsts": 0, //显示抓拍到的多少条违章记录
// "stime": "07:00",
// "etime": "23:00",
// "addtime": "2021-01-20 10:16:07",
// "updatetime": "2021-02-13 11:48:51"
// };
Future getListFlields() async {
//实时更新_listItems内容
_listItems = ['全部']; //LED点位名称List,除第一项外,后面都按ID号排列
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
_listItems.add('${i + 1}、${listDwinfoGetList2[i]['dwmc']}');
}
print('_listItems = $_listItems');
//获取指定id的LED记录数据返回 _mapGetLedXsxxGetData
_mapGetLedXsxxGetData = await getLedXsxxGetData(id: widget.id, theSbgllx: widget.sbgllx);
//printWrapped('_mapGetLedXsxxGetData = ${_mapGetLedXsxxGetData}');
//_mapGetLedXsxxGetData = {
// "id": 1,
// "dwip": "172.16.3.1",
// "xsnr": "绿水青山就是金山银山 宜宾市生态环境局宣。",
// "xsts": 0,
// "stime": "07:00",
// "etime": "23:00",
// "addtime": "2021-01-06 00:59:43",
// "updatetime": "2021-02-03 19:57:55"
// };
_xsts = _mapGetLedXsxxGetData['xsts'];
_ledMessage = _mapGetLedXsxxGetData['xsnr'];
_startTime = _mapGetLedXsxxGetData['stime'];
_endTime = _mapGetLedXsxxGetData['etime'];
try {
// _title =listDwinfoGetList2
// '${widget.title}(${(getIndex(widget.id) + 1).toString()} / ${listLedXsxxGetList2.length})id:${widget.id.toString()}';
//_title = '${widget.title}(${widget.id.toString()} / ${listDwinfoGetList2.length})id:${widget.id.toString()}';
//_title = '${widget.title}(${widget.id.toString()} / ${listDwinfoGetList2.length})${listDwinfoGetList2[widget.id - 1]['dwmc']}';
_title = '${widget.title}(${widget.id.toString()} / ${listDwinfoGetList2.length})';
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
// List listLedXsxxGetData = [];
// for(int i = 0; i < 13; i++) {
// listLedXsxxGetData.add(await getLedXsxxGetData(i + 1));
// }
// print('listLedXsxxGetData = \nlistLedXsxxGetData');
}
//获取 listLedXsxxGetList2 中ID号为 _id 的索引号
// int getIndex(int _id) {
// int len = listLedXsxxGetList2.length;
// int _index;
// for (_index = 0; _index < len; _index++) {
// if (listLedXsxxGetList2[_index]['id'] == _id) {
// break;
// }
// }
// return _index;
// }
Widget getTitleText(String text, {double fontSize = 16}) {
return Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis);
}
Widget getSizeText(String text, {double fontSize = 16, double width = 100, double top = 0}) {
return Container(
margin: EdgeInsets.only(top: top),
width: width,
child: Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
);
}
Widget getIcon(IconData _iconData) {
return Container(
width: _iconSize - 2,
height: _iconSize,
child: Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(_iconData, size: _iconSize, color: _iconColor),
),
);
}
//5、得到LED显示信息确认组件
Widget getLedQr() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
JdButton(
height: 126,
//JdText中已经使用ScreenUtil().setHeight(126),此处不能传 ScreenUtil().setHeight(126) ,否则严重错位
width: 350,
text: "更新",
color: Color.fromRGBO(45, 202, 115, 1),
onTop: () {
printWrapped('_message = ${_ledMessage}');
print('_xsts = ${_xsts}');
print('_startTime = ${_startTime}');
print('_endTime = ${_endTime}');
//updateLedData({@required int id, @required String theSbgllx, @required Map map})
//_modifyAll = true; //id = -1,处理全部记录
updateLedData(id: _modifyAll ? -1 : widget.id, theSbgllx: 'led_update', map: {
'xsnr': _ledMessage,
'xsts': _xsts,
'stime': _startTime,
'etime': _endTime,
});
Navigator.pop(context);
},
),
JdButton(
height: 126,
//JdText中已经使用ScreenUtil().setHeight(126),此处不能传 ScreenUtil().setHeight(126) ,否则严重错位
width: 350,
text: "取消",
color: Color.fromRGBO(43, 163, 255, 1),
onTop: () {
Navigator.pop(context);
},
),
],
);
}
//得到LED信息页面组件
//1、得到 选择LED点位 组件
Widget getSelectLedDw() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getSizeText('选择点位:', width: _titleWidth),
//SizedBox(width: _marginCenter),
//Expanded(child: SizedBox.shrink()),
DropdownItem(
listItems: _listItems,
//初始值 initValue 必须是 listItems 中的已有元素
initValue: _listItems[widget.id],
dropdownEvent: 'SelectLedDwUpdateEvent',
width: ScreenUtil().setWidth(590),
height: _widgetHeight,
), //SizedBox(width: _marginLeft),
SizedBox(width: _marginLeft),
],
);
}
//2、得到选择 显示违章记录 组件
Widget getSelectWzjl() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getSizeText('显示违章记录:', width: _titleWidth),
// Expanded(child: SizedBox.shrink()),
DropdownItem(
listItems: _listItemsWzjl,
initValue: getWzjlString(_xsts),
width: ScreenUtil().setWidth(590),
height: _widgetHeight,
dropdownEvent: 'SelectWzjlUpdateEvent',
),
SizedBox(width: _marginLeft),
],
);
}
List _listItemsWzjl = [
'不显示',
'显示3条',
'显示5条',
'显示10条',
];
//通过违章信息的条数得到显示的字符串
String getWzjlString(int wzjlCount) {
String _wzjlString = '';
switch (wzjlCount) {
case 0:
_wzjlString = _listItemsWzjl[0];
break;
case 3:
_wzjlString = _listItemsWzjl[1];
break;
case 5:
_wzjlString = _listItemsWzjl[2];
break;
case 10:
_wzjlString = _listItemsWzjl[3];
break;
default:
break;
}
return _wzjlString;
}
//通过字符串得到显示违章信息的条数
int getWzjlCount(String wzjlString) {
int _wzjlCount = -1;
switch (wzjlString) {
case '不显示':
_wzjlCount = 0;
break;
case '显示3条':
_wzjlCount = 3;
break;
case '显示5条':
_wzjlCount = 5;
break;
case '显示10条':
_wzjlCount = 10;
break;
default:
break;
}
return _wzjlCount;
}
//3、得到 启用时段 组件
Widget getOpenTime() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getSizeText('启用时段:', width: _titleWidth),
//SizedBox(width: _marginCenter),
getInBox(0, _widgetHeight), //whichTime:0为_startTime,1为_endTime
Text(' - '),
getInBox(1, _widgetHeight), //whichTime:0为_startTime,1为_endTime
],
);
}
//4、得到 显示信息 组件
Widget getLedMessage(double _width, double _height) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getSizeText('显示信息:', width: _titleWidth, top: 2),
],
),
SizedBox(height: ScreenUtil().setHeight(10)),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
getInBoxMsg(_width, _height), //whichTime:0为_startTime,1为_endTime
],
),
],
);
}
//显示信息 输入框
Widget getInBoxMsg(double _width, double _height) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: ScreenUtil().setHeight(_height),
maxHeight: ScreenUtil().setHeight(_height),
minWidth: ScreenUtil().setWidth(_width),
maxWidth: ScreenUtil().setWidth(_width),
),
child: TextField(
keyboardType: TextInputType.multiline,
maxLines: 10,
//不限制行数
textAlign: TextAlign.justify,
style: TextStyle(fontSize: my_fontSize),
decoration: InputDecoration(
hintText: '请输入LED显示信息',
contentPadding: EdgeInsets.only(top: 4, left: 8, bottom: 4, right: 8),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(3.0)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(3.0)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(3),
borderSide: BorderSide(
color: Colors.grey,
width: 2.0,
),
),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(3.0),
// borderSide: BorderSide(color: Colors.grey, width: 0)),
),
controller: TextEditingController.fromValue(TextEditingValue(
text: _ledMessage,
// 保持光标在最后
// selection: TextSelection.fromPosition(
// TextPosition(affinity: TextAffinity.downstream, offset: _message.length))
)),
enabled: true,
onChanged: (value) {
_ledMessage = value;
printWrapped(_ledMessage);
},
),
);
}
//whichTime:0为_startTime,1为_endTime
Widget getInBox(int _whichTime, double _height) {
return Container(
alignment: Alignment(0, 0),
height: _height,
width: 90,
// decoration: BoxDecoration(
// border: Border.all(color: Colors.grey, width: 2),
// borderRadius: BorderRadius.all(Radius.circular(3.0)),
// ),
child: TextField(
textAlign: TextAlign.center,
style: TextStyle(fontSize: my_fontSize),
decoration: InputDecoration(
hintText: _whichTime == 0 ? '启用时间' : '关闭时间',
contentPadding: EdgeInsets.all(0),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(3.0)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(3.0)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(3),
borderSide: BorderSide(
color: Colors.grey,
width: 2.0,
),
),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(3.0),
// borderSide: BorderSide(color: Colors.grey, width: 0)),
),
controller: TextEditingController.fromValue(TextEditingValue(
text: (_whichTime == 0 ? _startTime : _endTime),
// 保持光标在最后
selection: TextSelection.fromPosition(TextPosition(
affinity: TextAffinity.downstream,
offset: (_whichTime == 0 ? _startTime : _endTime).length)))),
enabled: true,
onChanged: (value) {
if (_whichTime == 0) {
_startTime = value;
} else {
_endTime = value;
}
},
),
);
}
String _sizedropDown = 'brown';
@override
Widget build(BuildContext context) {
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(_title,
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 30),
],
),
),
),
),
body: _listItems.isEmpty || _mapGetLedXsxxGetData == null
? getMoreWidget(color: Colors.grey)
: KeyboardAvoider(
autoScroll: true,
child: Container(
child: Column(
children: <Widget>[
//1、得到选择LED点位组件
SizedBox(height: _marginCenterHeight),
getSelectLedDw(),
Divider(height: _marginCenterHeight),
//2、得到选择 显示违章记录 组件
getSelectWzjl(),
Divider(height: _marginCenterHeight),
//3、得到 启用时段 组件
getOpenTime(),
Divider(height: _marginCenterHeight),
//4、得到 显示信息 组件
getLedMessage(980, 570),
Divider(height: _marginCenterHeight),
SizedBox(height: _marginCenterHeight),
//5、得到Led确认组件
getLedQr(),
SizedBox(height: _marginCenterHeight),
],
),
),
),
);
}
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,
),
);
}
}
@@ -0,0 +1,568 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'led_xsxx_content.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../components/commonFun.dart';
import '../../../services/EventBus.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import '../../../components/doJSON.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
//LedXsxx是本项目中“LED显示信息”的统一缩写
class LedXsxxGetList extends StatefulWidget {
//hyshlx为黑烟审核类型,处理'LedXsxx'LED显示信息。mapHyshlx[hyshlx]获取为各种类型的设置数据
LedXsxxGetList({this.sbgllx = 'led_xsxx', Key key}) : super(key: key);
String sbgllx;
_LedXsxxPageState createState() => _LedXsxxPageState();
}
class _LedXsxxPageState extends State<LedXsxxGetList> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void dispose() {
_controller.dispose(); //销毁控制器
super.dispose();
}
@override
void initState() {
hyshlx = widget.sbgllx;
iPage = 0;
listLedXsxxGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList().then((value) {
listLedXsxxGetList2 = value;
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
});
///从接口 mapHyshlx[theHyshlx]['api'] 获取指定类型第 page 页的列表数据,返回 list
///获取点位信息数据
listDwinfoGetList2.clear();
getThePageList(theHyshlx: 'dwxx').then((value) {
listDwinfoGetList2 = value;
print('listDwinfoGetList2 = \n$listDwinfoGetList2');
});
//监听违章信息数据更新事件
eventBus.on<LedXsxxUpdateEvent>().listen((event) async {
iPage = 0;
print(event.str);
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
_listSort();
});
//监听违章信息数据审核事件
eventBus.on<WzxxDataAuditEvent>().listen((event) async {
print('LedXsxxGetList: ' + event.str);
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
_listSort();
});
//监听违章信息Listview滚动事件
eventBus.on<WzxxDataScrollEvent>().listen((event) async {
firstIndex = event.firstIndex;
lastIndex = event.lastIndex;
try_setState();
});
super.initState();
}
//Led数据变量
// Map mapGetLedXsxxGetData = {
// "id": 2,
// "xsnr": "绿水青山就是金山银山 宜宾市生态环境局宣。",
// "addtime": "2021-01-20 10:16:07",
// "updatetime": "2021-02-13 11:48:51"
// };
Widget _getListTile(BuildContext context, indexRecord) {
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: Text(
"${(indexRecord + 1).toString()}. " +
listLedXsxxGetList2[indexRecord]['addtime'] +
' 添加',
style: TextStyle(fontSize: 10)),
subtitle: Text(getDate(listLedXsxxGetList2[indexRecord]['updatetime']) + ' 更新',
style: TextStyle(fontSize: 10)),
trailing: Container(
width: 180,
child: Text(
'id:' +
listLedXsxxGetList2[indexRecord]['id'].toString() +
', 显示信息:' +
listLedXsxxGetList2[indexRecord]['xsnr'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 12),
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {
int ret = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LedXsxxContent(
title: 'LED显示信息详情',
sbgllx: widget.sbgllx,
id: listLedXsxxGetList2[indexRecord]['id'],
),
),
);
print('ret = $ret');
},
),
Divider(height: 1.0),
],
);
}
ScrollController _controller = ScrollController(); //ListView控制器
bool isLoading = false; //正在处理下载数据、跳转到首项、跳转到尾项等操作
int firstIndex = 0; //ListView当前显示页面首项0基序号
int lastIndex = 0; //ListView当前显示页面末项0基序号
int itemOnPage = 8; //估计一屏显示的项目数量
Widget getIconButton({IconData iconData, var onPressed, double iconSize = 22}) {
return SizedBox(
height: iconSize,
width: iconSize + 10,
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: Icon(iconData, size: iconSize),
onPressed: onPressed,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
//leading: Text(''),
titleSpacing: 0.0,
//设置title的左边距
title: Padding(
padding: EdgeInsets.only(left: 0, right: 0),
child: Row(
//mainAxisAlignment: MainAxisAlignment.start,
children: [
getIconAndTextButton(
iconData: Icons.arrow_back,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text("${mapHyshlx[hyshlx]['text']}",
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
style: widget.sbgllx == 'fhycx' ? TextStyle(fontSize: 16) : null),
),
SizedBox(width: 5),
],
),
),
actions: <Widget>[
getDropdownButton(),
SizedBox(width: 10),
getIconButton(
iconData: Icons.cloud_download,
onPressed: !isLoading
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//print("I Pressed the Iconbutton");
int oldItems = listLedXsxxGetList2.length;
for (int i = 0; i < 10; i++) {
List list = await getPageList();
if (list.length > 0) {
listLedXsxxGetList2.addAll(list); //加载累加
} else {
break;
}
}
Future.delayed(const Duration(milliseconds: 1000), () async {
if (listLedXsxxGetList2.length > oldItems) {
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
Fluttertoast.showToast(
msg: '新增 ${listLedXsxxGetList2.length - oldItems} 条数据下载完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
_listSort();
}
isLoading = false;
try_setState();
});
}
: null,
),
getIconButton(
iconData: Icons.vertical_align_top_outlined,
onPressed: (!isLoading && (firstIndex > 0)) //未到顶部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.minScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到开头记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
firstIndex = 0;
lastIndex = itemOnPage - 1; //0基序号,所以需要减1
isLoading = false;
try_setState();
},
);
}
: null,
),
getIconButton(
iconData: Icons.vertical_align_bottom_outlined,
onPressed: (!isLoading && (lastIndex < listLedXsxxGetList2.length)) //未到尾部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.maxScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到末尾记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
//0基序号需要减1,再加上底部有一组显示信息,所以需要减2
firstIndex = listLedXsxxGetList2.length - itemOnPage - 2;
lastIndex = listLedXsxxGetList2.length;
isLoading = false;
try_setState();
},
);
}
: null,
),
],
),
body: (0 == listLedXsxxGetList2.length)
? getMoreWidget(color: Colors.black38)
: EasyRefresh(
child: ListView.custom(
controller: _controller,
cacheExtent: 1.0, // 只有设置了1.0 才能够准确的标记position 位置
childrenDelegate: MyChildrenDelegate(
_getListTile,
childCount: listLedXsxxGetList2.length,
),
),
onRefresh: () async {
// await Future.delayed(const Duration(seconds: 1), () async {
// iPage = 0;
// //await getWzxxGetList();
// listLedXsxxGetList2 = await getPageList();
// eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
// });
},
onLoad: () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
print('iPage = $iPage');
await Future.delayed(const Duration(seconds: 1), () async {
//await getWzxxGetList();
List list = await getPageList();
if (list.length > 0) {
listLedXsxxGetList2.addAll(list); //加载累加
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
}
isLoading = false;
try_setState();
});
},
header: getHeader(),
footer: getFooter(),
),
);
}
//DropdownButton需要设置初始值的时候,初始值必须是显示列表里面的值,否则会导致弹出框异常。
// 比如说:你的DropdownButton的items属性使用的是list这个列表里面的值,那么你的初始值应该在list[index]里面取,要不就会报错。
//
// There should be exactly one item with [DropdownButton]'s value: 0.0.
// Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
// 'package:flutter/src/material/dropdown.dart':
// Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
// items.where((DropdownMenuItem<T> item) {
// return item.value == value;
// }).length == 1'
String _selectedValue = '主键ID';
bool _descending = false; //默认生效排列
Widget _getImage(String _image) {
return Container(
margin: EdgeInsets.only(),
height: ScreenUtil().setWidth(38),
width: ScreenUtil().setWidth(38),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(_image,
fit: BoxFit.cover, color: isLoading ? Theme.of(context).disabledColor : null));
}
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
Future _listSort({bool bShowToast = false}) {
if (!isLoading && listLedXsxxGetList2.length > 0) {
isLoading = true;
try_setState();
switch (_selectedValue) {
default:
if (_descending) {
//按_selectedValue排序,降序
listLedXsxxGetList2.sort((a, b) =>
(b[mapWzxxDataText[_selectedValue]]).compareTo(a[mapWzxxDataText[_selectedValue]]));
} else {
//按_selectedValue排序,升序
listLedXsxxGetList2.sort((a, b) =>
(a[mapWzxxDataText[_selectedValue]]).compareTo(b[mapWzxxDataText[_selectedValue]]));
}
break;
}
Future.delayed(const Duration(milliseconds: 1000), () {
if (bShowToast) {
Fluttertoast.showToast(
msg: '按“${_selectedValue}”${_descending ? '降序' : '升序'}排列完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
}
isLoading = false;
try_setState(); //避免如下异常报错
});
}
}
Widget getDropdownButtonItemText(String item) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment(0, 0.28),
child: item == _selectedValue
? _descending
? _getImage('assets/images/descending.png')
: _getImage('assets/images/ascending.png')
// ? Icon(Icons.arrow_downward_outlined, size: 20)
// : Icon(Icons.arrow_upward_outlined, size: 20)
: SizedBox(),
),
SizedBox(
width: 3,
),
Container(
//alignment: Alignment(0, -1),
child: Text(item,
style: isLoading
? TextStyle(color: Theme.of(context).disabledColor)
: (item == _selectedValue ? TextStyle(color: Colors.blue) : null)),
),
],
);
}
Widget getDropdownButton() {
//DropdownMenuItem项目文本list
List<String> itemList = [
'主键ID',
'添加时间',
'更新时间',
'显示信息',
];
//添加按'推送状态'排序
if (hyshlx != 'led_xsxx') {
itemList.removeLast();
itemList.addAll(['推送状态', '主键ID']);
}
//获取DropdownMenuItem项目组件list
List<DropdownMenuItem<String>> _dropDownMenuItems =
itemList.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>(
value: item,
child: getDropdownButtonItemText(item),
);
}).toList();
return Padding(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: Container(
alignment: Alignment(0.7, 0),
width: 125,
margin: EdgeInsets.only(bottom: 0),
padding: EdgeInsets.only(left: 0, bottom: 0),
decoration: BoxDecoration(
border: Border.all(width: 0),
//边框圆角设置
borderRadius:
BorderRadius.vertical(top: Radius.elliptical(2, 2), bottom: Radius.elliptical(2, 2)),
),
//DropdownButton默认有一条下划线,DropdownButtonHideUnderline去除下划线
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
isDense: true,
value: _selectedValue,
items: _dropDownMenuItems,
onChanged: (String selectedValue) {
if (isLoading) {
return;
}
if (_selectedValue == selectedValue) {
_descending = !_descending;
} else {
_descending = true;
}
_selectedValue = selectedValue;
print('_selectedValue = $_selectedValue');
//按照用户选择的_selectedValue、_descending对listLedXsxxGetList2进行排序,并延时更新
_listSort(bShowToast: true);
},
),
),
),
);
}
}
//https://blog.csdn.net/u014803467/article/details/103750018
//Flutter 使用SliverChildBuilderDelegate获取ListView的第一个和最后一个可见Item序号
// 秋名山交警X 2019-12-28 23:52:52
class _SaltedValueKey extends ValueKey<Key> {
const _SaltedValueKey(Key key)
: assert(key != null),
super(key);
}
class MyChildrenDelegate extends SliverChildBuilderDelegate {
MyChildrenDelegate(
Widget Function(BuildContext, int) builder, {
int childCount,
bool addAutomaticKeepAlive = true,
bool addRepaintBoundaries = true,
}) : super(builder,
childCount: childCount,
addAutomaticKeepAlives: addAutomaticKeepAlive,
addRepaintBoundaries: addRepaintBoundaries);
// Return a Widget for the given Exception
Widget _createErrorWidget(dynamic exception, StackTrace stackTrace) {
final FlutterErrorDetails details = FlutterErrorDetails(
exception: exception,
stack: stackTrace,
library: 'widgets library',
context: ErrorDescription('building'),
);
FlutterError.reportError(details);
return ErrorWidget.builder(details);
}
@override
Widget build(BuildContext context, int index) {
assert(builder != null);
if (index < 0 || (childCount != null && index >= childCount)) return null;
Widget child;
try {
child = builder(context, index);
} catch (exception, stackTrace) {
child = _createErrorWidget(exception, stackTrace);
}
if (child == null) return null;
final Key key = child.key != null ? _SaltedValueKey(child.key) : null;
if (addRepaintBoundaries) child = RepaintBoundary(child: child);
if (addSemanticIndexes) {
final int semanticIndex = semanticIndexCallback(child, index);
if (semanticIndex != null)
child = IndexedSemantics(index: semanticIndex + semanticIndexOffset, child: child);
}
if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child);
return KeyedSubtree(child: child, key: key);
}
@override
void didFinishLayout(int _firstIndex, int _lastIndex) {
// TODO: implement didFinishLayout
super.didFinishLayout(_firstIndex, _lastIndex);
}
///监听 在可见的列表中 显示的第一个位置和最后一个位置
@override
double estimateMaxScrollOffset(
int _firstIndex, int _lastIndex, double _leadingScrollOffset, double _trailingScrollOffset) {
//违章信息Listview滚动广播
eventBus.fire(WzxxDataScrollEvent(_firstIndex, _lastIndex));
return super.estimateMaxScrollOffset(
_firstIndex, _lastIndex, _leadingScrollOffset, _trailingScrollOffset);
}
}
+595
View File
@@ -0,0 +1,595 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/screen_util.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hyzp_ybqx/components/commonFun.dart';
import 'package:hyzp_ybqx/components/customDialogF.dart';
import 'package:hyzp_ybqx/services/EventBus.dart';
import 'package:hyzp_ybqx/widget/customRadioWidget.dart';
import '../../../components/doJSON.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import 'dart:io';
import '../../../components/customDialogH.dart';
import '../../../components/customDialogJ.dart';
class SbbjContent extends StatefulWidget {
//SbbjContent({Key key, this.title, this.mapData}) : super(key: key);
SbbjContent({
@required this.title,
@required this.index,
@required this.hyshlx,
Key key,
}) : super(key: key);
String title;
int index = -1;
String hyshlx;
_SbbjPageState createState() => _SbbjPageState();
}
class _SbbjPageState extends State<SbbjContent> {
Map _mapGetSbbjGetDataText = {
"id": "主键ID",
"bjlx": "设备类型",
"content": "报警内容",
"dwip": "点位IP",
"sbip": "设备IP",
"addtime": "添加时间",
"workflow": "处理状态"
};
Map _mapGetSbbjGetData = {
"id": 1177,
"bjlx": "风扇",
"content": "串口COM1获取风扇异常数据",
"dwip": "172.16.3.1",
"sbip": "192.168.1.10",
"addtime": "2021-02-07 23:56:45",
"workflow": 999
};
List<TextEditingController> _listController = [];
int listLen = 0;
String nums = '';
int _selectedRadio = 0;
void initState() {
// TODO: implement initState
super.initState();
listLen = listSbbjGetList2.length;
getListFlields();
}
//监听登录页面销毁的事件
dispose() {
_controller.dispose();
super.dispose();
}
getListFlields() async {
//获取指定id的sbbj记录数据返回 _mapGetSbbjGetData。由于 sbbj 信息需要进行查核处理,所以要重新读取最新的记录数据
_mapGetSbbjGetData =
await getLedXsxxGetData(id: listSbbjGetList2[widget.index]['id'], theSbgllx: widget.hyshlx);
print('_mapGetSbbjGetData = ${_mapGetSbbjGetData}');
//_mapGetSbbjGetData = listSbbjGetList2[widget.index];
_listController = List.generate(_mapGetSbbjGetData.length, (index) {
String key = _mapGetSbbjGetData.keys.elementAt(index);
String strContent = _mapGetSbbjGetData[key].toString();
//时间戳转换
if (strContent.isNotEmpty && 'addtime' == key) {
strContent = getDate(strContent);
}
//workflow转换
if (strContent.isNotEmpty && 'workflow' == key) {
strContent = strContent == '999' ? '已处理' : '待处理';
}
var controller = TextEditingController(text: strContent);
controller.selection = TextSelection.fromPosition(
TextPosition(affinity: TextAffinity.downstream, offset: '${controller.text}'.length),
);
return controller;
});
getPreBtn_NextBtn();
nums = '${(widget.index + 1).toString()} / $listLen';
setState(() {});
}
Widget getTrail(String key, int index, double widthTrail) {
if (0 == _listController.length) {
return Container(width: widthTrail);
}
//print('key = $key');
if ('avatar' == key) {
imagePath = _listController[index].text;
return getAvatar(width: widthTrail);
} else {
return Container(
alignment: Alignment(-1, 0),
//widthTrail = 400报错,360刚能显示,300换行,260
width: widthTrail,
//解决信息显示不全问题
child: Text(_listController[index].text,
style: TextStyle(fontSize: 16), textAlign: TextAlign.left),
);
}
}
Widget getTrail0(String key, int index, double widthTrail) {
if (0 == _listController.length) {
return Container(width: widthTrail);
}
//print('key = $key');
if ('avatar' == key) {
imagePath = _listController[index].text;
return getAvatar(width: widthTrail);
} else {
return Container(
alignment: Alignment(1, 0),
//widthTrail = 400报错,360刚能显示,300换行,260
width: widthTrail,
child: TextField(
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 16),
decoration: InputDecoration(
//hintText: '請輸入字段信息',
border: InputBorder.none, //TextField去掉下划线
contentPadding: EdgeInsets.only(right: 0),
),
controller: _listController[index],
enabled: 'content' == key ? true : false,
//解决报警信息显示不全问题,但软键盘会弹出,很难控制键盘弹出问题
//利用控制器初始化文本
onChanged: null,
),
);
}
}
Future<String> doContacts() async {
bFlash = false;
return showDialog(
context: context,
builder: (BuildContext context) {
return customDialogH(
title: "请选择头像修改操作",
content: "头像修改",
index: 0,
);
},
).then((value) {
imagePath = value;
print('Page2_Contacts bFlash = $bFlash');
if (imagePath.isNotEmpty) {
_image = Image.file(File(imagePath), fit: BoxFit.cover);
setState(() {});
}
});
}
//Image.file(this._image);
String imagePath = '';
Image _image;
Widget getAvatar({double width = 260.0}) {
if (imagePath.isEmpty) {
_image = Image.asset('assets/images/user.png', fit: BoxFit.cover);
} else {
String head = imagePath.substring(0, 4).trim().toLowerCase();
if ('http' == head) {
_image = Image.network(imagePath, fit: BoxFit.cover);
}
}
return Container(
alignment: Alignment(-1, 0),
width: width,
child: InkWell(
onTap: () async {
doContacts();
},
child: Container(
width: 40,
child: _image,
),
),
);
}
//添加、修改、删除联系人对话框
doContacts2(String key, int index) async {
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogJ(
theKey: key,
index: index,
);
},
);
}
static onNullFun() {}
Widget _getListTile(String key, int index, double widthTrail,
{onTapFun = onNullFun, onLongPressFun = onNullFun, size = 16.0}) {
//print('key = $key, index = $index');
return ListTile(
//leading: new Icon(Icons.phone),
title: Text((index + 1).toString() + ". " + '${_mapGetSbbjGetDataText[key]} :',
style: TextStyle(fontSize: 16)),
trailing: getTrail(key, index, widthTrail),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {
// print('第 $index 项被点击了');
// await doContacts2(key, index);
// if ('avatar' == key) {
// print('选择图片或拍照');
// await doContacts();
// }
},
onLongPress: () {},
);
}
TextEditingController _controller = TextEditingController.fromValue(TextEditingValue(
text: '已做简单处理。低级故障,不影响系统运行',
// 保持光标在最后
selection: TextSelection.fromPosition(
TextPosition(affinity: TextAffinity.downstream, offset: '已处理'.length))));
//7、得到核查处理意见组件
Widget getClyj(int index, bool _bCheck) {
if (_bCheck) {
_controller.text = '';
} else {
_controller.text = (0 == _selectedRadio ? '已做简单处理。低级故障,不影响系统运行' : '已核查,属于误报');
}
return ConstrainedBox(
constraints: BoxConstraints(
minWidth: double.infinity, //宽度尽可能大
//minHeight: _listTileHeight, //最小高度
maxHeight: _heigth, //最大高度
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.baseline,
children: <Widget>[
SizedBox(width: _marginLeft),
Text('处理意见:',
style: TextStyle(
fontSize: _fontSize,
color: _bCheck
? Colors.grey
: 0 == _selectedRadio
? Colors.red
: Colors.green)),
Container(
alignment: Alignment(-1, 0),
height: _heigth,
//widthTrail = 400报错,360刚能显示,300换行,260
width: 240,
child: TextField(
//textAlign: TextAlign.right,
//style: TextStyle(fontSize: _fontSize, color: cpysList[getIndexOfCpysList(colorText: topTabs_map['cpysText_List'][i])].cpysFont),
//style: TextStyle(fontSize: _fontSize, color: cpysList[getIndexOfCpysList(colorText: myCpys)].cpysFont),
style: TextStyle(fontSize: _fontSize),
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: _bCheck ? '' : '請輸入审核意见',
//border: InputBorder.none, //TextField去掉下划线
//contentPadding: EdgeInsets.only(right: 0),
//contentPadding: EdgeInsets.symmetric(vertical: _textFieldHeight),
contentPadding: EdgeInsets.only(left: 4, right: 4), //这行代码是关键,设置这个之后,居中
//contentPadding: EdgeInsets.zero, //这行代码是关键,设置这个之后,居中
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey[600]),
//borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(3),
),
),
controller: _controller,
maxLines: 1,
minLines: 1,
//maxLengthEnforced: false,
//maxLength: 10,
enabled: !_bCheck,
//利用控制器初始化文本
onChanged: (value) {
_controller.text = value;
},
),
),
],
),
);
}
double _heigth = 30;
double _fontSize = 16;
double _marginLeft = 15;
@override
Widget build(BuildContext context) {
bool bCheck = _mapGetSbbjGetData['workflow'] == 999; //已处理
return Scaffold(
// appBar: AppBar(
// title: Text("设备报警信息详情($nums)"),
// centerTitle: true,
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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.center,
children: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text("设备报警信息详情($nums)",
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 50),
],
),
),
),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(
//https://www.it1352.com/2028416.html
//用Map而不是List的Flutter ListView.builder(Flutter listview with Map instead of List)
//使用ListView.separated设置分割线ListView.separated(
//child: ListView.separated( //这种方式不能设置每项高度,每页只能有7项
child: ListView.builder(
//这种方式可以通过itemExtent设置每项高度,每页可以有9项
//separatorBuilder: (BuildContext context, int index) => index %2 ==0? Divider(color: Colors.green) : Divider(color: Colors.red),//index为偶数,创建绿色分割线;index为奇数,则创建红色分割线
//separatorBuilder: (BuildContext context, int index) => Divider(),
//itemExtent: 57.0, //列表项高度。56越界、57刚好。还是自动计算最好
itemCount: _mapGetSbbjGetData.length,
itemBuilder: (BuildContext context, index) {
String key = _mapGetSbbjGetData.keys.elementAt(index);
return Column(
children: <Widget>[
_getListTile(key, index, 200.0),
Divider(
height: 1.0,
),
],
);
},
),
),
//7、得到核查处理意见组件
Divider(height: 1.0, color: Colors.blue),
SizedBox(height: 15),
getClyj(widget.index, bCheck),
SizedBox(height: 10),
//8、处理结果
Container(
height: _heigth,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: _marginLeft),
Text('处理结果:',
style: TextStyle(
fontSize: _fontSize,
color: bCheck
? Colors.grey
: 0 == _selectedRadio
? Colors.red
: Colors.green)),
CustomRadioWidget(
value: 0,
title: "已处理",
fontSize: _fontSize,
width: 120,
groupValue: _selectedRadio,
onChanged: bCheck
? null
: (int value) {
_selectedRadio = value;
//黑烟初审数据审核Radio选项改变广播
//eventBus.fire(HycsDataAuditRadioEvent('黑烟初审数据审核Radio选项已改变', _selectedRadio));
_controller.text = '已做简单处理。低级故障,不影响系统运行';
setState(() {});
print('selectedRadio = ${_selectedRadio.toString()}');
},
),
SizedBox(width: 20),
CustomRadioWidget(
value: 1,
title: "误报",
fontSize: _fontSize,
width: 100,
groupValue: _selectedRadio,
onChanged: bCheck
? null
: (int value) {
_selectedRadio = value;
//黑烟初审数据审核Radio选项改变广播
//eventBus.fire(HycsDataAuditRadioEvent('黑烟初审数据审核Radio选项已改变', _selectedRadio));
_controller.text = '已核查,属于误报';
setState(() {});
print('selectedRadio = ${_selectedRadio.toString()}');
},
),
],
),
),
SizedBox(height: 10),
Divider(height: 1.0, color: Colors.blue),
SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getBtnSizeX(
text: "处理",
onPressedFun: bCheck
? null
: () async {
int ret = -1;
print('等待处理确认');
await Navigator.of(context)
.push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
CustomDialogF(title: '处理确认', content: '是否进行设备报警信息核查处理?'),
),
)
.then((value) async {
print('value = $value');
if (value) {
print('用户已确认,开始处理报警信息核查处理!');
// sbglContentFirstAudit 整型返回值:更新的结果,1表示成功,0表示无更新,false表示失败
ret = await sbglContentAudit(
sbgllx: widget.hyshlx,
sbglID: _mapGetSbbjGetData['id'],
shuoming: _controller.text,
title: 0 == _selectedRadio ? '已处理' : '误报',
);
if (1 == ret) {
eventBus.fire(SbglDataUpdateEvent(
'${mapHyshlx[widget.hyshlx]['text']}数据已更新'));
print('${mapHyshlx[widget.hyshlx]['text']}结果已成功上传服务器。');
}
} else {
print('用户取消了报警信息核查处理');
}
});
Navigator.pop(context, ret);
}),
//getBtnSizeX(text: "删除", onPressedFun: () async {}),
preBtn,
nextBtn,
],
),
SizedBox(height: 20),
],
),
),
);
}
//解决第一次进入报错问题。因为getPreBtn_NextBtn()还未执行,preBtn和nextBtn为空
Widget preBtn = Container(
color: Colors.white12, //onPressedFun为null时无效
width: 70.0,
height: 35.0,
child: RaisedButton(
padding: EdgeInsets.all(0),
textColor: Colors.black,
child: Text('上一条'),
onPressed: null,
),
);
Widget nextBtn = Container(
color: Colors.white12, //onPressedFun为null时无效
width: 70.0,
height: 35.0,
child: RaisedButton(
padding: EdgeInsets.all(0),
textColor: Colors.black,
child: Text('下一条'),
onPressed: null,
),
);
getPreBtn_NextBtn() {
preBtn = getBtnSizeX(
text: "上一条",
onPressedFun: null,
);
nextBtn = getBtnSizeX(
text: "下一条",
onPressedFun: null,
);
if (widget.index > 0 && listLen > 0) {
preBtn = getBtnSizeX(
text: "上一条",
onPressedFun: () async {
if (widget.index > 0) {
widget.index--;
getListFlields();
}
},
);
}
if (widget.index < (listLen - 1) && listLen > 0) {
nextBtn = getBtnSizeX(
text: "下一条",
onPressedFun: () async {
if (widget.index < listLen - 1) {
widget.index++;
getListFlields();
}
},
);
}
}
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,
),
);
}
}
+799
View File
@@ -0,0 +1,799 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'sbbj_content.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../components/commonFun.dart';
import '../../../services/EventBus.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import '../../../components/doJSON.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
//sbbj是本项目中“设备报警”的统一缩写
class SbbjGetList extends StatefulWidget {
//hyshlx为黑烟审核类型,处理sbbj信息。mapHyshlx[hyshlx]获取为各种类型的设置数据
SbbjGetList({this.hyshlx = 'sbbj', Key key}) : super(key: key);
String hyshlx;
_SbbjPageState createState() => _SbbjPageState();
}
class _SbbjPageState extends State<SbbjGetList> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void dispose() {
_controller.dispose(); //销毁控制器
super.dispose();
}
@override
void initState() {
hyshlx = widget.hyshlx;
iPage = 0;
listSbbjGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList().then((value) {
listSbbjGetList2 = value;
//按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
});
///从接口 mapHyshlx[theHyshlx]['api'] 获取指定类型第 page 页的列表数据,返回 list
///获取点位信息数据
listDwinfoGetList2.clear();
getThePageList(theHyshlx: 'dwxx').then((value) {
listDwinfoGetList2 = value;
print('listDwinfoGetList2 = \n$listDwinfoGetList2');
});
//监听设备管理信息数据更新事件
eventBus.on<SbglDataUpdateEvent>().listen((event) async {
print(event.str);
iPage = 0;
listSbbjGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList().then((value) {
listSbbjGetList2 = value;
//按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
});
});
super.initState();
}
// List listSbbjGetList2 = [
// {
// "id": 1196,
// "bjlx": "风扇",
// "content": "串口COM1获取风扇异常数据",
// "dwip": "172.16.3.12",
// "sbip": "192.168.1.10",
// "addtime": "2021-02-16 09:50:30",
// "workflow": 999
// },
// ];
Widget _getListTile(BuildContext context, indexRecord) {
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: Text(
"${(indexRecord + 1).toString()}. " +
getDate(listSbbjGetList2[indexRecord]['addtime']) +
',',
style: TextStyle(fontSize: 14)),
subtitle: Text(
getDwmc(listSbbjGetList2[indexRecord]['dwip']) +
',' +
(listSbbjGetList2[indexRecord]['workflow'] == 999 ? '已处理' : '待处理'),
style: TextStyle(fontSize: 14)),
trailing: Container(
width: 160,
child: Text(
'${listSbbjGetList2[indexRecord]['bjlx']}, 报警:${listSbbjGetList2[indexRecord]['content']}' +
', 设备IP:${listSbbjGetList2[indexRecord]['sbip']}' +
'ID:${listSbbjGetList2[indexRecord]['id'].toString()}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 14),
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {
int ret = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SbbjContent(
title: '设备报警信息',
index: indexRecord,
hyshlx: widget.hyshlx,
),
),
);
print('ret = $ret');
},
),
Divider(height: 1.0),
],
);
}
ScrollController _controller = ScrollController(); //ListView控制器
bool isLoading = false; //正在处理下载数据、跳转到首项、跳转到尾项等操作
int firstIndex = 0; //ListView当前显示页面首项0基序号
int lastIndex = 0; //ListView当前显示页面末项0基序号
int itemOnPage = 8; //估计一屏显示的项目数量
Widget getIconButton({IconData iconData, var onPressed, double iconSize = 22}) {
return SizedBox(
height: iconSize,
width: iconSize + 10,
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: Icon(iconData, size: iconSize, color: Colors.white),
onPressed: onPressed,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// automaticallyImplyLeading: false,
// centerTitle: true,
// //leading: Text(''),
// titleSpacing: 0.0,
// //设置title的左边距
// title: Padding(
// padding: EdgeInsets.only(left: 0, right: 0),
// child: Row(
// //mainAxisAlignment: MainAxisAlignment.start,
// children: [
// getIconAndTextButton(
// iconData: Icons.arrow_back,
// onPress: () {
// Navigator.pop(context);
// },
// ),
// Expanded(
// child: Text("${mapHyshlx[hyshlx]['text']}",
// textAlign: TextAlign.left,
// overflow: TextOverflow.ellipsis,
// style: widget.hyshlx == 'fhycx' ? TextStyle(fontSize: 14) : null),
// ),
// SizedBox(width: 5),
// ],
// ),
// ),
// actions: <Widget>[
// getDropdownButton(),
// SizedBox(width: 10),
// getIconButton(
// iconData: Icons.cloud_download,
// onPressed: !isLoading
// ? () async {
// if (isLoading) {
// return;
// }
// isLoading = true;
// try_setState();
// //print("I Pressed the Iconbutton");
// int oldItems = listSbbjGetList2.length;
// for (int i = 0; i < 10; i++) {
// List list = await getPageList();
// if (list.length > 0) {
// listSbbjGetList2.addAll(list); //加载累加
// } else {
// break;
// }
// }
// Future.delayed(const Duration(milliseconds: 1000), () async {
// if (listSbbjGetList2.length > oldItems) {
// eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
// Fluttertoast.showToast(
// msg: '新增 ${listSbbjGetList2.length - oldItems} 条数据下载完成!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
//
// //按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
// _listSort();
// }
// isLoading = false;
// try_setState();
// });
// }
// : null,
// ),
// getIconButton(
// iconData: Icons.vertical_align_top_outlined,
// onPressed: (!isLoading && (firstIndex > 0)) //未到顶部
// ? () async {
// if (isLoading) {
// return;
// }
// isLoading = true;
// try_setState();
//
// //必须延时执行,否则不能及时完成按钮状态更新
// Timer(
// Duration(milliseconds: 500),
// () {
// _controller.jumpTo(_controller.position.minScrollExtent);
// },
// );
//
// Timer(
// Duration(milliseconds: 1000),
// () {
// // Fluttertoast.showToast(
// // msg: '已经跳转到开头记录!',
// // toastLength: Toast.LENGTH_SHORT,
// // gravity: ToastGravity.CENTER,
// // );
// firstIndex = 0;
// lastIndex = itemOnPage - 1; //0基序号,所以需要减1
// isLoading = false;
// try_setState();
// },
// );
// }
// : null,
// ),
// getIconButton(
// iconData: Icons.vertical_align_bottom_outlined,
// onPressed: (!isLoading && (lastIndex < listSbbjGetList2.length)) //未到尾部
// ? () async {
// if (isLoading) {
// return;
// }
// isLoading = true;
// try_setState();
//
// //必须延时执行,否则不能及时完成按钮状态更新
// Timer(
// Duration(milliseconds: 500),
// () {
// _controller.jumpTo(_controller.position.maxScrollExtent);
// },
// );
//
// Timer(
// Duration(milliseconds: 1000),
// () {
// // Fluttertoast.showToast(
// // msg: '已经跳转到末尾记录!',
// // toastLength: Toast.LENGTH_SHORT,
// // gravity: ToastGravity.CENTER,
// // );
// //0基序号需要减1,再加上底部有一组显示信息,所以需要减2
// firstIndex = listSbbjGetList2.length - itemOnPage - 2;
// lastIndex = listSbbjGetList2.length;
// isLoading = false;
// try_setState();
// },
// );
// }
// : null,
// ),
// ],
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // here the desired height
child: AppBar(
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),
// ),
),
),
//1、第1行组件,工具按钮
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);
},
),
//1.2、title 显示控制
Expanded(
child: Text("${mapHyshlx[hyshlx]['text']}",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.white, fontSize: 20)),
),
SizedBox(width: 5),
],
),
),
//1.3、尾部工具按钮组
actions: <Widget>[
//getDropdownButton(),
getIconButton(
iconData: Icons.cloud_download,
onPressed: !isLoading
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//print("I Pressed the Iconbutton");
int oldItems = listSbbjGetList2.length;
for (int i = 0; i < 10; i++) {
List list = await getPageList();
if (list.length > 0) {
listSbbjGetList2.addAll(list); //加载累加
} else {
break;
}
}
Future.delayed(const Duration(milliseconds: 1000), () async {
if (listSbbjGetList2.length > oldItems) {
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
Fluttertoast.showToast(
msg: '新增 ${listSbbjGetList2.length - oldItems} 条数据下载完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
//按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
_listSort();
//_controller.jumpTo(1); // _controller.position 能够有效刷新,人眼可察觉的滚动
_controller.jumpTo(0.001); // _controller.position 完美解决有效刷新,而且人眼不可见察觉滚动
//第二次跳转必须延时,否则 _controller.position 不能有效刷新
Future.delayed(Duration(milliseconds: 500), () {
_controller.jumpTo(_controller.position.minScrollExtent);
});
}
isLoading = false;
try_setState();
});
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
getIconButton(
iconData: Icons.vertical_align_top_outlined,
onPressed: (!isLoading && (firstIndex > 0)) //未到顶部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.minScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到开头记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
firstIndex = 0;
lastIndex = itemOnPage - 1; //0基序号,所以需要减1
isLoading = false;
try_setState();
},
);
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
getIconButton(
iconData: Icons.vertical_align_bottom_outlined,
onPressed: (!isLoading && (lastIndex < listSbbjGetList2.length)) //未到尾部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.maxScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到末尾记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
//0基序号需要减1,再加上底部有一组显示信息,所以需要减2
firstIndex = listSbbjGetList2.length - itemOnPage - 2;
lastIndex = listSbbjGetList2.length;
isLoading = false;
try_setState();
},
);
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
],
),
),
body: Column(children: [
//2、第2行排序按钮
Container(
height: ScreenUtil().setHeight(142),
decoration: new BoxDecoration(border: new Border.all(color: Colors.red)),
child: Row(
children: [
SizedBox(width: ScreenUtil().setWidth(50)),
Text('排序', style: TextStyle(fontSize: 18)),
Expanded(child: SizedBox.shrink()),
getDropdownButton(),
SizedBox(width: ScreenUtil().setWidth(20)),
],
),
),
(0 == listSbbjGetList2.length)
? getMoreWidget(color: Colors.black38)
: Expanded(
child: EasyRefresh(
child: ListView.custom(
//itemExtent: 75.0, //列表项高度
controller: _controller,
cacheExtent: 1.0, // 只有设置了1.0 才能够准确的标记 position 位置
childrenDelegate: MyChildrenDelegate(
_getListTile,
childCount: listSbbjGetList2.length,
),
),
onRefresh: () async {
// await Future.delayed(const Duration(seconds: 1), () async {
// iPage = 0;
// //await getWzxxGetList();
// listSbbjGetList2 = await getPageList();
// eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
// });
},
onLoad: () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
print('iPage = $iPage');
await Future.delayed(const Duration(seconds: 1), () async {
//await getWzxxGetList();
List list = await getPageList();
if (list.length > 0) {
listSbbjGetList2.addAll(list); //加载累加
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
}
isLoading = false;
try_setState();
});
},
header: getHeader(),
footer: getFooter(),
),
),
]),
);
}
//DropdownButton需要设置初始值的时候,初始值必须是显示列表里面的值,否则会导致弹出框异常。
// 比如说:你的DropdownButton的items属性使用的是list这个列表里面的值,那么你的初始值应该在list[index]里面取,要不就会报错。
//
// There should be exactly one item with [DropdownButton]'s value: 0.0.
// Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
// 'package:flutter/src/material/dropdown.dart':
// Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
// items.where((DropdownMenuItem<T> item) {
// return item.value == value;
// }).length == 1'
String _selectedValue = '添加时间';
bool _descending = true; //默认生效排列
Widget _getImage(String _image) {
return Container(
margin: EdgeInsets.only(),
height: ScreenUtil().setWidth(48),
width: ScreenUtil().setWidth(48),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(_image,
fit: BoxFit.cover, color: isLoading ? Theme.of(context).disabledColor : null));
}
//按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
Future _listSort({bool bShowToast = false}) {
if (!isLoading && listSbbjGetList2.length > 0) {
isLoading = true;
try_setState();
switch (_selectedValue) {
default:
if (_descending) {
//按_selectedValue排序,降序
listSbbjGetList2.sort((a, b) =>
(b[mapWzxxDataText[_selectedValue]]).compareTo(a[mapWzxxDataText[_selectedValue]]));
} else {
//按_selectedValue排序,升序
listSbbjGetList2.sort((a, b) =>
(a[mapWzxxDataText[_selectedValue]]).compareTo(b[mapWzxxDataText[_selectedValue]]));
}
break;
}
Future.delayed(const Duration(milliseconds: 1000), () {
if (bShowToast) {
Fluttertoast.showToast(
msg: '按“${_selectedValue}”${_descending ? '降序' : '升序'}排列完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
}
isLoading = false;
try_setState(); //避免如下异常报错
});
}
}
Widget getDropdownButtonItemText(String item) {
return Padding(
padding: EdgeInsets.only(bottom: ScreenUtil().setHeight(3)),
child: Row(
//crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment(0, 0),
padding: EdgeInsets.only(top: ScreenUtil().setHeight(10)),
child: item == _selectedValue
? _descending
? _getImage('assets/images/descending.png')
: _getImage('assets/images/ascending.png')
// ? Icon(Icons.arrow_downward_outlined, size: 20)
// : Icon(Icons.arrow_upward_outlined, size: 20)
: SizedBox(),
),
SizedBox(
width: ScreenUtil().setWidth(10),
),
Container(
//alignment: Alignment(0, -1),
child: Text(item,
style: TextStyle(
fontSize: 18,
color: isLoading
? Theme.of(context).disabledColor
: item == _selectedValue
? Colors.blue
: null)),
// style: isLoading
// ? TextStyle(color: Theme.of(context).disabledColor)
// : (item == _selectedValue ? TextStyle(color: Colors.blue) : null)),
),
],
),
);
}
// List listSbbjGetList2 = [
// {
// "id": 1196,
// "bjlx": "风扇",
// "content": "串口COM1获取风扇异常数据",
// "dwip": "172.16.3.12",
// "sbip": "192.168.1.10",
// "addtime": "2021-02-16 09:50:30",
// "workflow": 999
// },
// ];
Widget getDropdownButton() {
//DropdownMenuItem项目文本list
List<String> itemList = [
'添加时间',
'主键ID',
'设备类型',
'报警内容',
'点位IP',
'设备IP',
'处理状态',
];
//添加按'推送状态'排序
if (hyshlx != 'sbbj') {
// itemList.removeLast();
// itemList.addAll(['推送状态', '主键ID']);
}
//获取DropdownMenuItem项目组件list
List<DropdownMenuItem<String>> _dropDownMenuItems =
itemList.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>(
value: item,
child: getDropdownButtonItemText(item),
);
}).toList();
return Padding(
padding: EdgeInsets.only(top: 0, bottom: 0),
child: Container(
alignment: Alignment(0, 0),
width: 135,
margin: EdgeInsets.only(bottom: 0),
padding: EdgeInsets.only(left: 0, bottom: 0),
// decoration: BoxDecoration(
// border: Border.all(width: 0),
// //边框圆角设置
// borderRadius:
// BorderRadius.vertical(top: Radius.elliptical(2, 2), bottom: Radius.elliptical(2, 2)),
// ),
//DropdownButton默认有一条下划线,DropdownButtonHideUnderline去除下划线
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
iconSize: ScreenUtil().setHeight(100),
//itemHeight: ScreenUtil().setHeight(372),
isDense: true,
value: _selectedValue,
items: _dropDownMenuItems,
onChanged: (String selectedValue) {
if (isLoading) {
return;
}
if (_selectedValue == selectedValue) {
_descending = !_descending;
} else {
_descending = true;
}
_selectedValue = selectedValue;
print('_selectedValue = $_selectedValue');
//按抓拍次数排序,降序
// listSbbjGetList2.sort((a, b) => (b["yjxx_id"].split(',').length.toString())
// .compareTo(a["yjxx_id"].split(',').length.toString()));
//按照用户选择的_selectedValue、_descending对listSbbjGetList2进行排序,并延时更新
_listSort();
},
),
),
),
);
}
}
//https://blog.csdn.net/u014803467/article/details/103750018
//Flutter 使用SliverChildBuilderDelegate获取ListView的第一个和最后一个可见Item序号
// 秋名山交警X 2019-12-28 23:52:52
class _SaltedValueKey extends ValueKey<Key> {
const _SaltedValueKey(Key key)
: assert(key != null),
super(key);
}
class MyChildrenDelegate extends SliverChildBuilderDelegate {
MyChildrenDelegate(
Widget Function(BuildContext, int) builder, {
int childCount,
bool addAutomaticKeepAlive = true,
bool addRepaintBoundaries = true,
}) : super(builder,
childCount: childCount,
addAutomaticKeepAlives: addAutomaticKeepAlive,
addRepaintBoundaries: addRepaintBoundaries);
// Return a Widget for the given Exception
Widget _createErrorWidget(dynamic exception, StackTrace stackTrace) {
final FlutterErrorDetails details = FlutterErrorDetails(
exception: exception,
stack: stackTrace,
library: 'widgets library',
context: ErrorDescription('building'),
);
FlutterError.reportError(details);
return ErrorWidget.builder(details);
}
@override
Widget build(BuildContext context, int index) {
assert(builder != null);
if (index < 0 || (childCount != null && index >= childCount)) return null;
Widget child;
try {
child = builder(context, index);
} catch (exception, stackTrace) {
child = _createErrorWidget(exception, stackTrace);
}
if (child == null) return null;
final Key key = child.key != null ? _SaltedValueKey(child.key) : null;
if (addRepaintBoundaries) child = RepaintBoundary(child: child);
if (addSemanticIndexes) {
final int semanticIndex = semanticIndexCallback(child, index);
if (semanticIndex != null)
child = IndexedSemantics(index: semanticIndex + semanticIndexOffset, child: child);
}
if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child);
return KeyedSubtree(child: child, key: key);
}
@override
void didFinishLayout(int _firstIndex, int _lastIndex) {
// TODO: implement didFinishLayout
super.didFinishLayout(_firstIndex, _lastIndex);
}
///监听 在可见的列表中 显示的第一个位置和最后一个位置
@override
double estimateMaxScrollOffset(
int _firstIndex, int _lastIndex, double _leadingScrollOffset, double _trailingScrollOffset) {
//违章信息Listview滚动广播
eventBus.fire(WzxxDataScrollEvent(_firstIndex, _lastIndex));
return super.estimateMaxScrollOffset(
_firstIndex, _lastIndex, _leadingScrollOffset, _trailingScrollOffset);
}
}
+476
View File
@@ -0,0 +1,476 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/screen_util.dart';
import 'package:hyzp_ybqx/components/commonFun.dart';
import '../../../components/customDialogH.dart';
import '../../../components/customDialogJ.dart';
import '../../../components/dioFun.dart';
//import 'package:hyzp_ybqx/widget/player_pro.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
class DwxxContent extends StatefulWidget {
//SbglContent({Key key, this.title, this.mapData}) : super(key: key);
DwxxContent({
@required this.title,
@required this.index,
@required this.hyshlx,
Key key,
}) : super(key: key);
String title;
int index = -1;
String hyshlx;
_SbglPageState createState() => _SbglPageState();
}
class _SbglPageState extends State<DwxxContent> {
Map _mapGetSbglGetDataText = {
"id": "主键ID",
"dwip": "点位IP",
"dwmc": '点位名称',
"dwbh": '点位编号',
"dwinfo": '点位信息',
"dwzb": '点位坐标',
"dwms": '点位描述',
"dwzt": '点位状态',
};
//点位信息数据
Map _mapGetSbglGetData = {
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "江北振兴大道",
"dwbh": 1,
"dwinfo": "江北振兴大道入城方向",
"dwzb": "104.607091|28.807061",
"dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆",
"dwzt": "正常"
};
List<TextEditingController> _listController = [];
int listLen = 0;
String nums = '';
int _selectedRadio = 0;
void initState() {
// TODO: implement initState
super.initState();
listLen = listSbglGetList2.length;
getListFlields();
}
//监听登录页面销毁的事件
dispose() {
_controller.dispose();
getingDwVideo = false;
super.dispose();
}
getListFlields() async {
//获取指定id的sbgl记录数据返回 _mapGetSbglGetData。由于 sbgl 信息需要进行查核处理,所以要重新读取最新的记录数据
// _mapGetSbglGetData =
// await getLedXsxxGetData(id: listSbglGetList2[widget.index]['id'], theSbgllx: widget.hyshlx);
_mapGetSbglGetData = listSbglGetList2[widget.index];
print('_mapGetSbglGetData = ${_mapGetSbglGetData}');
//_mapGetSbglGetData = listSbglGetList2[widget.index];
_listController = List.generate(_mapGetSbglGetData.length, (index) {
String key = _mapGetSbglGetData.keys.elementAt(index);
String strContent = _mapGetSbglGetData[key].toString();
//时间戳转换
if (strContent.isNotEmpty && 'addtime' == key) {
strContent = getDate(strContent);
}
//workflow转换
if (strContent.isNotEmpty && 'workflow' == key) {
strContent = strContent == '999' ? '已处理' : '待处理';
}
var controller = TextEditingController(text: strContent);
controller.selection = TextSelection.fromPosition(
TextPosition(affinity: TextAffinity.downstream, offset: '${controller.text}'.length),
);
return controller;
});
getPreBtn_NextBtn();
nums = '${(widget.index + 1).toString()} / $listLen';
setState(() {});
}
Widget getTrail(String key, int index, double widthTrail) {
if (0 == _listController.length) {
return Container(width: widthTrail);
}
//print('key = $key');
if ('avatar' == key) {
imagePath = _listController[index].text;
return getAvatar(width: widthTrail);
} else {
return Container(
alignment: Alignment(-1, 0),
//widthTrail = 400报错,360刚能显示,300换行,260
width: widthTrail,
//解决信息显示不全问题
child: Text(_listController[index].text,
style: TextStyle(fontSize: 'dwms' == key ? 14 : 16), textAlign: TextAlign.left),
);
}
}
Widget getTrail0(String key, int index, double widthTrail) {
if (0 == _listController.length) {
return Container(width: widthTrail);
}
//print('key = $key');
if ('avatar' == key) {
imagePath = _listController[index].text;
return getAvatar(width: widthTrail);
} else {
return Container(
alignment: Alignment(1, 0),
//widthTrail = 400报错,360刚能显示,300换行,260
width: widthTrail,
child: TextField(
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 16),
decoration: InputDecoration(
//hintText: '請輸入字段信息',
border: InputBorder.none, //TextField去掉下划线
contentPadding: EdgeInsets.only(right: 0),
),
controller: _listController[index],
enabled: false,
//利用控制器初始化文本
onChanged: (value) {},
),
);
}
}
Future<String> doContacts() async {
bFlash = false;
return showDialog(
context: context,
builder: (BuildContext context) {
return customDialogH(
title: "请选择头像修改操作",
content: "头像修改",
index: 0,
);
},
).then((value) {
imagePath = value;
print('Page2_Contacts bFlash = $bFlash');
if (imagePath.isNotEmpty) {
_image = Image.file(File(imagePath), fit: BoxFit.cover);
setState(() {});
}
});
}
//Image.file(this._image);
String imagePath = '';
Image _image;
Widget getAvatar({double width = 260.0}) {
if (imagePath.isEmpty) {
_image = Image.asset('assets/images/user.png', fit: BoxFit.cover);
} else {
String head = imagePath.substring(0, 4).trim().toLowerCase();
if ('http' == head) {
_image = Image.network(imagePath, fit: BoxFit.cover);
}
}
return Container(
alignment: Alignment(-1, 0),
width: width,
child: InkWell(
onTap: () async {
doContacts();
},
child: Container(
width: 40,
child: _image,
),
),
);
}
//添加、修改、删除联系人对话框
doContacts2(String key, int index) async {
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogJ(
theKey: key,
index: index,
);
},
);
}
static onNullFun() {}
Widget _getListTile(String key, int index, double widthTrail,
{onTapFun = onNullFun, onLongPressFun = onNullFun, size = 16.0}) {
//print('key = $key, index = $index');
return ListTile(
//leading: new Icon(Icons.phone),
title: Text((index + 1).toString() + ". " + '${_mapGetSbglGetDataText[key]} :',
style: TextStyle(fontSize: 16)),
trailing: getTrail(key, index, widthTrail),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {
// print('第 $index 项被点击了');
// await doContacts2(key, index);
// if ('avatar' == key) {
// print('选择图片或拍照');
// await doContacts();
// }
},
onLongPress: () {},
);
}
TextEditingController _controller = TextEditingController.fromValue(TextEditingValue(
text: '已做简单处理。低级故障,不影响系统运行',
// 保持光标在最后
selection: TextSelection.fromPosition(
TextPosition(affinity: TextAffinity.downstream, offset: '已处理'.length))));
double _heigth = 30;
double _fontSize = 16;
double _marginLeft = 15;
@override
Widget build(BuildContext context) {
bool bCheck = _mapGetSbglGetData['workflow'] == 999; //已处理
return Scaffold(
// appBar: AppBar(
// title: Text("设备点位信息详情($nums)"),
// centerTitle: true,
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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.center,
children: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
getingDwVideo = false;
Navigator.pop(context);
},
),
Expanded(
child: Text("设备点位信息详情($nums)",
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 50),
],
),
),
),
),
body: Container(
child: Column(
children: <Widget>[
Expanded(
//https://www.it1352.com/2028416.html
//用Map而不是List的Flutter ListView.builder(Flutter listview with Map instead of List)
//使用ListView.separated设置分割线ListView.separated(
//child: ListView.separated( //这种方式不能设置每项高度,每页只能有7项
child: ListView.builder(
//这种方式可以通过itemExtent设置每项高度,每页可以有9项
//separatorBuilder: (BuildContext context, int index) => index %2 ==0? Divider(color: Colors.green) : Divider(color: Colors.red),//index为偶数,创建绿色分割线;index为奇数,则创建红色分割线
//separatorBuilder: (BuildContext context, int index) => Divider(),
//itemExtent: 57.0, //列表项高度。56越界、57刚好。还是自动计算最好
itemCount: _mapGetSbglGetData.length,
itemBuilder: (BuildContext context, index) {
String key = _mapGetSbglGetData.keys.elementAt(index);
return Column(
children: <Widget>[
_getListTile(key, index, 200.0),
Divider(
height: 1.0,
),
],
);
},
),
),
//7、得到核查处理意见组件
Divider(height: 1.0, color: Colors.blue),
SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// getBtnSizeX(
// text: "复制",
// onPressedFun: () {
// // Flutter 复制文本到剪贴板
// Clipboard.setData(
// ClipboardData(text: listSbglGetList2[widget.index].toString()));
// Fluttertoast.showToast(msg: '点位信息已复制到剪贴板', gravity: ToastGravity.CENTER);
// }),
//getBtnSizeX(text: "删除", onPressedFun: () async {}),
getBtnSizeX(
text: "视频",
onPressedFun: () {
//getDwspUrl(index: widget.index, context: context);
getDwspUrlNew(indexRecord: widget.index, context: context);
// getDwspUrl(index: widget.index + 1).then((url) {
// print('index = ${(widget.index + 1).toString()}, url = $url');
// urlnew = url;
//
// //获取视频地址失败
// if (!isVideoUrl(urlnew)) {
// return;
// }
//
// var ret = Navigator.of(context).push(MaterialPageRoute(
// builder: (context) => PlayerPro(
// url: urlnew,
// title:
// '点位视频\n${(widget.index + 1)}、${listDwinfoGetList2[widget.index]['dwmc']}',
// //initVideoSize: Size(704.0, 576.0),
// )));
// print('ret = $ret');
// });
//getDwVideoUrl(index: widget.index);
//getData();
// Flutter 复制文本到剪贴板
// Clipboard.setData(
// ClipboardData(text: listSbglGetList2[widget.index].toString()));
// Fluttertoast.showToast(msg: '点位信息已复制到剪贴板', gravity: ToastGravity.CENTER);
}),
preBtn,
nextBtn,
],
),
SizedBox(height: 20),
],
),
),
);
}
//解决第一次进入报错问题。因为getPreBtn_NextBtn()还未执行,preBtn和nextBtn为空
Widget preBtn = Container(
color: Colors.white12, //onPressedFun为null时无效
width: 70.0,
height: 35.0,
child: RaisedButton(
padding: EdgeInsets.all(0),
textColor: Colors.black,
child: Text('上一条'),
onPressed: null,
),
);
Widget nextBtn = Container(
color: Colors.white12, //onPressedFun为null时无效
width: 70.0,
height: 35.0,
child: RaisedButton(
padding: EdgeInsets.all(0),
textColor: Colors.black,
child: Text('下一条'),
onPressed: null,
),
);
getPreBtn_NextBtn() {
preBtn = getBtnSizeX(
text: "上一条",
onPressedFun: null,
);
nextBtn = getBtnSizeX(
text: "下一条",
onPressedFun: null,
);
if (widget.index > 0 && listLen > 0) {
preBtn = getBtnSizeX(
text: "上一条",
onPressedFun: () async {
if (widget.index > 0) {
widget.index--;
getListFlields();
}
},
);
}
if (widget.index < (listLen - 1) && listLen > 0) {
nextBtn = getBtnSizeX(
text: "下一条",
onPressedFun: () async {
if (widget.index < listLen - 1) {
widget.index++;
getListFlields();
}
},
);
}
}
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,
),
);
}
}
+820
View File
@@ -0,0 +1,820 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'dwxx_content.dart';
import '../../../components/dioFun.dart';
import '../../../components/hyxx_data_handle.dart';
import '../../../components/commonFun.dart';
import '../../../services/EventBus.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import '../../../components/doJSON.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
//sbgl是本项目中“设备管理”的统一缩写
class DwxxGetList extends StatefulWidget {
//hyshlx为黑烟审核类型,处理sbgl信息。mapHyshlx[hyshlx]获取为各种类型的设置数据
DwxxGetList({this.hyshlx = 'dwxx', Key key}) : super(key: key);
String hyshlx;
_SbglPageState createState() => _SbglPageState();
}
class _SbglPageState extends State<DwxxGetList> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void dispose() {
_controller.dispose(); //销毁控制器
super.dispose();
}
@override
void initState() {
hyshlx = widget.hyshlx;
iPage = 0;
listSbglGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList().then((value) {
listSbglGetList2 = value;
//按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
//为播放点位视频读取数据
print('listDwspGetList2 = ${listDwspGetList2}');
listDwspGetList2 = listSbglGetList2;
listDwinfoGetList2 = listSbglGetList2;
print('listDwspGetList2 = ${listDwspGetList2}');
});
// ///从接口 mapHyshlx[theHyshlx]['api'] 获取指定类型第 page 页的列表数据,返回 list
// ///获取点位信息数据
// listDwinfoGetList2.clear();
// getThePageList(theHyshlx: 'dwxx').then((value) {
// listDwinfoGetList2 = value;
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// });
//监听设备管理信息数据更新事件
eventBus.on<SbglDataUpdateEvent>().listen((event) async {
print(event.str);
iPage = 0;
listSbglGetList2.clear();
///从接口 mapHyshlx[hyshlx]['api'] 获取第 iPage 页的列表数据,返回 list
getPageList().then((value) {
listSbglGetList2 = value;
//按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
_listSort();
firstIndex = 0;
lastIndex = 7;
});
});
super.initState();
}
//点位信息数据
//{
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆",
// "dwzt": "正常"
//},
// Widget getDropdownButton() {
// //DropdownMenuItem项目文本list
// List<String> itemList = [
// '主键ID',
// '点位IP',
// '点位名称',
// '点位编号',
// '点位信息',
// '点位坐标',
// '点位描述',
// '点位状态',
// ];
Widget _getListTile(BuildContext context, indexRecord) {
List listCoordinate = listSbglGetList2[indexRecord]["dwzb"].trim().split('|');
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: Text(
"${listSbglGetList2[indexRecord]['dwbh'].toString()}. ${listSbglGetList2[indexRecord]['dwmc']}",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
subtitle: Text(
'dwIP:${listSbglGetList2[indexRecord]['dwip']},${listSbglGetList2[indexRecord]['dwzt']}',
style: TextStyle(fontSize: 14)),
trailing: Container(
width: 160,
child: Text(
'${listSbglGetList2[indexRecord]['dwms']}' +
', 经纬度:${listCoordinate[0]}、${listCoordinate[1]}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
//textAlign: TextAlign.right,
style: TextStyle(fontSize: 14),
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {
int ret = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DwxxContent(
title: '设备管理信息详情',
index: indexRecord,
hyshlx: widget.hyshlx,
),
),
);
print('ret = $ret');
},
),
Divider(height: 1.0),
],
);
}
ScrollController _controller = ScrollController(); //ListView控制器
bool isLoading = false; //正在处理下载数据、跳转到首项、跳转到尾项等操作
int firstIndex = 0; //ListView当前显示页面首项0基序号
int lastIndex = 0; //ListView当前显示页面末项0基序号
int itemOnPage = 8; //估计一屏显示的项目数量
Widget getIconButton({IconData iconData, var onPressed, double iconSize = 22}) {
return SizedBox(
height: iconSize,
width: iconSize + 10,
child: IconButton(
padding: EdgeInsets.all(0.0),
icon: Icon(iconData, size: iconSize, color: Colors.white),
onPressed: onPressed,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// automaticallyImplyLeading: false,
// centerTitle: true,
// //leading: Text(''),
// titleSpacing: 0.0,
// //设置title的左边距
// title: Padding(
// padding: EdgeInsets.only(left: 0, right: 0),
// child: Row(
// //mainAxisAlignment: MainAxisAlignment.start,
// children: [
// getIconAndTextButton(
// iconData: Icons.arrow_back,
// onPress: () {
// Navigator.pop(context);
// },
// ),
// Expanded(
// child: Text("${mapHyshlx[hyshlx]['text']}",
// textAlign: TextAlign.left,
// overflow: TextOverflow.ellipsis,
// style: widget.hyshlx == 'fhycx' ? TextStyle(fontSize: 16) : null),
// ),
// SizedBox(width: 5),
// ],
// ),
// ),
// actions: <Widget>[
// getDropdownButton(),
// SizedBox(width: 10),
// // getIconButton(
// // iconData: Icons.cloud_download,
// // onPressed: !isLoading
// // ? () async {
// // if (isLoading) {
// // return;
// // }
// // isLoading = true;
// // try_setState();
// // //print("I Pressed the Iconbutton");
// // int oldItems = listSbglGetList2.length;
// // for (int i = 0; i < 10; i++) {
// // List list = await getPageList();
// // if (list.length > 0) {
// // listSbglGetList2.addAll(list); //加载累加
// // } else {
// // break;
// // }
// // }
// // Future.delayed(const Duration(milliseconds: 1000), () async {
// // if (listSbglGetList2.length > oldItems) {
// // eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
// // Fluttertoast.showToast(
// // msg: '新增 ${listSbglGetList2.length - oldItems} 条数据下载完成!',
// // toastLength: Toast.LENGTH_SHORT,
// // gravity: ToastGravity.CENTER,
// // );
// //
// // //按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
// // _listSort();
// // }
// // isLoading = false;
// // try_setState();
// // });
// // }
// // : null,
// // ),
// SizedBox(width: 10),
// getIconButton(
// iconData: Icons.vertical_align_top_outlined,
// onPressed: (!isLoading && (firstIndex > 0)) //未到顶部
// ? () async {
// if (isLoading) {
// return;
// }
// isLoading = true;
// try_setState();
//
// //必须延时执行,否则不能及时完成按钮状态更新
// Timer(
// Duration(milliseconds: 500),
// () {
// _controller.jumpTo(_controller.position.minScrollExtent);
// },
// );
//
// Timer(
// Duration(milliseconds: 1000),
// () {
// // Fluttertoast.showToast(
// // msg: '已经跳转到开头记录!',
// // toastLength: Toast.LENGTH_SHORT,
// // gravity: ToastGravity.CENTER,
// // );
// firstIndex = 0;
// lastIndex = itemOnPage - 1; //0基序号,所以需要减1
// isLoading = false;
// try_setState();
// },
// );
// }
// : null,
// ),
// SizedBox(width: 10),
// getIconButton(
// iconData: Icons.vertical_align_bottom_outlined,
// onPressed: (!isLoading && (lastIndex < listSbglGetList2.length)) //未到尾部
// ? () async {
// if (isLoading) {
// return;
// }
// isLoading = true;
// try_setState();
//
// //必须延时执行,否则不能及时完成按钮状态更新
// Timer(
// Duration(milliseconds: 500),
// () {
// _controller.jumpTo(_controller.position.maxScrollExtent);
// },
// );
//
// Timer(
// Duration(milliseconds: 1000),
// () {
// // Fluttertoast.showToast(
// // msg: '已经跳转到末尾记录!',
// // toastLength: Toast.LENGTH_SHORT,
// // gravity: ToastGravity.CENTER,
// // );
// //0基序号需要减1,再加上底部有一组显示信息,所以需要减2
// firstIndex = listSbglGetList2.length - itemOnPage - 2;
// lastIndex = listSbglGetList2.length;
// isLoading = false;
// try_setState();
// },
// );
// }
// : null,
// ),
// SizedBox(width: 10),
// ],
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // here the desired height
child: AppBar(
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),
// ),
),
),
//1、第1行组件,工具按钮
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);
},
),
//1.2、title 显示控制
Expanded(
child: Text("${mapHyshlx[hyshlx]['text']}",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.white, fontSize: 20)),
),
SizedBox(width: 5),
],
),
),
//1.3、尾部工具按钮组
actions: <Widget>[
//getDropdownButton(),
getIconButton(
iconData: Icons.cloud_download,
onPressed: !isLoading
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//print("I Pressed the Iconbutton");
int oldItems = listSbglGetList2.length;
for (int i = 0; i < 10; i++) {
List list = await getPageList();
if (list.length > 0) {
listSbglGetList2.addAll(list); //加载累加
} else {
break;
}
}
Future.delayed(const Duration(milliseconds: 1000), () async {
if (listSbglGetList2.length > oldItems) {
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
Fluttertoast.showToast(
msg: '新增 ${listSbglGetList2.length - oldItems} 条数据下载完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
//按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
_listSort();
//_controller.jumpTo(1); // _controller.position 能够有效刷新,人眼可察觉的滚动
_controller.jumpTo(0.001); // _controller.position 完美解决有效刷新,而且人眼不可见察觉滚动
//第二次跳转必须延时,否则 _controller.position 不能有效刷新
Future.delayed(Duration(milliseconds: 500), () {
_controller.jumpTo(_controller.position.minScrollExtent);
});
}
isLoading = false;
try_setState();
});
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
getIconButton(
iconData: Icons.vertical_align_top_outlined,
onPressed: (!isLoading && (firstIndex > 0)) //未到顶部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.minScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到开头记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
firstIndex = 0;
lastIndex = itemOnPage - 1; //0基序号,所以需要减1
isLoading = false;
try_setState();
},
);
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
getIconButton(
iconData: Icons.vertical_align_bottom_outlined,
onPressed: (!isLoading && (lastIndex < listSbglGetList2.length)) //未到尾部
? () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
//必须延时执行,否则不能及时完成按钮状态更新
Timer(
Duration(milliseconds: 500),
() {
_controller.jumpTo(_controller.position.maxScrollExtent);
},
);
Timer(
Duration(milliseconds: 1000),
() {
// Fluttertoast.showToast(
// msg: '已经跳转到末尾记录!',
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
// );
//0基序号需要减1,再加上底部有一组显示信息,所以需要减2
firstIndex = listSbglGetList2.length - itemOnPage - 2;
lastIndex = listSbglGetList2.length;
isLoading = false;
try_setState();
},
);
}
: null,
),
SizedBox(width: ScreenUtil().setWidth(32)),
],
),
),
body: Column(children: [
//2、第2行排序按钮
Container(
height: ScreenUtil().setHeight(142),
decoration: new BoxDecoration(border: new Border.all(color: Colors.red)),
child: Row(
children: [
SizedBox(width: ScreenUtil().setWidth(50)),
Text('排序', style: TextStyle(fontSize: 18)),
Expanded(child: SizedBox.shrink()),
getDropdownButton(),
SizedBox(width: ScreenUtil().setWidth(20)),
],
),
),
(0 == listSbglGetList2.length)
? getMoreWidget(color: Colors.black38)
: Expanded(
child: EasyRefresh(
child: ListView.custom(
//itemExtent: 75.0, //列表项高度
controller: _controller,
cacheExtent: 1.0, // 只有设置了1.0 才能够准确的标记 position 位置
childrenDelegate: MyChildrenDelegate(
_getListTile,
childCount: listSbglGetList2.length,
),
),
onRefresh: () async {
// await Future.delayed(const Duration(seconds: 1), () async {
// iPage = 0;
// //await getWzxxGetList();
// listSbglGetList2 = await getPageList();
// eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
// });
},
onLoad: () async {
if (isLoading) {
return;
}
isLoading = true;
try_setState();
print('iPage = $iPage');
await Future.delayed(const Duration(seconds: 1), () async {
//await getWzxxGetList();
List list = await getPageList();
if (list.length > 0) {
listSbglGetList2.addAll(list); //加载累加
eventBus.fire(WzxxDataAuditEvent('${mapHyshlx[hyshlx]['text']}数据已更新'));
}
isLoading = false;
try_setState();
});
},
header: getHeader(),
footer: getFooter(),
),
)
]),
);
}
//DropdownButton需要设置初始值的时候,初始值必须是显示列表里面的值,否则会导致弹出框异常。
// 比如说:你的DropdownButton的items属性使用的是list这个列表里面的值,那么你的初始值应该在list[index]里面取,要不就会报错。
//
// There should be exactly one item with [DropdownButton]'s value: 0.0.
// Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
// 'package:flutter/src/material/dropdown.dart':
// Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
// items.where((DropdownMenuItem<T> item) {
// return item.value == value;
// }).length == 1'
String _selectedValue = '点位编号';
bool _descending = false; //默认升序排列
Widget _getImage(String _image) {
return Container(
margin: EdgeInsets.only(),
height: ScreenUtil().setWidth(48),
width: ScreenUtil().setWidth(48),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(_image,
fit: BoxFit.cover, color: isLoading ? Theme.of(context).disabledColor : null));
}
//按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
Future _listSort({bool bShowToast = false}) {
if (!isLoading && listSbglGetList2.length > 0) {
isLoading = true;
try_setState();
switch (_selectedValue) {
default:
if (_descending) {
//按_selectedValue排序,降序
listSbglGetList2.sort((a, b) =>
(b[mapWzxxDataText[_selectedValue]]).compareTo(a[mapWzxxDataText[_selectedValue]]));
} else {
//按_selectedValue排序,升序
listSbglGetList2.sort((a, b) =>
(a[mapWzxxDataText[_selectedValue]]).compareTo(b[mapWzxxDataText[_selectedValue]]));
}
break;
}
Future.delayed(const Duration(milliseconds: 1000), () {
if (bShowToast) {
Fluttertoast.showToast(
msg: '按“${_selectedValue}”${_descending ? '降序' : '升序'}排列完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
}
isLoading = false;
try_setState(); //避免如下异常报错
});
}
}
Widget getDropdownButtonItemText(String item) {
return Padding(
padding: EdgeInsets.only(bottom: ScreenUtil().setHeight(3)),
child: Row(
//crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment(0, 0),
padding: EdgeInsets.only(top: ScreenUtil().setHeight(10)),
child: item == _selectedValue
? _descending
? _getImage('assets/images/descending.png')
: _getImage('assets/images/ascending.png')
// ? Icon(Icons.arrow_downward_outlined, size: 20)
// : Icon(Icons.arrow_upward_outlined, size: 20)
: SizedBox(),
),
SizedBox(
width: ScreenUtil().setWidth(10),
),
Container(
//alignment: Alignment(0, -1),
child: Text(item,
style: TextStyle(
fontSize: 18,
color: isLoading
? Theme.of(context).disabledColor
: item == _selectedValue
? Colors.blue
: null)),
// style: isLoading
// ? TextStyle(color: Theme.of(context).disabledColor)
// : (item == _selectedValue ? TextStyle(color: Colors.blue) : null)),
),
],
),
);
}
//点位信息数据
//{
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆",
// "dwzt": "正常"
//},
Widget getDropdownButton() {
//DropdownMenuItem项目文本list
List<String> itemList = [
'主键ID',
'点位IP',
'点位名称',
'点位编号',
'点位信息',
'点位坐标',
'点位描述',
'点位状态',
];
//添加按'推送状态'排序
if (hyshlx != 'dwxx') {
// itemList.removeLast();
// itemList.addAll(['推送状态', '主键ID']);
}
//获取DropdownMenuItem项目组件list
List<DropdownMenuItem<String>> _dropDownMenuItems =
itemList.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>(
value: item,
child: getDropdownButtonItemText(item),
);
}).toList();
return Padding(
padding: EdgeInsets.only(top: 0, bottom: 0),
child: Container(
alignment: Alignment(0, 0),
width: 135,
margin: EdgeInsets.only(bottom: 0),
padding: EdgeInsets.only(left: 0, bottom: 0),
// decoration: BoxDecoration(
// border: Border.all(width: 0),
// //边框圆角设置
// borderRadius:
// BorderRadius.vertical(top: Radius.elliptical(2, 2), bottom: Radius.elliptical(2, 2)),
// ),
//DropdownButton默认有一条下划线,DropdownButtonHideUnderline去除下划线
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
iconSize: ScreenUtil().setHeight(100),
//itemHeight: ScreenUtil().setHeight(372),
isDense: true,
value: _selectedValue,
items: _dropDownMenuItems,
onChanged: (String selectedValue) {
if (isLoading) {
return;
}
if (_selectedValue == selectedValue) {
_descending = !_descending;
} else {
_descending = true;
}
_selectedValue = selectedValue;
print('_selectedValue = $_selectedValue');
//按抓拍次数排序,降序
// listSbglGetList2.sort((a, b) => (b["yjxx_id"].split(',').length.toString())
// .compareTo(a["yjxx_id"].split(',').length.toString()));
//按照用户选择的_selectedValue、_descending对listSbglGetList2进行排序,并延时更新
_listSort();
},
),
),
),
);
}
}
//https://blog.csdn.net/u014803467/article/details/103750018
//Flutter 使用SliverChildBuilderDelegate获取ListView的第一个和最后一个可见Item序号
// 秋名山交警X 2019-12-28 23:52:52
class _SaltedValueKey extends ValueKey<Key> {
const _SaltedValueKey(Key key)
: assert(key != null),
super(key);
}
class MyChildrenDelegate extends SliverChildBuilderDelegate {
MyChildrenDelegate(
Widget Function(BuildContext, int) builder, {
int childCount,
bool addAutomaticKeepAlive = true,
bool addRepaintBoundaries = true,
}) : super(builder,
childCount: childCount,
addAutomaticKeepAlives: addAutomaticKeepAlive,
addRepaintBoundaries: addRepaintBoundaries);
// Return a Widget for the given Exception
Widget _createErrorWidget(dynamic exception, StackTrace stackTrace) {
final FlutterErrorDetails details = FlutterErrorDetails(
exception: exception,
stack: stackTrace,
library: 'widgets library',
context: ErrorDescription('building'),
);
FlutterError.reportError(details);
return ErrorWidget.builder(details);
}
@override
Widget build(BuildContext context, int index) {
assert(builder != null);
if (index < 0 || (childCount != null && index >= childCount)) return null;
Widget child;
try {
child = builder(context, index);
} catch (exception, stackTrace) {
child = _createErrorWidget(exception, stackTrace);
}
if (child == null) return null;
final Key key = child.key != null ? _SaltedValueKey(child.key) : null;
if (addRepaintBoundaries) child = RepaintBoundary(child: child);
if (addSemanticIndexes) {
final int semanticIndex = semanticIndexCallback(child, index);
if (semanticIndex != null)
child = IndexedSemantics(index: semanticIndex + semanticIndexOffset, child: child);
}
if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child);
return KeyedSubtree(child: child, key: key);
}
@override
void didFinishLayout(int _firstIndex, int _lastIndex) {
// TODO: implement didFinishLayout
super.didFinishLayout(_firstIndex, _lastIndex);
}
///监听 在可见的列表中 显示的第一个位置和最后一个位置
@override
double estimateMaxScrollOffset(
int _firstIndex, int _lastIndex, double _leadingScrollOffset, double _trailingScrollOffset) {
//违章信息Listview滚动广播
eventBus.fire(WzxxDataScrollEvent(_firstIndex, _lastIndex));
return super.estimateMaxScrollOffset(
_firstIndex, _lastIndex, _leadingScrollOffset, _trailingScrollOffset);
}
}
+688
View File
@@ -0,0 +1,688 @@
import 'package:hyzp_ybqx/components/commonFun.dart';
import 'package:hyzp_ybqx/components/dioFun.dart';
import 'package:hyzp_ybqx/components/hyxx_data_handle.dart';
import 'package:hyzp_ybqx/services/EventBus.dart';
///获取车流量日统计数据
bool cllRStatisDataGeting = false; //正在获取车流量日统计数据,禁止重入
bool cllRStatisDataOk = false; //listCllrtjStatis 中的数据是否准备好
//List listCllrtjStatis = [];
// [
// {
// "dwbh": 4,
// "dwmc": "一曼路",
// "dwip": "172.16.3.4"
// "all": "770742",
// "cllmx": [
// {
// "day": "2021-04-12",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "17760",
// "am": "1272",
// "pm": "3153"
// },
// {
// "day": "2021-04-11",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "18005",
// "am": "1677",
// "pm": "2275"
// },
// // ...
// ]
// },
// {
// "dwbh": 5,
// "dwmc": "柏溪收费站",
// "dwip": "172.16.3.5"
// "all": "770742",
// "cllmx": [
// {
// "day": "2021-04-12",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "17760",
// "am": "1272",
// "pm": "3153"
// },
// {
// "day": "2021-04-11",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "18005",
// "am": "1677",
// "pm": "2275"
// },
// // ...
// ]
// },
// ]
///获取抓拍统计数据
List listZptjStatis = [];
///获取审核黑烟车统计数据
List listSh_hyc_tjStatis = [];
///获取审核黑烟车统计数据
List listClltjStatis = [];
///获取车流量日统计数据
List listCllrtjStatis = [];
bool statisDataOk = false; //listCllrtjStatis 中的数据是否准备好
Map mapCllrtjStatis = {};
/*
{
"total": 6635167,
"am": 713074,
"pm": 981656,
"view": [
{
"dwip": "172.16.3.1",
"dw_all": 701120,
"dw_am": 76210,
"dw_pm": 105153,
"cllmx": [
{
"day": "2021-05-25",
"am_order": "0730:0930",
"pm_order": "1730:1930",
"all": "24190",
"am": "2148",
"pm": "5173"
},
{
"day": "2021-05-24",
"am_order": "0730:0930",
"pm_order": "1730:1930",
"all": "20254",
"am": "1825",
"pm": "3975"
},
...
},
{
"dwip": "172.16.3.2",
"dw_all": 533990,
"dw_am": 65276,
"dw_pm": 78055,
"cllmx": [
{
"day": "2021-05-25",
"am_order": "0730:0930",
"pm_order": "1730:1930",
"all": "16355",
"am": "1375",
"pm": "3029"
},
{
"day": "2021-05-24",
"am_order": "0730:0930",
"pm_order": "1730:1930",
"all": "15997",
"am": "1797",
"pm": "2216"
},
...
*/
// [
// {
// "dwbh": 4,
// "dwmc": "一曼路",
// "dwip": "172.16.3.4"
// "all": "770742",
// "cllmx": [
// {
// "day": "2021-04-12",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "17760",
// "am": "1272",
// "pm": "3153"
// },
// {
// "day": "2021-04-11",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "18005",
// "am": "1677",
// "pm": "2275"
// },
// // ...
// ]
// },
// {
// "dwbh": 5,
// "dwmc": "柏溪收费站",
// "dwip": "172.16.3.5"
// "all": "770742",
// "cllmx": [
// {
// "day": "2021-04-12",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "17760",
// "am": "1272",
// "pm": "3153"
// },
// {
// "day": "2021-04-11",
// "am_order": "0730:0930",
// "pm_order": "1730:1930",
// "all": "18005",
// "am": "1677",
// "pm": "2275"
// },
// // ...
// ]
// },
// ]
// 一次性获取所有点位的统计数据存入 listCllrtjStatis
Future getCllrtjStatisNew(String statisType) async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listCllrtjStatis.clear();
mapCllrtjStatis = await getStatisData(statisType: statisType);
listCllrtjStatis = mapCllrtjStatis["view"];
// int len = listDwinfoGetList2.length;
// for (int i = 0; i < len; i++) {
// Map map = await getStatisData(statisType: statisType, ip: listDwinfoGetList2[i]['dwip']);
// map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
// map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
// map['dwip'] = listDwinfoGetList2[i]['dwip'];
// listCllrtjStatis.add(map);
// }
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
//遍历 listDwinfoGetList2 中所有点位,得到对应点位 ip 的统计数据存入 listCllrtjStatis
Future getCllrtjStatis(String statisType) async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listCllrtjStatis.clear();
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map = await getStatisData(statisType: statisType, ip: listDwinfoGetList2[i]['dwip']);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listCllrtjStatis.add(map);
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
//遍历 listDwinfoGetList2 中所有点位,得到对应点位 ip 的统计数据存入 listZptjStatis
Future getZptjStatis(String statisType) async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listZptjStatis.clear();
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map = await getStatisData(statisType: statisType, ip: listDwinfoGetList2[i]['dwip']);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listZptjStatis.add(map);
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
//在Dart语言中,如何通过值获取MAP键?mapTjDataText
String getKey(String value) {
String key = mapTjDataText.keys.firstWhere((k) => mapTjDataText[k] == value, orElse: () => null);
}
Map<String, String> mapTjDataText = {
"dwmc": '点位名称',
"dwbh": '点位编号',
"dwip": '点位IP',
"today": '今日',
"all": '总共',
"total": '已审核',
"sends": '已推送'
};
//////////////////////////////////////////////////////////////////
///独立获取抓拍统计数据
List listZptjStatisAlone = [];
List listTodayZpjl = []; //今日抓拍记录列表
//遍历 listDwinfoGetList2 中所有点位,独立得到对应点位 ip 的统计数据存入 listZptjStatisNew
Future getZptjStatisAlone() async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listZptjStatisAlone.clear();
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map = await getStatisData(statisType: 'zptj', ip: listDwinfoGetList2[i]['dwip']);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listZptjStatisAlone.add(map);
// if (listZptjStatisAlone.length >= dwSum) {
// //发送统计数据已更新广播
// eventBus.fire(StatisDataUpdate('统计数据已更新'));
// }
getAllSum('today', listZptjStatisAlone).then((value) {
//mapStatisInfo['今日抓拍'] = value[1];
listTodayZpjl = value[2];
//try_setState();
});
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
///独立获取今日审核统计数据
List listTodayShtj = [];
List listTodayChjl = []; //今日初审记录列表
List listTodayFhjl = []; //今日复审记录列表
List listTodayTsjl = []; //今日推送记录列表
//遍历 listDwinfoGetList2 中所有点位,独立得到对应点位 ip 的统计数据存入 listShtjStatisNew
Future getTodayShtj() async {
//今日审核统计数据
//{
// "total": 0,"today": 0,
// "sends": 0,"all": 72
// "csnum": 0,"dwbh": 1,
// "fsnum": 0"dwmc": "江北振兴大道",
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listTodayShtj.clear();
DateTime dateTime = DateTime.now();
String _mouth = dateTime.month.toString().trim();
if (_mouth.length == 1) {
_mouth = '0' + _mouth;
}
String _day = dateTime.day.toString().trim();
if (_day.length == 1) {
_day = '0' + _day;
}
String date = '${dateTime.year}-${_mouth}-${_day}';
print('date = $date');
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map =
await getStatisData(statisType: 'sh_hyc_tj', ip: listDwinfoGetList2[i]['dwip'], date: date);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listTodayShtj.add(map);
// if (listTodayShtj.length >= dwSum) {
// print('listTodayShtj = $listTodayShtj');
// //发送统计数据已更新广播
// eventBus.fire(StatisDataUpdate('统计数据已更新'));
// }
getAllSum('csnum', listTodayShtj).then((value) {
//mapStatisInfo['今日初审'] = value[1];
listTodayChjl = value[2];
//try_setState();
});
getAllSum('fsnum', listTodayShtj).then((value) {
//mapStatisInfo['今日复审'] = value[1];
listTodayFhjl = value[2];
//try_setState();
});
getAllSum('sends', listTodayShtj).then((value) {
//mapStatisInfo['今日推送'] = value[1];
listTodayTsjl = value[2];
//try_setState();
});
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
///独立获取审核统计数据
List listShtjStatisAlone = [];
//遍历 listDwinfoGetList2 中所有点位,独立得到对应点位 ip 的统计数据存入 listShtjStatisNew
Future getShtjStatisAlone() async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listShtjStatisAlone.clear();
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map = await getStatisData(statisType: 'sh_hyc_tj', ip: listDwinfoGetList2[i]['dwip']);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listShtjStatisAlone.add(map);
// if (listShtjStatisAlone.length >= dwSum) {
// //发送统计数据已更新广播
// eventBus.fire(StatisDataUpdate('统计数据已更新'));
// }
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
///独立获取车流量统计数据
List listClltjStatisAlone = [];
//遍历 listDwinfoGetList2 中所有点位,独立得到对应点位 ip 的统计数据存入 listShtjStatisNew
Future getClltjStatisAlone() async {
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
///从接口 mapStatisType[statisType]['api'] 获取指定 ip 的 statisType 类型的统计数据,返回 Map
//Future getStatisData({@required String statisType, @required String ip}) async {
listClltjStatisAlone.clear();
int len = listDwinfoGetList2.length;
for (int i = 0; i < len; i++) {
Map map = await getStatisData(statisType: 'clltj', ip: listDwinfoGetList2[i]['dwip']);
map['dwbh'] = listDwinfoGetList2[i]['dwbh'];
map['dwmc'] = listDwinfoGetList2[i]['dwmc'];
map['dwip'] = listDwinfoGetList2[i]['dwip'];
listClltjStatisAlone.add(map);
// if (listClltjStatisAlone.length >= dwSum) {
// //发送统计数据已更新广播
// eventBus.fire(StatisDataUpdate('统计数据已更新'));
// }
}
//print('listZptjStatis = ${listZptjStatis}');
//StorageDataToFile.writeCounter(json_print(listZptjStatis, 1));
}
//////////////////////////////////////////////////////////////////
///获取所有统计数据
List listAllStatisData = [];
///车流量日统计数据类
var trinityData;
// 实现多个基于 Page1_Works 构建的页面共享统计数据
Future startGetStatisDataNew() async {
///获取点位信息数据
//listDwinfoGetList2.clear();
if (listDwinfoGetList2.isEmpty) {
//若没有读取点位数据,便需要先读取
getThePageList(theHyshlx: 'dwxx').then((value) {
listDwinfoGetList2 = value;
print('listDwinfoGetList2 = \n$listDwinfoGetList2');
dwSum = listDwinfoGetList2.length;
//获取记录数据
getZptjStatisAlone();
getTodayShtj();
getClltjStatisAlone();
//获取统计数据
getAllStatisData().then((value) {
listAllStatisData = value;
eventBus.fire(StatisDataUpdate('统计数据已更新'));
});
});
} else {
if (mapStatisInfo['今日抓拍'] < 0) {
//获取记录数据
getZptjStatisAlone();
getTodayShtj();
getClltjStatisAlone();
//获取统计数据
getAllStatisData().then((value) {
listAllStatisData = value;
eventBus.fire(StatisDataUpdate('统计数据已更新'));
});
} else {
//发送统计数据已更新广播
eventBus.fire(StatisDataUpdate('统计数据已更新'));
}
}
}
Map<String, double> mapStatisInfo = {
'今日抓拍': -1,
'今日初审': -1,
'今日复审': -1,
'今日推送': -1,
'今日车流': -1,
};
//得到所有5项统计数据
//适用的字段:抓拍统计的'today'、all;审核统计的"total"、"sends";
Future getAllSumNew() async {
int items = 0;
mapStatisInfo['今日抓拍'] = 0;
mapStatisInfo['今日初审'] = 0;
mapStatisInfo['今日复审'] = 0;
mapStatisInfo['今日推送'] = 0;
mapStatisInfo['今日车流'] = 0;
for (var item in listAllStatisData) {
items++;
if (item["zp_today"] > 0) {
//listRecords.addAll(item[field]["data"]); //将记录详情存入listRecords
mapStatisInfo['今日抓拍'] += item["zp_today"];
}
if (item["csnum"] > 0) {
mapStatisInfo['今日初审'] += item["csnum"];
}
if (item["fsnum"] > 0) {
mapStatisInfo['今日复审'] += item["fsnum"];
}
if (item["sends"] > 0) {
mapStatisInfo['今日推送'] += item["sends"];
}
if (item["cll_today"] > 0) {
mapStatisInfo['今日车流'] += item["cll_today"];
}
}
mapStatisInfo['今日车流'] = mapStatisInfo['今日车流'] / 10000;
// 统计点位数(未用),总计,记录列表
//return [items, sum, listRecords];
}
/*
[
{
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "锦绣花园",
"zp_all": 54,
"hyc_all": 52,
"zp_today": 1,
"sends": 0,
"send_all": 33,
"csnum": 1,
"fsnum": 0,
"cll_today": 6420,
"cll_all": 3225733
},
{
"id": 2,
"dwip": "172.16.3.2",
"dwmc": "石马溪桥",
"zp_all": 377,
"hyc_all": 370,
"zp_today": 1,
"sends": 0,
"send_all": 204,
"csnum": 1,
"fsnum": 0,
"cll_today": 3430,
"cll_all": 2127839
},
...
]
*/
// 实现多个基于 Page1_Works 构建的页面共享统计数据
Future startGetStatisDataOld() async {
///获取点位信息数据
//listDwinfoGetList2.clear();
if (listDwinfoGetList2.isEmpty) {
//若没有读取点位数据,便需要先读取
getThePageList(theHyshlx: 'dwxx').then((value) {
listDwinfoGetList2 = value;
print('listDwinfoGetList2 = \n$listDwinfoGetList2');
dwSum = listDwinfoGetList2.length;
getZptjStatisAlone();
getTodayShtj();
getClltjStatisAlone();
});
} else {
if (mapStatisInfo['今日抓拍'] < 0) {
getZptjStatisAlone();
} else {
//发送统计数据已更新广播
eventBus.fire(StatisDataUpdate('统计数据已更新'));
}
if (mapStatisInfo['今日初审'] < 0) {
getTodayShtj();
} else {
//发送统计数据已更新广播
eventBus.fire(StatisDataUpdate('统计数据已更新'));
}
if (mapStatisInfo['今日车流'] < 0) {
getClltjStatisAlone();
} else {
//发送统计数据已更新广播
eventBus.fire(StatisDataUpdate('统计数据已更新'));
}
}
}
//获取已审核黑烟车统计数据:App.Car_Statis.GetStaHyc
//{
// "ret": 200,
// "data": {
// "total": 40,
// "sends": {
// "total": 0,
// "data": []
// },
// "csnum": {
// "total": 0,
// "data": []
// },
// "fsnum": {
// "total": 0,
// "data": []
// }
// },
// "msg": ""
// }
//获取抓拍统计数据:App.Car_Statis.GetStaYjxx
//{
// "ret": 200,
// "data": {
// "today": {
// "total": 0,
// "data": []
// },
// "all": 40
// },
// "msg": ""
// }
//得到 listStatis[field] 的统计数据,
//适用的字段:抓拍统计的'today'、all;审核统计的"total"、"sends";
Future getAllSum(String field, List listStatis) async {
int items = 0;
int sum = 0;
List listRecords = []; //记录详情存入
for (var item in listStatis) {
if (item[field]["total"] > 0) {
items++;
listRecords.addAll(item[field]["data"]); //将记录详情存入listRecords
sum += item[field]["total"];
}
}
return [items, sum, listRecords];
}
//获取车流量统计数据:App.Car_Statis.GetStaCll
//{
// "ret": 200,
// "data": {
// "today": 7010,
// "all": 1640350
// },
// "msg": ""
//}
//得到 listStatis[field] 的统计数据,
//适用的字段:车流量统计的'today'、all
Future getAllSumCll(String field, List listStatis) async {
int items = 0;
int sum = 0;
for (var item in listStatis) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
//////////////////////////////////////////////////////////////////
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,778 @@
//import '../../../widget/player_pro.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_drag_scale/flutter_drag_scale.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hyzp_ybqx/widget/my_superplayer.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';
//
import '../../../components/commonFun.dart';
import '../../../components/doJSON.dart';
import '../../../components/hyxx_data_handle.dart';
// "today": {
// "total": 4,
// "data": [
// {
// "id": 428549,
// "car_number": "川15A2563",
// "cpys": "绿色",
// "zpsj": "2021-04-04 11:31:11",
// "dwip": "172.16.3.3",
// "dwms": "岷江南路森林小区附近",
// "cplx": "农用车",
// "lgmzs": 3,
// "pic_url": "/wwwroot/admin/Api/wwwroot/public/uploads/e936524e92f90541cbaeca3b092c95be.jpg",
// "video_url": "video/3_6063_20210404_113111_川15A2563.mp4"
// },
class TodayListZpjlContent extends StatefulWidget {
TodayListZpjlContent({
@required this.hyshlx,
@required this.num,
@required this.text,
@required this.mapZpjl,
this.tsztText = '',
Key key,
}) : super(key: key);
String hyshlx;
String num;
String text;
Map mapZpjl;
String tsztText;
_TodayListZpjlPageState createState() => _TodayListZpjlPageState();
}
//用TabController实现顶部tab切换
class _TodayListZpjlPageState extends State<TodayListZpjlContent> {
//try_setState(); //避免如下异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
dispose() {
super.dispose();
}
BuildContext _context;
//flutter_screenUtil 4.x 用法,ScreenUtil.screenWidth (sdk>=2.6 : 1.sw) //设备宽度
double _screenWidth = 1.sw;
double _marginLeft = 25;
double _marginCenter = 35;
double _fontSize = 16;
double _widthLeft = 40; // = _screenWidth / 3;
double _iconSize = 18;
double _stampSize = 100;
double _listTileHeight = 30;
Color _iconColor = Colors.blue;
double _marginVer = 10;
Map _mapTsjjGetTsStatus = {};
Map mapName = {};
void initState() {
_context = context;
_widthLeft = _screenWidth / 2.6;
//getListFlields();
//得到字段名称
mapName['plate_id'] = widget.hyshlx == 'jrzp' ? 'car_number' : 'plate_id';
mapName['plate_color'] = widget.hyshlx == 'jrzp' ? 'cpys' : 'plate_color';
imageWztp = getWztp(); //得到违章图片
super.initState();
}
double _radioImage = 9 / 16;
// 使用 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),
);
}
// 167 50 3.34
Widget getLgmzs(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 == widget.mapZpjl['lgmzs'])
? Colors.red
: Color.fromRGBO(244, 244, 244, 1),
width: 2),
//color: Colors.lightBlue,
borderRadius: new BorderRadius.circular(3.0),
),
),
)
],
);
}
//得到tsjj页面组件
//1、得到格林曼黑度标准和视频播放按钮组件
Widget getHdAndPlay() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getLgmzs(0),
getLgmzs(1),
getLgmzs(2),
getLgmzs(3),
getLgmzs(4),
getLgmzs(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(widget.mapZpjl['video_url']);
//获取视频地址失败
if (!isVideoUrl(urlnew)) {
return;
}
Navigator.of(_context).push(MaterialPageRoute(
builder: (context) => SuperPlayerPage(
loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
url: urlnew,
title:
'${widget.text}视频${widget.num}\n${widget.mapZpjl[mapName['plate_id']]}(${getDwmc(widget.mapZpjl['dwip'])})')));
// Navigator.of(_context).push(MaterialPageRoute(
// builder: (context) => PlayerProNew(
// loop: 0, //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
// url: urlnew,
// title:
// '${widget.text}视频${widget.num}\n${widget.mapZpjl[mapName['plate_id']]}(${getDwmc(widget.mapZpjl['dwip'])})')));
},
),
SizedBox(width: ScreenUtil().setWidth(15)),
],
);
}
Widget imageWztp;
//2、得到违章图片组件
Widget getWztp() {
//ratioList[index] = 0.5714285714285714
return Stack(
children: [
Container(
width: ScreenUtil().setWidth(1022),
//height: ScreenUtil().setHeight(639),
//height: ScreenUtil().setHeight(22 + 1022 * _radioImage),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
decoration: BoxDecoration(
//color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
),
Positioned(
//left: ScreenUtil().setWidth(_marginLeft),
top: ScreenUtil().setHeight(_marginLeft),
child: Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(30 + 1022 * _radioImage),
child: getNetworkImage(getMediaUrl(widget.mapZpjl['pic_url'])),
),
)
],
);
}
// void printScreenInformation() {
// print('Device width dp:${1.sw}dp');
// print('Device height dp:${1.sh}dp');
// print('Device pixel density:${ScreenUtil().pixelRatio}');
// print('Bottom safe zone distance dp:${ScreenUtil().bottomBarHeight}dp');
// print('Status bar height dp:${ScreenUtil().statusBarHeight}dp');
// print('The ratio of actual width to UI design:${ScreenUtil().scaleWidth}');
// print(
// 'The ratio of actual height to UI design:${ScreenUtil().scaleHeight}');
// print('System font scaling:${ScreenUtil().textScaleFactor}');
// print('0.5 times the screen width:${0.5.sw}dp');
// print('0.5 times the screen height:${0.5.sh}dp');
// }
void printScreenInformation() {
print('ScreenUtil().screenWidth = ${ScreenUtil().screenWidth}');
print('设备宽度:${1.sw}dp');
print('"1.w" = ${1.w}');
print('"1.sw" = ${1.sw}');
print('设备高度:${1.sh}dp');
print('设备的像素密度:${ScreenUtil().pixelRatio}');
print('底部安全区距离:${ScreenUtil().bottomBarHeight}dp');
print('状态栏高度:${ScreenUtil().statusBarHeight}dp');
print('实际宽度的dp与设计稿px的比例:${ScreenUtil().scaleWidth}');
print('实际高度的dp与设计稿px的比例:${ScreenUtil().scaleHeight}');
print('宽度和字体相对于设计稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil().pixelRatio}');
print('高度相对于设计稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil().pixelRatio}');
print('系统的字体缩放比例:${ScreenUtil().textScaleFactor}');
print('屏幕宽度的0.5:${0.5.sw}dp');
print('屏幕高度的0.5:${0.5.sh}dp');
}
//3、得到违章图片说明信息组件
Widget getWztpSmxx() {
return Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(390),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//违章信息组件1:车牌号码、车牌颜色
getWzxxPart1(),
//违章信息组件2:抓拍时间组件
getWzxxText('抓拍时间:' + widget.mapZpjl['zpsj']),
//违章信息组件3:车牌类型 + 黑度
getWzxxPart3(),
//违章信息组件4:抓拍地点(简称)
getWzxxText('抓拍地点:' + getDwmc(widget.mapZpjl['dwip']) + ' (简称)'),
//违章信息组件5:抓拍地点
getWzxxText('抓拍地点:' + widget.mapZpjl['dwms']),
],
),
);
}
// I/flutter (22989): ScreenUtil().screenWidth = 360.0
// I/flutter (22989): 设备宽度:360.0dp
// I/flutter (22989): "1.w" = 0.3333333333333333
// I/flutter (22989): "1.sw" = 360.0
// I/flutter (22989): 设备高度:640.0dp
// I/flutter (22989): 设备的像素密度:3.0
// I/flutter (22989): 底部安全区距离:0.0dp
// I/flutter (22989): 状态栏高度:24.0dp
// I/flutter (22989): 实际宽度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 实际高度的dp与设计稿px的比例:0.3333333333333333
// I/flutter (22989): 宽度和字体相对于设计稿放大的比例:1.0
// I/flutter (22989): 高度相对于设计稿放大的比例:1.0
// I/flutter (22989): 系统的字体缩放比例:1.0
// I/flutter (22989): 屏幕宽度的0.5:180.0dp
// I/flutter (22989): 屏幕高度的0.5:320.0dp
//3、得到违章信息组件1:车牌号码、车牌颜色
//车牌颜色Map cpysMap = {
// '蓝色': cpysItem(
// cpysText: '蓝色',
// cpysBackground: Colors.blue,
// cpysFont: Colors.white,
// cpysBorder: Colors.orange),
// }
Widget getWzxxPart1() {
//printScreenInformation();
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
getTitleText('车牌号码:'),
getBoderText(widget.mapZpjl[mapName['plate_id']].toString(),
width: ScreenUtil().setWidth(1022 / 3.2)),
Expanded(child: SizedBox.shrink()),
getTitleText('颜色:'),
getBoderText(widget.mapZpjl[mapName['plate_color']],
width: ScreenUtil().setWidth(1022 / 4.8)),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
],
);
}
Widget getTitleRichText(String text1, {String text2 = '', double fontSize = 16}) {
return RichText(
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
text: TextSpan(
text: text1,
style: TextStyle(fontSize: fontSize, color: Colors.black),
children: [
TextSpan(
text: text2,
style: TextStyle(fontSize: fontSize, color: Colors.blue, fontWeight: FontWeight.w500),
),
],
),
);
}
Widget getTitleText(String text, {double fontSize = 16}) {
return Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis);
}
Widget getTrailText(String text, {double fontSize = 16, double off = 0}) {
return Container(
width: _screenWidth - _widthLeft - off - (2 * ScreenUtil().setWidth(_marginLeft)),
child: Text(text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
);
}
Widget getBoderText(String text, {double width = 40}) {
cpysItem _cpysItem = cpysMap[widget.mapZpjl[mapName['plate_color']]];
return Container(
//color: _cpysItem.cpysBackground,
alignment: Alignment(0, -1),
width: width,
decoration: BoxDecoration(
border: Border.all(color: _cpysItem.cpysBorder, width: 2),
color: _cpysItem.cpysBackground,
borderRadius: BorderRadius.circular(3),
),
child: Padding(
padding: EdgeInsets.only(bottom: 3),
child: Text(text,
style: TextStyle(fontSize: _fontSize, color: _cpysItem.cpysFont),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
),
);
}
//I/flutter (17555): mapZpjl = {
// id: 1222, plate_id: 川Q736X2, plate_color: 蓝色, zpsj: 1612857077, yjxx_id: 1399, workflow: 999,
// video_url: video/9_6063_20210209_155117_川Q736X2.mp4,
// pic_url: /wwwroot/admin/Api/wwwroot/public/uploads/9d2f45fd24b41f2b94abe42b30970d75.jpg,
// clfl: 集装箱卡车, dwip: 172.16.3.9, dwms: 宜长路出城方向, lgmzs: 3, jczxd: 994, sfhy: 黑烟车
// }
Widget getIcon(IconData _iconData) {
return Container(
width: _iconSize - 2,
height: _iconSize,
child: Padding(
padding: EdgeInsets.only(top: 2),
child: Icon(_iconData, size: _iconSize, color: _iconColor),
),
);
}
Widget getWzxxText(String _text, {double fontSize = 16}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022) - ScreenUtil().setWidth(_marginLeft),
child: Text(_text,
style: TextStyle(fontSize: fontSize),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis),
),
],
);
}
Widget getWzxxPart3() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
//width: ScreenUtil().setWidth(1022) - ScreenUtil().setWidth(_marginLeft),
child: getTitleText('车牌类型:' + widget.mapZpjl['cplx']),
),
Expanded(child: SizedBox.shrink()),
//getTitleText('黑度: ${widget.mapZpjl['lgmzs']}'),
getTitleRichText('黑度:', text2: '${widget.mapZpjl['lgmzs']} '),
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
],
);
}
Widget getText(String text, {Color color}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022 - 2 * _marginLeft),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Text(text,
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: color))
],
),
),
],
);
}
Widget getText2(String text1, String text2, String text3, {Color color}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment(-1, 0),
width: ScreenUtil().setWidth(1022 - 2 * _marginLeft),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Text(text1, textAlign: TextAlign.left),
Text(text2,
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: color, fontWeight: FontWeight.w500)),
Text(text3, textAlign: TextAlign.left),
],
),
),
],
);
}
//5、得到黑烟初审'hycsInfo'、或者黑烟'hyfhInfo'複核信息组件
//style: TextStyle(fontSize: _fontSize),
Widget getHyshInfo(String _hyshInfo) {
String _hyshLx = (_hyshInfo == 'hycsInfo' ? '初审' : '复审'); //黑烟审核类型
String _hyshYh = (_hyshInfo == 'hycsInfo' ? 'cs_username' : 'fs_username'); //黑烟审核用户
String _hyshSj = (_hyshInfo == 'hycsInfo' ? 'cs_time' : 'fs_time'); //黑烟审核时间
String _hyshJg = (_hyshInfo == 'hycsInfo' ? 'cs_tile' : 'fs_tile'); //黑烟审核结果
String _hyshYj = (_hyshInfo == 'hycsInfo' ? 'cs_shuoming' : 'fs_shuoming'); //黑烟审核意见
double _height = _hyshInfo == 'hyfhInfo' && widget.hyshlx == 'tsjj' ? 315 : 265;
return Column(
children: [
Container(
width: ScreenUtil().setWidth(1022),
height: ScreenUtil().setHeight(_height),
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 - 2 * _marginLeft),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Text('${_hyshLx}结果:' + widget.mapZpjl[_hyshJg],
textAlign: TextAlign.left, overflow: TextOverflow.ellipsis),
SizedBox(width: ScreenUtil().setWidth(20)),
Container(
width: my_iconSize,
height: my_iconSize,
decoration: widget.mapZpjl[_hyshJg] == ''
? null
: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
image: AssetImage(widget.mapZpjl[_hyshJg] == "黑烟车"
? "assets/images/hyc.png"
: "assets/images/fhyc.png"),
fit: BoxFit.contain),
),
alignment: Alignment.center,
//child:
),
],
),
),
],
),
getText('${_hyshLx}意见:' + widget.mapZpjl[_hyshYj]),
getText('${_hyshLx}用户:' + widget.mapZpjl[_hyshYh]),
getText('${_hyshLx}时间:' + widget.mapZpjl[_hyshSj]),
_hyshInfo == 'hyfhInfo' && widget.hyshlx == 'tsjj'
? (getText2('推送状态:', widget.tsztText, ' (${getDate(widget.mapZpjl['ts_time'])})',
color:
widget.tsztText.indexOf('成功') >= 0 ? Colors.blueAccent : Colors.black26))
: SizedBox.shrink(),
],
),
),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
],
);
}
//9、得到推送交警状态信息组件7:推送状态
// tszt 整型 推送状态:0-未推送 | 1-推送失败 | 3-推送成功
//_mapTsjjGetTsStatus['tszt']
Widget getWzxxPart7() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: ScreenUtil().setWidth(_marginLeft)),
Container(
alignment: Alignment(-1, 0),
width: _screenWidth - ScreenUtil().setWidth(_marginLeft),
child: getTitleText('推送状态:' + mapTsztText[_mapTsjjGetTsStatus['tszt']]),
),
],
);
}
//10、得到推送交警确认组件
Widget getTsjjQr() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
getBtnSizeX(
text: "返回",
onPressedFun: () async {
Navigator.pop(context);
},
width: 90.0),
],
);
}
bool showMoreWidget = false;
@override
Widget build(BuildContext context) {
return Scaffold(
//resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: showMoreWidget
? null
: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(widget.text + '记录' + widget.num,
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 30),
],
),
),
),
),
body: null == imageWztp
// 显示加载中的圈圈
? getMoreWidget(color: Colors.black38, size: 20.0, strokeWidth: 2.0)
: Stack(
children: [
//SizedBox.shrink() 创建父类允许最小尺寸的约束Box
showMoreWidget
? Align(
alignment: Alignment(0, 0.8),
child: Container(
height: 200,
width: 200,
child: getMoreWidget2(
text: '加载中...',
color: Colors.red,
size: 40.0,
strokeWidth: 3.0), //显示加载中的圈圈,
),
)
: SizedBox.shrink(),
KeyboardAvoider(
autoScroll: true,
child: Container(
color: Color.fromRGBO(244, 244, 244, 1),
child: Column(
children: <Widget>[
//1、得到格林曼黑度标准和视频播放按钮组件
getHdAndPlay(),
//2、得到违章图片组件
imageWztp,
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//3、得到违章图片说明信息组件
getWztpSmxx(),
SizedBox(height: ScreenUtil().setHeight(_marginVer)),
//7、得到黑烟初审信息组件
widget.hyshlx == 'hycs' ||
widget.hyshlx == 'hyfh' ||
widget.hyshlx == 'tsjj'
? getHyshInfo('hycsInfo')
: SizedBox.shrink(),
//8、得到黑烟复审信息组件
widget.hyshlx == 'hyfh' || widget.hyshlx == 'tsjj'
? getHyshInfo('hyfhInfo')
: SizedBox.shrink(),
SizedBox(height: widget.hyshlx == 'tsjj' ? 0 : 15),
//9、得到推送交警确认组件
getTsjjQr(),
//SizedBox(height: 10),
],
),
),
),
widget.hyshlx == 'tsjj'
? Positioned(
//alignment: Alignment(0.9, 0.35),
//alignment: Alignment(0.8, 0.45),
right: ScreenUtil().setWidth(50),
top: ScreenUtil().setHeight(1423),
child: Container(
//alignment: Alignment(0.5, -0.5),
width: _stampSize,
height: _stampSize,
//color: Colors.black12,
decoration: BoxDecoration(
//color: Colors.white,
image: DecorationImage(
//image: AssetImage("assets/images/jkzx_stamp.png"), fit: BoxFit.contain),
image: AssetImage(widget.mapZpjl['fs_tile'] == '黑烟车'
? "assets/images/hyc.png"
: "assets/images/fhyc.png"),
fit: BoxFit.contain),
),
//child:
),
)
: SizedBox.shrink(),
],
),
);
}
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,
),
);
}
}
+629
View File
@@ -0,0 +1,629 @@
import 'package:fl_chart/fl_chart.dart';
//import 'package:flustars/flustars.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hyzp_ybqx/components/commonFun.dart';
import 'package:hyzp_ybqx/components/dioFun.dart';
import 'package:hyzp_ybqx/components/hyxx_data_handle.dart';
import 'package:hyzp_ybqx/pages/Works/TJXX/tj_data.dart';
class ZptjBarChart extends StatefulWidget {
ZptjBarChart({this.statisType, this.data_ok = false, Key key}) : super(key: key);
String statisType; //统计类型
bool data_ok; //listZptjStatis 中的数据是否准备好
@override
State<StatefulWidget> createState() => ZptjBarChartState();
}
class ZptjBarChartState extends State<ZptjBarChart> {
static const Color red = const Color(0xffff5182);
static const Color blue = const Color(0xff0000ff);
static const Color leftBarColor = const Color(0xffff5182);
static const Color rightBarColor = const Color(0xff0000ff);
static const Color bottomBarColor = const Color(0xff939393);
static const Color gridColor = const Color(0xffe7e8ec);
static const double width = 7;
String _textBottom1;
String _textBottom2;
String _textTop1;
String _textTop2;
int _rate = 10; // today 字段放大倍率
int _rateCoord = 10000; // 坐标压缩倍率
int _interval = 20; // 坐标间隔
int _maxY = -1;
List<BarChartGroupData> _listBarData = [];
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void initState() {
super.initState();
getDataNew().then((value) {
_listBarData = value;
try_setState();
});
// ///获取点位信息数据
// if (!widget.data_ok) {
// //listZptjStatis 中的数据未准备好
// listZptjStatis.clear(); //最后需要显示的数据
// }
//
// if (listZptjStatis.isEmpty) {
// if (listDwinfoGetList2.isEmpty) {
// //若没有读取了点位数据,便需要先读取
// getThePageList(theHyshlx: 'dwxx').then((value) {
// listDwinfoGetList2 = value;
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// //按 sortField 升序排序
// listZptjStatis.sort((a, b) => (a['dwbh']).compareTo(b['dwbh']));
//
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// });
// });
// } else {
// //若已经读取了点位数据,便直接使用
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// //按 sortField 升序排序
// listZptjStatis.sort((a, b) => (a['dwbh']).compareTo(b['dwbh']));
//
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// });
// }
// } else {
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// }
}
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text(mapStatisType[widget.statisType]['text']),
// centerTitle: true,
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
titleSpacing: 0.0,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(mapStatisType[widget.statisType]['text'],
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 50),
],
),
),
),
),
body: Container(
alignment: Alignment(0, -0.85),
child: AspectRatio(
aspectRatio: 0.94, //宽高比
child: Card(
elevation: 4, //阴影高度
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
color: Colors.white,
child: Container(
padding: const EdgeInsets.only(top: 20),
child: (listAllStatisData.isEmpty || _listBarData.isEmpty)
? getMoreWidget(color: Colors.black38)
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: 3),
Text(_textTop1, style: TextStyle(color: leftBarColor, fontSize: 12)),
Expanded(
child: Text(''),
),
Text(_textTop2, style: TextStyle(color: rightBarColor, fontSize: 12)),
SizedBox(width: 3),
],
),
SizedBox(
height: 10,
),
BarChart(
BarChartData(
maxY: _maxY.toDouble() * 1.1,
groupsSpace: 6,
alignment: BarChartAlignment.spaceEvenly,
barTouchData: BarTouchData(
enabled: false,
),
//坐标数据
titlesData: FlTitlesData(
show: true,
bottomTitles: SideTitles(
rotateAngle: 45,
showTitles: true,
getTextStyles: (value) =>
const TextStyle(color: bottomBarColor, fontSize: 10),
margin: 10,
getTitles: (double value) {
int i = value.toInt() - 1;
return '${listAllStatisData[i]['id']}. ${listAllStatisData[i]['dwmc']}';
},
),
leftTitles: SideTitles(
showTitles: true,
getTextStyles: (value) =>
const TextStyle(color: leftBarColor, fontSize: 10),
margin: 4, //边距
getTitles: (double value) {
value = value / _rateCoord; //坐标压缩别率
if (value.toInt() % _interval == 0) {
return '${(value / _rate).toInt()}'; //将左侧坐标放大 _rate 倍
} else {
return '';
}
},
),
rightTitles: SideTitles(
showTitles: true,
getTextStyles: (value) =>
const TextStyle(color: rightBarColor, fontSize: 10),
margin: 4,
getTitles: (double value) {
value = value / _rateCoord; //坐标压缩别率
if (value.toInt() % _interval == 0) {
return '${value.toInt()}';
} else {
return '';
}
},
),
),
//栅格线
gridData: FlGridData(
show: true,
checkToShowHorizontalLine: (value) => value % _rate == 0,
getDrawingHorizontalLine: (value) => FlLine(
color: gridColor,
strokeWidth: 1,
),
),
//边线
borderData: FlBorderData(
show: true,
border: const Border(
bottom: BorderSide(
color: gridColor,
width: 2,
),
left: BorderSide(
color: leftBarColor,
width: 2,
),
right: BorderSide(
color: rightBarColor,
width: 2,
),
top: BorderSide(
color: Colors.transparent,
),
),
),
//图标数据
barGroups: _listBarData,
//barGroups: showingBarGroups,
),
),
SizedBox(height: 30),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: 3),
Text(_textBottom1,
style: TextStyle(color: leftBarColor, fontSize: 12)),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('点位编号',
style: TextStyle(color: bottomBarColor, fontSize: 12)),
),
),
Text(_textBottom2,
style: TextStyle(color: rightBarColor, fontSize: 12)),
SizedBox(width: 3),
],
),
]),
),
),
),
),
);
}
List<int> bar_getAllSumNew(String field) {
int items = 0;
int sum = 0;
for (var item in listAllStatisData) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
Future<List<BarChartGroupData>> getDataNew() async {
String _field1 = '';
String _field2 = '';
_maxY = -1;
int len = listAllStatisData.length;
List<BarChartGroupData> listBarData = [];
switch (widget.statisType) {
case 'zptj':
_field1 = 'zp_today';
_field2 = 'zp_all';
_rate = 10; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSumNew(_field1)[1]}';
_textBottom2 = '总共 ${bar_getAllSumNew(_field2)[1]}'; // 'all' 字段没有记录详情,所以用bar_getAllSumCll()
_textTop1 = '今日(次)';
_textTop2 = '(次)合计';
_rateCoord = 1;
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listAllStatisData[i]['id'],
(listAllStatisData[i][_field1] * _rate).toDouble(),
listAllStatisData[i][_field2].toDouble()),
);
//得到最大值
_maxY = listAllStatisData[i][_field1] * _rate > _maxY
? listAllStatisData[i][_field1] * _rate
: _maxY;
_maxY = listAllStatisData[i][_field2] > _maxY ? listAllStatisData[i][_field2] : _maxY;
}
break;
case 'sh_hyc_tj':
_field1 = 'hyc_all';
_field2 = 'send_all';
_rate = 1; // today 字段放大倍率
_rateCoord = 1; //坐标压缩倍率
_interval = 2; // 坐标间隔
_textBottom1 = '已审核 ${bar_getAllSumNew(_field1)[1]}';
_textBottom2 = '已推送 ${bar_getAllSumNew(_field2)[1]}';
_textTop1 = '审核(次)';
_textTop2 = '(次)推送';
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listAllStatisData[i]['id'],
(listAllStatisData[i][_field1] * _rate).toDouble(),
listAllStatisData[i][_field2].toDouble()),
);
//得到最大值
_maxY = listAllStatisData[i][_field1] * _rate > _maxY
? listAllStatisData[i][_field1] * _rate
: _maxY;
_maxY = listAllStatisData[i][_field2] > _maxY ? listAllStatisData[i][_field2] : _maxY;
}
break;
/*
listAllStatisData =
[
{
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "锦绣花园",
"zp_all": 54,
"hyc_all": 53,
"zp_today": 1,
"sends": 1,
"send_all": 34,
"csnum": 1,
"fsnum": 1,
"cll_today": 23200,
"cll_all": 3242513
},
...
]
*/
case 'clltj':
_field1 = 'cll_today';
_field2 = 'cll_all';
_rate = 10; // today 字段放大倍率
_rateCoord = 10000; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSumNew(_field1)[1] ~/ _rateCoord} 万辆';
_textBottom2 = '总共 ${bar_getAllSumNew(_field2)[1] ~/ _rateCoord} 万辆';
_textTop1 = '今日(万辆)';
_textTop2 = '(万辆)合计';
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listAllStatisData[i]['id'],
(listAllStatisData[i][_field1] * _rate).toDouble(),
listAllStatisData[i][_field2].toDouble()),
);
//得到最大值
_maxY = listAllStatisData[i][_field1] * _rate > _maxY
? listAllStatisData[i][_field1] * _rate
: _maxY;
_maxY = listAllStatisData[i][_field2] > _maxY ? listAllStatisData[i][_field2] : _maxY;
}
break;
default:
break;
}
return listBarData;
}
Future<List<BarChartGroupData>> getData() async {
String _field1 = '';
String _field2 = '';
_maxY = -1;
int len = listZptjStatis.length;
List<BarChartGroupData> listBarData = [];
switch (widget.statisType) {
case 'zptj':
_field1 = 'today';
_field2 = 'all';
_rate = 10; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSum('today')[1]}';
_textBottom2 = '总共 ${bar_getAllSumCll('all')[1]}'; // 'all' 字段没有记录详情,所以用bar_getAllSumCll()
_textTop1 = '今日(次)';
_textTop2 = '(次)合计';
_rateCoord = 1;
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listZptjStatis[i]['dwbh'],
(listZptjStatis[i][_field1]["total"] * _rate).toDouble(),
listZptjStatis[i][_field2].toDouble()),
);
//得到最大值
_maxY = listZptjStatis[i][_field1]["total"] * _rate > _maxY
? listZptjStatis[i][_field1]["total"] * _rate
: _maxY;
_maxY = listZptjStatis[i][_field2] > _maxY ? listZptjStatis[i][_field2] : _maxY;
}
break;
case 'sh_hyc_tj':
_field1 = 'total';
_field2 = 'sends';
_rate = 1; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 2; // 坐标间隔
_textBottom1 =
'已审核 ${bar_getAllSumCll('total')[1]}'; // 'total' 字段没有记录详情,所以用bar_getAllSumCll()
_textBottom2 = '已推送 ${bar_getAllSum('sends')[1]}';
_textTop1 = '审核(次)';
_textTop2 = '(次)推送';
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listZptjStatis[i]['dwbh'],
(listZptjStatis[i][_field1] * _rate).toDouble(),
listZptjStatis[i][_field2]["total"].toDouble()),
);
//得到最大值
_maxY = listZptjStatis[i][_field1] * _rate > _maxY
? listZptjStatis[i][_field1] * _rate
: _maxY;
_maxY = listZptjStatis[i][_field2]["total"] > _maxY
? listZptjStatis[i][_field2]["total"]
: _maxY;
}
break;
case 'clltj':
_field1 = 'today';
_field2 = 'all';
_rate = 10; // today 字段放大倍率
_rateCoord = 10000; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSumCll('today')[1] ~/ _rateCoord} 万辆';
_textBottom2 = '总共 ${bar_getAllSumCll('all')[1] ~/ _rateCoord} 万辆';
_textTop1 = '今日(万辆)';
_textTop2 = '(万辆)合计';
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listZptjStatis[i]['dwbh'],
(listZptjStatis[i][_field1] * _rate).toDouble(),
listZptjStatis[i][_field2].toDouble()),
);
//得到最大值
_maxY = listZptjStatis[i][_field1] * _rate > _maxY
? listZptjStatis[i][_field1] * _rate
: _maxY;
_maxY = listZptjStatis[i][_field2] > _maxY ? listZptjStatis[i][_field2] : _maxY;
}
break;
default:
break;
}
return listBarData;
}
BarChartGroupData makeGroupData(int x, double y1, double y2) {
return BarChartGroupData(barsSpace: 0, x: x, barRods: [
BarChartRodData(
y: y1,
colors: [leftBarColor],
width: width,
borderRadius: const BorderRadius.all(Radius.zero),
),
BarChartRodData(
y: y2,
colors: [rightBarColor],
width: width,
borderRadius: const BorderRadius.all(Radius.zero),
),
]);
}
//获取已审核黑烟车统计数据:App.Car_Statis.GetStaHyc
//{
// "ret": 200,
// "data": {
// "total": 40,
// "sends": {
// "total": 0,
// "data": []
// },
// "csnum": {
// "total": 0,
// "data": []
// },
// "fsnum": {
// "total": 0,
// "data": []
// }
// },
// "msg": ""
// }
//获取抓拍统计数据:App.Car_Statis.GetStaYjxx
//{
// "ret": 200,
// "data": {
// "today": {
// "total": 0,
// "data": []
// },
// "all": 40
// },
// "msg": ""
// }
//得到 listZptjStatis[field] 的统计数据,
//适用的字段:抓拍统计的'today'、all;审核统计的"total"、"sends";
List<int> bar_getAllSum(String field) {
int items = 0;
int sum = 0;
for (var item in listZptjStatis) {
if (item[field]["total"] > 0) {
items++;
sum += item[field]["total"];
}
}
return [items, sum];
}
//获取车流量统计数据:App.Car_Statis.GetStaCll
//{
// "ret": 200,
// "data": {
// "today": 7010,
// "all": 1640350
// },
// "msg": ""
//}
//得到 listZptjStatis[field] 的统计数据,
//适用的字段:车流量统计的'today'、all
List<int> bar_getAllSumCll(String field) {
int items = 0;
int sum = 0;
for (var item in listZptjStatis) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
}
@@ -0,0 +1,508 @@
import 'package:fl_chart/fl_chart.dart';
//import 'package:flustars/flustars.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hyzp_ybqx/components/commonFun.dart';
import 'package:hyzp_ybqx/components/dioFun.dart';
import 'package:hyzp_ybqx/components/hyxx_data_handle.dart';
import 'package:hyzp_ybqx/pages/Works/TJXX/tj_data.dart';
class ZptjBarChartOne extends StatefulWidget {
ZptjBarChartOne({this.statisType, this.data_ok = false, Key key}) : super(key: key);
String statisType; //统计类型
bool data_ok; //listZptjStatis 中的数据是否准备好
@override
State<StatefulWidget> createState() => ZptjBarChartOneState();
}
class ZptjBarChartOneState extends State<ZptjBarChartOne> {
static const Color red = const Color(0xffff5182);
static const Color blue = const Color(0xff0000ff);
static const Color leftBarColor = const Color(0xffff5182);
static const Color rightBarColor = const Color(0xff0000ff);
static const Color bottomBarColor = const Color(0xff939393);
static const Color gridColor = const Color(0xffe7e8ec);
static const double width = 7;
String _textBottom1;
String _textBottom2;
String _textTop1;
String _textTop2;
int _rate = 10; // today 字段放大倍率
int _rateCoord = 10000; // 坐标压缩倍率
int _interval = 20; // 坐标间隔
int _maxY = -1;
List<BarChartGroupData> _listBarData = [];
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void initState() {
super.initState();
print('ZptjBarChartOne');
getDataNew().then((value) {
_listBarData = value;
try_setState();
});
// ///获取点位信息数据
// if (!widget.data_ok) {
// //listZptjStatis 中的数据未准备好
// listZptjStatis.clear(); //最后需要显示的数据
// }
//
// if (listZptjStatis.isEmpty) {
// if (listDwinfoGetList2.isEmpty) {
// //若没有读取了点位数据,便需要先读取
// getThePageList(theHyshlx: 'dwxx').then((value) {
// listDwinfoGetList2 = value;
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// //按 sortField 升序排序
// listZptjStatis.sort((a, b) => (a['dwbh']).compareTo(b['dwbh']));
//
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// });
// });
// } else {
// //若已经读取了点位数据,便直接使用
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// //按 sortField 升序排序
// listZptjStatis.sort((a, b) => (a['dwbh']).compareTo(b['dwbh']));
//
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// });
// }
// } else {
// getData().then((value) {
// _listBarData = value;
// try_setState();
// });
// }
}
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text(mapStatisType[widget.statisType]['text']),
// centerTitle: true,
// ),
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)),
// 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
titleSpacing: 0.0,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(mapStatisType[widget.statisType]['text'],
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 50),
],
),
),
),
),
body: Container(
alignment: Alignment(0, -0.85),
child: AspectRatio(
aspectRatio: 0.94, //宽高比
child: Card(
elevation: 4, //阴影高度
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
color: Colors.white,
child: Container(
padding: const EdgeInsets.only(top: 20),
child: (listAllStatisData.isEmpty || _listBarData.isEmpty)
? getMoreWidget(color: Colors.black38)
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: 3),
Text(_textTop1, style: TextStyle(color: leftBarColor, fontSize: 12)),
Expanded(
child: Text(''),
),
Text(_textTop2, style: TextStyle(color: rightBarColor, fontSize: 12)),
SizedBox(width: 3),
],
),
SizedBox(
height: 10,
),
BarChart(
BarChartData(
maxY: _maxY.toDouble() * 1.1,
groupsSpace: 6,
alignment: BarChartAlignment.spaceEvenly,
barTouchData: BarTouchData(
enabled: false,
),
//坐标数据
titlesData: FlTitlesData(
show: true,
bottomTitles: SideTitles(
rotateAngle: 45,
showTitles: true,
getTextStyles: (value) =>
const TextStyle(color: bottomBarColor, fontSize: 10),
margin: 10,
getTitles: (double value) {
int i = value.toInt() - 1;
return '${listAllStatisData[i]['id']}. ${listAllStatisData[i]['dwmc']}';
},
),
leftTitles: SideTitles(
showTitles: true,
getTextStyles: (value) =>
const TextStyle(color: leftBarColor, fontSize: 10),
margin: 4, //边距
getTitles: (double value) {
//value = value / 1000; //坐标压缩别率
if (value.toInt() % 20000 == 0) {
return '${value / 100000}'; //将左侧坐标放大 _rate 倍
} else {
return '';
}
// if (value.toInt() % _interval == 0) {
// return '${(value / _rate).toInt()}'; //将左侧坐标放大 _rate 倍
// } else {
// return '';
// }
},
),
rightTitles: SideTitles(
showTitles: true,
// getTextStyles: (value) => const TextStyle(color: rightBarColor, fontSize: 10),
getTextStyles: (value) =>
const TextStyle(color: leftBarColor, fontSize: 10),
margin: 4,
getTitles: (double value) {
if (value.toInt() % 20000 == 0) {
return '${value / 100000}'; //将左侧坐标放大 _rate 倍
//return '';
} else {
return '';
}
},
),
),
//栅格线
gridData: FlGridData(
show: true,
checkToShowHorizontalLine: (value) => value % _rate == 0,
getDrawingHorizontalLine: (value) => FlLine(
color: gridColor,
strokeWidth: 1,
),
),
//边线
borderData: FlBorderData(
show: true,
border: const Border(
bottom: BorderSide(
color: gridColor,
width: 2,
),
left: BorderSide(
color: leftBarColor,
width: 2,
),
right: BorderSide(
// color: rightBarColor,
color: leftBarColor,
width: 2,
),
top: BorderSide(
color: Colors.transparent,
),
),
),
//图表数据
barGroups: _listBarData,
//barGroups: showingBarGroups,
),
),
SizedBox(height: 30),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(width: 3),
Text(_textBottom1,
style: TextStyle(color: leftBarColor, fontSize: 12)),
SizedBox(width: 60),
Text('点位编号', style: TextStyle(color: bottomBarColor, fontSize: 12)),
// Text(_textBottom2,
// style: TextStyle(color: rightBarColor, fontSize: 12)),
//SizedBox(width: 73),
],
),
]),
),
),
),
),
);
}
List<int> bar_getAllSumNew(String field) {
int items = 0;
int sum = 0;
for (var item in listAllStatisData) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
Future<List<BarChartGroupData>> getDataNew() async {
String _field1 = '';
String _field2 = '';
switch (widget.statisType) {
case 'zptj':
_field1 = 'zp_today';
_field2 = 'zp_all';
_rate = 10; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSumNew(_field1)[1]}';
_textBottom2 = '总共 ${bar_getAllSumNew(_field2)[1]}'; // 'all' 字段没有记录详情,所以用bar_getAllSumCll()
_textTop1 = '今日(次)';
_textTop2 = '(次)合计';
_rateCoord = 1;
break;
case 'sh_hyc_tj':
_field1 = 'hyc_all';
_field2 = 'send_all';
_rate = 1; // today 字段放大倍率
_rateCoord = 1; //坐标压缩倍率
_interval = 2; // 坐标间隔
_textBottom1 = '已审核 ${bar_getAllSumNew(_field1)[1]}';
_textBottom2 = '已推送 ${bar_getAllSumNew(_field2)[1]}';
_textTop1 = '审核(次)';
_textTop2 = '(次)推送';
break;
/*
listAllStatisData =
[
{
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "锦绣花园",
"zp_all": 54,
"hyc_all": 53,
"zp_today": 1,
"sends": 1,
"send_all": 34,
"csnum": 1,
"fsnum": 1,
"cll_today": 23200,
"cll_all": 3242513
},
...
]
*/
case 'clltj':
_field1 = 'cll_today';
_field2 = 'cll_all';
_rate = 10; // today 字段放大倍率
_rateCoord = 10000; //坐标压缩别率
_interval = 5; // 坐标间隔
_textBottom1 = '今日合计 ${bar_getAllSumNew(_field1)[1] ~/ _rateCoord} 万辆';
//_textBottom2 = '总共 ${bar_getAllSumNew(_field2)[1] ~/ _rateCoord} 万辆';
_textBottom2 = '';
_textTop1 = '今日(万辆)';
//_textTop2 = '(万辆)合计';
_textTop2 = '';
break;
default:
break;
}
_maxY = -1;
int len = listAllStatisData.length;
List<BarChartGroupData> listBarData = [];
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(
listAllStatisData[i]['id'],
(listAllStatisData[i][_field1] * _rate).toDouble(),
listAllStatisData[i][_field2].toDouble()),
);
//得到最大值,只显示今日车流量
_maxY = listAllStatisData[i][_field1] * _rate > _maxY
? listAllStatisData[i][_field1] * _rate
: _maxY;
// _maxY = listZptjStatis[i][_field2] > _maxY ? listZptjStatis[i][_field2] : _maxY;
}
return listBarData;
}
Future<List<BarChartGroupData>> getData() async {
String _field1 = '';
String _field2 = '';
switch (widget.statisType) {
case 'zptj':
_field1 = 'today';
_field2 = 'all';
_rate = 10; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 20; // 坐标间隔
_textBottom1 = '今日合计 ${getAllSum('today')[1]}';
_textBottom2 = '总共 ${getAllSum('all')[1]}';
_textTop1 = '今日(次)';
_textTop2 = '(次)合计';
_rateCoord = 1;
break;
case 'sh_hyc_tj':
_field1 = 'total';
_field2 = 'sends';
_rate = 1; // today 字段放大倍率
_rateCoord = 1; //坐标压缩别率
_interval = 2; // 坐标间隔
_textBottom1 = '今日审核 ${getAllSum('total')[1]}';
_textBottom2 = '今日推送 ${getAllSum('sends')[1]}';
_textTop1 = '审核(次)';
_textTop2 = '(次)推送';
break;
case 'clltj':
_field1 = 'today';
_field2 = 'all';
_rate = 10; // today 字段放大倍率
_rateCoord = 10000; //坐标压缩别率
_interval = 5; // 坐标间隔
_textBottom1 = '今日合计 ${getAllSum('today')[1] ~/ (_rateCoord)} 万辆';
//_textBottom2 = '总共 ${getAllSum('all')[1] ~/ _rateCoord} 千辆';
_textBottom2 = '';
_textTop1 = '今日(万辆)';
//_textTop2 = '(千辆)合计';
_textTop2 = '';
break;
default:
break;
}
_maxY = -1;
int len = listZptjStatis.length;
List<BarChartGroupData> listBarData = [];
for (int i = 0; i < len; i++) {
//将 today 字段放大 _rate 倍
listBarData.add(
makeGroupData(listZptjStatis[i]['dwbh'], (listZptjStatis[i][_field1] * _rate).toDouble(),
listZptjStatis[i][_field2].toDouble()),
);
//得到最大值,只显示今日车流量
_maxY =
listZptjStatis[i][_field1] * _rate > _maxY ? listZptjStatis[i][_field1] * _rate : _maxY;
// _maxY = listZptjStatis[i][_field2] > _maxY ? listZptjStatis[i][_field2] : _maxY;
}
return listBarData;
}
BarChartGroupData makeGroupData(int x, double y1, double y2) {
return BarChartGroupData(barsSpace: 0, x: x, barRods: [
BarChartRodData(
y: y1,
colors: [leftBarColor],
width: width,
borderRadius: const BorderRadius.all(Radius.zero),
),
// BarChartRodData(
// y: y2,
// colors: [rightBarColor],
// width: width,
// borderRadius: const BorderRadius.all(Radius.zero),
// ),
]);
}
//得到 listZptjStatis[field] 的统计数据,
//适用的字段:抓拍统计和车流量统计的'today'、all;审核统计的"total"、"sends";
List<int> getAllSum(String field) {
int items = 0;
int sum = 0;
for (var item in listZptjStatis) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
}
+835
View File
@@ -0,0 +1,835 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hyzp_ybqx/components/save_data_to_file.dart';
import 'package:hyzp_ybqx/pages/Works/TJXX/zptj_bar_chart.dart';
import 'package:hyzp_ybqx/pages/Works/TJXX/zptj_bar_chart_one.dart';
import '../../../components/commonFun.dart';
import '../../../components/hyxx_data_handle.dart';
import 'tj_data.dart';
//zptj 是本项目中“抓拍统计”的统一缩写
//sh_hyc_tj 是本项目中“审核黑烟车统计”的统一缩写
//clltj 是本项目中“车流量统计”的统一缩写
class ZptjPage extends StatefulWidget {
//mapStatisType 为统计数据类型数据结构。用于在同一套代码中,处理相似类型的多种统计数据
//statisType 为统计类型。mapStatisType[statisType] 为各种相似类型的设置数据
ZptjPage({@required this.statisType, Key key}) : super(key: key);
String statisType;
_ZptjPageState createState() => _ZptjPageState();
}
class _ZptjPageState extends State<ZptjPage> {
//try_setState(); //避免异常报错
try_setState() {
try {
setState(() {});
} catch (e) {
print('setState(() {})异常:${e}');
}
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
// ///获取点位信息数据
// listZptjStatis.clear(); //最后需要显示的数据
//
// if (listDwinfoGetList2.isEmpty) {
// //若没有读取了点位数据,便需要先读取
// getThePageList(theHyshlx: 'dwxx').then((value) {
// listDwinfoGetList2 = value;
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// _listSort(sortField: 'dwbh');
// });
// });
// } else {
// //若已经读取了点位数据,便直接使用
// print('listDwinfoGetList2 = \n$listDwinfoGetList2');
// getZptjStatis(widget.statisType).then((value) {
// _listSort(sortField: 'dwbh');
// });
// }
super.initState();
}
///获取点位信息数据
// List listDwinfoGetList2 = [
// {
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆"
// },
// ];
//listZptjStatis = [
// {today: 832, all: 4479, dwip: 172.16.3.1},
// {today: 0, all: 185, dwip: 172.16.3.2},
// {today: 0, all: 131, dwip: 172.16.3.3},
// {today: 0, all: 72, dwip: 172.16.3.4},
// {today: 0, all: 30, dwip: 172.16.3.5},
// {today: 0, all: 26, dwip: 172.16.3.6},
// {today: 0, all: 0, dwip: 172.16.3.7},
// {today: 0, all: 135, dwip: 172.16.3.8},
// {today: 0, all: 65, dwip: 172.16.3.9},
// {today: 0, all: 36, dwip: 172.16.3.10},
// {today: 0, all: 44, dwip: 172.16.3.11},
// {today: 0, all: 76, dwip: 172.16.3.12},
// {today: 0, all: 83, dwip: 172.16.3.13}
//]
Widget _getListTile(BuildContext context, int indexRecord, {double width = 520}) {
switch (widget.statisType) {
case 'zptj':
return _getZptjListTile(context, indexRecord, 520);
break;
case 'clltj':
return _getClltjListTile(context, indexRecord, 520);
break;
case 'sh_hyc_tj':
return _getSh_hyc_tjListTile(context, indexRecord, 510);
break;
default:
return Container();
break;
}
}
//抓拍统计数据
//{
// "today": 0,
// "all": 72
// "dwbh": 1,
// "dwmc": "江北振兴大道",
// "dwip": "172.16.3.1"
//}
Widget _getSh_hyc_tjListTile(BuildContext context, int indexRecord, double width) {
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: getDwmcField(indexRecord, 40),
// subtitle:
// Text('今日:${listZptjStatis[indexRecord]['today']}', style: TextStyle(fontSize: 10)),
trailing: Container(
width: ScreenUtil().setWidth(width),
child: Row(
children: [
getText(
text: listAllStatisData[indexRecord]['hyc_all'].toString(),
width: 260,
fontSize: 16),
getText(
text: listAllStatisData[indexRecord]['send_all'].toString(),
width: 240,
fontSize: 16),
],
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {},
),
Divider(height: 1.0),
],
);
}
Widget getText({String text = '', double width = 100, double fontSize = 16}) {
return SizedBox(
width: ScreenUtil().setWidth(width),
child: Text(
text,
maxLines: 1,
overflow: TextOverflow.ellipsis,
//textAlign: TextAlign.right,
style: TextStyle(fontSize: fontSize),
),
);
}
///获取点位信息数据
// List listDwinfoGetList2 = [
// {
// "id": 1,
// "dwip": "172.16.3.1",
// "dwmc": "江北振兴大道",
// "dwbh": 1,
// "dwinfo": "江北振兴大道入城方向",
// "dwzb": "104.607091|28.807061",
// "dwms": "江北振兴大道入城方向,识别孜岩、红坝路入城排放黑烟车辆"
// },
// ];
Widget getDwmcField(int indexRecord, double width) {
return SizedBox(
width: ScreenUtil().setWidth(width),
child: Text(
'${listAllStatisData[indexRecord]["id"].toString()}. ${listAllStatisData[indexRecord]["dwmc"]}',
style: TextStyle(fontSize: 16),
),
);
}
/*
listAllStatisData =
[
{
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "锦绣花园",
"zp_all": 54,
"hyc_all": 53,
"zp_today": 1,
"sends": 1,
"send_all": 34,
"csnum": 1,
"fsnum": 1,
"cll_today": 23200,
"cll_all": 3242513
},
...
]
*/
Widget _getZptjListTile(BuildContext context, int indexRecord, double width) {
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: getDwmcField(indexRecord, 40),
// subtitle:
// Text('今日:${listAllStatisData[indexRecord]['today']}', style: TextStyle(fontSize: 10)),
trailing: Container(
width: ScreenUtil().setWidth(width),
child: Row(
children: [
getText(
text: listAllStatisData[indexRecord]['zp_today'].toString(),
width: 260,
fontSize: 16),
getText(
text: listAllStatisData[indexRecord]['zp_all'].toString(),
width: 260,
fontSize: 16),
],
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {},
),
Divider(height: 1.0),
],
);
}
Widget _getClltjListTile(BuildContext context, int indexRecord, double width) {
return Column(
children: <Widget>[
ListTile(
//leading: new Icon(Icons.phone),
title: getDwmcField(indexRecord, 40),
// subtitle:
// Text('今日:${listAllStatisData[indexRecord]['today']}', style: TextStyle(fontSize: 10)),
trailing: Container(
width: ScreenUtil().setWidth(width),
child: Row(
children: [
// getText(
// text: listAllStatisData[indexRecord]['today'].toString(),
// width: 260,
// fontSize: 16),
// getText(
// text: (listAllStatisData[indexRecord]['all'] / 10000).toString(),
// width: 260,
// fontSize: 16),
getText(text: '', width: 260, fontSize: 16),
getText(
text: listAllStatisData[indexRecord]['cll_today'].toString(),
width: 260,
fontSize: 16),
],
),
),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 0),
enabled: true,
onTap: () async {},
),
Divider(height: 1.0),
],
);
}
bool isLoading = false; //正在处理下载数据、跳转到首项、跳转到尾项等操作
//Map<String, String> mapTjDataText = {
// "dwip": '点位IP',
// "today": '今日',
// "all": '总共',
// "total": '总共2',
// "sends": '推送'
// };
//抓拍统计数据
//{
// "today": 5,
// "all": 77
//},
//审核统计数据
//{
// "total": 6,
// "sends": 5
// },
//车流量统计数据
//{
// "today": 0,
// "all": 675338
//}
//得到表头行
Widget getHeadRow() {
Widget _headRow;
switch (widget.statisType) {
case 'zptj':
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(475),
child: _getSortBtn(sortField: 'dwmc', left: 78),
),
SizedBox(
width: ScreenUtil().setWidth(285),
child: _getSortBtn(sortField: 'today', left: 10),
),
SizedBox(
width: ScreenUtil().setWidth(280),
child: _getSortBtn(sortField: 'all', left: 10),
),
],
);
break;
case 'sh_hyc_tj':
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(495),
child: _getSortBtn(sortField: 'dwmc', left: 78),
),
SizedBox(
width: ScreenUtil().setWidth(265),
child: _getSortBtn(sortField: 'total', left: 10),
),
SizedBox(
width: ScreenUtil().setWidth(300),
child: _getSortBtn(sortField: 'sends', left: 20),
),
],
);
break;
case 'clltj':
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(465),
child: _getSortBtn(sortField: 'dwmc', left: 78),
),
// SizedBox(
// width: ScreenUtil().setWidth(265),
// child: _getSortBtn(sortField: 'today', left: 20),
// ),
// SizedBox(
// width: ScreenUtil().setWidth(300),
// child: _getSortBtn(sortField: 'all', left: 50),
// ),
SizedBox(
width: ScreenUtil().setWidth(265),
child: Text(''),
),
SizedBox(
width: ScreenUtil().setWidth(300),
child: _getSortBtn(sortField: 'today', left: 20),
),
],
);
break;
default:
return Container();
break;
}
return _headRow;
}
/*
listAllStatisData =
[
{
"id": 1,
"dwip": "172.16.3.1",
"dwmc": "锦绣花园",
"zp_all": 54,
"hyc_all": 53,
"zp_today": 1,
"sends": 1,
"send_all": 34,
"csnum": 1,
"fsnum": 1,
"cll_today": 23200,
"cll_all": 3242513
},
...
]
*/
//得到统计行
Widget getStatisRow() {
Widget _headRow;
switch (widget.statisType) {
case 'zptj':
List _listSum = tj_getAllSum('zp_today');
List _listAll = tj_getAllSum('zp_all');
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(455),
//xx个点位正常\n(共xx个点位)
child: _getStatisText(
//text: '${getOKdw().toString()}个点位正常\n(共${listDwinfoGetList2.length.toString()}个点位)',
text: '共 ${listDwinfoGetList2.length.toString()} 个点位',
left: ScreenUtil().setWidth(170)),
),
SizedBox(
width: ScreenUtil().setWidth(270),
//xx个点位,今日共抓拍xx
child: _getStatisText(
//text: '${_listSum[0].toString()}个点位,今日共抓拍${_listSum[1].toString()}',
text: '今日 ${_listSum[1].toString()} 次',
width: ScreenUtil().setWidth(245)),
),
SizedBox(
width: ScreenUtil().setWidth(300),
//xx个点位,总共抓拍xx
child: _getStatisText(
//text: '${_listAll[0].toString()}个点位,总共抓拍${_listAll[1].toString()}',
text: '总共 ${_listAll[1].toString()} 次',
width: ScreenUtil().setWidth(260)),
),
],
);
break;
case 'sh_hyc_tj':
List _listSum = tj_getAllSum('send_all');
//List _listAll = tj_getAllSumCll('total'); // 'total' 字段没有记录详情,所以用tj_getAllSumCll()
List _listAll = tj_getAllSum('hyc_all');
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(475),
//xx正常(共13)
child: _getStatisText(
//text: '${getOKdw().toString()}个点位正常\n(共${listDwinfoGetList2.length.toString()}个点位)',
text: '共 ${listDwinfoGetList2.length.toString()} 个点位',
left: ScreenUtil().setWidth(170)),
),
SizedBox(
width: ScreenUtil().setWidth(260),
//xx个点位,总共审核xx
child: _getStatisText(
//text: '${_listAll[0].toString()}个点位,总共审核${_listAll[1].toString()}',
text: '共审核 ${_listAll[1].toString()} 次',
width: ScreenUtil().setWidth(225)),
),
SizedBox(
//xx个点位,总共推送xx
child: _getStatisText(
//text: '${_listSum[0].toString()}个点位,总共推送${_listSum[1].toString()}',
text: '共推送 ${_listSum[1].toString()} 次',
width: ScreenUtil().setWidth(260)),
),
],
);
break;
case 'clltj':
List _listSum = tj_getAllSum('cll_today');
List _listAll = tj_getAllSum('cll_all');
_headRow = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: ScreenUtil().setWidth(445),
//xx个点位正常\n(共xx个点位)
child: _getStatisText(
//text: '${getOKdw().toString()}个点位正常\n(共${listDwinfoGetList2.length.toString()}个点位)',
text: '共 ${listDwinfoGetList2.length.toString()} 个点位',
left: ScreenUtil().setWidth(150)),
),
// SizedBox(
// width: ScreenUtil().setWidth(280),
// //xx个点位,今日共抓拍xx
// child: _getStatisText(
// //text: '${_listSum[0].toString()}个点位,今日车流量${_listSum[1].toString()}',
// text: '今日 ${_listSum[1].toString()}',
// width: ScreenUtil().setWidth(265)),
// ),
// SizedBox(
// width: ScreenUtil().setWidth(280),
// //xx个点位,总共抓拍xx
// child: _getStatisText(
// //text: '${_listAll[0].toString()}个点位,总共车流量${_listAll[1].toString()}',
// text: '总共 ${(_listAll[1] ~/ 10000).toString()} 万',
// width: ScreenUtil().setWidth(280)),
// ),
SizedBox(
width: ScreenUtil().setWidth(280),
//xx个点位,今日共抓拍xx
child: _getStatisText(
//text: '${_listSum[0].toString()}个点位,今日车流量${_listSum[1].toString()}',
text: '',
width: ScreenUtil().setWidth(265)),
),
SizedBox(
width: ScreenUtil().setWidth(280),
//xx个点位,今日共抓拍xx
child: _getStatisText(
//text: '${_listSum[0].toString()}个点位,今日车流量${_listSum[1].toString()}',
text: '今日 ${_listSum[1].toString()}',
width: ScreenUtil().setWidth(205)),
),
],
);
break;
default:
return Container();
break;
}
return _headRow;
}
//获取已审核黑烟车统计数据:App.Car_Statis.GetStaHyc
//{
// "ret": 200,
// "data": {
// "total": 40,
// "sends": {
// "total": 0,
// "data": []
// },
// "csnum": {
// "total": 0,
// "data": []
// },
// "fsnum": {
// "total": 0,
// "data": []
// }
// },
// "msg": ""
// }
//获取抓拍统计数据:App.Car_Statis.GetStaYjxx
//{
// "ret": 200,
// "data": {
// "today": {
// "total": 0,
// "data": []
// },
// "all": 40
// },
// "msg": ""
// }
//得到 listAllStatisData[field] 的统计数据,
//适用的字段:抓拍统计的'today'、all;审核统计的"total"、"sends";
List<int> tj_getAllSum(String field) {
int items = 0;
int sum = 0;
for (var item in listAllStatisData) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
//获取车流量统计数据:App.Car_Statis.GetStaCll
//{
// "ret": 200,
// "data": {
// "today": 7010,
// "all": 1640350
// },
// "msg": ""
//}
//得到 listZptjStatis[field] 的统计数据,
//适用的字段:车流量统计的'today'、all
List<int> tj_getAllSumCll(String field) {
int items = 0;
int sum = 0;
for (var item in listZptjStatis) {
if (item[field] > 0) {
items++;
sum += item[field];
}
}
return [items, sum];
}
Widget _getStatisText({@required String text, double left = 0, double width = 100}) {
return Row(
children: [
SizedBox(width: ScreenUtil().setWidth(left)),
Container(
width: width,
child:
Text(text, style: TextStyle(fontSize: 12), maxLines: 2, textAlign: TextAlign.center),
),
//SizedBox(width: ScreenUtil().setWidth(20)),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
// 设置appBar高度
child: AppBar(
automaticallyImplyLeading: false,
centerTitle: true,
titleSpacing: 0.0,
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: [
getIconAndTextButton(
iconColor: Colors.white,
iconData: Icons.chevron_left_outlined,
onPress: () {
Navigator.pop(context);
},
),
Expanded(
child: Text(mapStatisType[widget.statisType]['text'],
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis),
),
SizedBox(width: 10),
],
),
),
actions: [
InkWell(
child: Image.asset(
widget.statisType == 'zptj'
? 'assets/images/statis_blue.png'
: widget.statisType == 'sh_hyc_tj'
? 'assets/images/statis_red.png'
: 'assets/images/statis_green.png',
width: 32,
height: 32,
color: Colors.white),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
if (widget.statisType == 'clltj') {
return ZptjBarChartOne(
data_ok: true, //listAllStatisData 中的数据已经准备好
statisType: widget.statisType,
);
} else {
return ZptjBarChart(
data_ok: true, //listAllStatisData 中的数据已经准备好
statisType: widget.statisType,
);
}
}),
);
},
),
SizedBox(width: 15),
],
),
),
body: (listAllStatisData.isEmpty)
? getMoreWidget(color: Colors.black38)
: Column(
children: [
SizedBox(height: ScreenUtil().setHeight(20)),
getHeadRow(), //得到表头行
SizedBox(height: ScreenUtil().setHeight(20)),
Divider(height: 1.0, color: Colors.blue),
SizedBox(height: ScreenUtil().setHeight(10)),
getStatisRow(), //得到统计行
SizedBox(height: ScreenUtil().setHeight(10)),
Divider(height: 1.0, color: Colors.blue),
Expanded(
child: ListView.builder(
itemCount: listAllStatisData.length,
itemBuilder: (BuildContext context, index) {
return Column(
children: <Widget>[
_getListTile(context, index),
Divider(height: 1.0),
],
);
},
),
),
],
),
);
}
Widget _getImage(String sortField) {
sortField = (sortField == 'dwmc' ? 'id' : sortField);
String _image = _sortField != sortField
? 'assets/images/sort.png'
: _descending
? 'assets/images/descending.png'
: 'assets/images/ascending.png';
return Container(
margin: EdgeInsets.only(top: 4),
height: ScreenUtil().setWidth(38),
width: ScreenUtil().setWidth(38),
//child: Image.asset('assets/images/ybsthbj.png', fit: BoxFit.fitHeight),
child: Image.asset(_image,
fit: BoxFit.cover,
color: isLoading
? Theme.of(context).disabledColor
: (_sortField == sortField ? Colors.blue : null)));
}
String _sortField = 'dwmc';
bool _descending = false; //默认升序排列
Widget _getSortBtn({@required String sortField, double left = 0}) {
return InkWell(
// color: Colors.white,
// padding: EdgeInsets.all(0),
//iconSize: this.iconSize,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(width: ScreenUtil().setWidth(left)),
Text(mapTjDataText[sortField],
style: TextStyle(
fontSize: 18,
color: Colors.blue,
fontWeight: _sortField == sortField || (_sortField == 'id' && sortField == 'dwmc')
? FontWeight.bold
: null)),
SizedBox(width: ScreenUtil().setWidth(20)),
_getImage(sortField),
],
),
onTap: () {
if (isLoading) {
return;
}
print('sortField = $sortField,_descending = $_descending');
//按照用户选择的 sortField、_descending对listSbbjGetList2进行排序,并延时更新
_listSort(sortField: sortField == 'dwmc' ? 'id' : sortField);
},
);
}
// Map<String, String> mapTjDataText = {
// "dwip": '点位IP',
// "today": '今日',
// "all": '总共',
// "total": '总共2',
// "sends": '推送'
// };
//按照用户选择的 sortField、_descending对listZptjStatis进行排序,并延时更新
Future _listSort({@required String sortField, bool bShowToast = false}) {
if (!isLoading && listAllStatisData.length > 0) {
isLoading = true;
try_setState();
if (_sortField == sortField) {
_descending = !_descending; //若是与上一次按同一个自动排序,则切换升序降序
} else {
_descending = false; //默认升序排列
}
switch (sortField) {
default:
if (_descending) {
//按 sortField 降序排序
listAllStatisData.sort((a, b) => (b[sortField]).compareTo(a[sortField]));
} else {
//按 sortField 升序排序
listAllStatisData.sort((a, b) => (a[sortField]).compareTo(b[sortField]));
}
break;
}
Future.delayed(const Duration(milliseconds: 1000), () {
if (bShowToast) {
Fluttertoast.showToast(
msg:
'按“${mapTjDataText[sortField == 'id' ? 'dwmc' : sortField]}”${_descending ? '降序' : '升序'}排列完成!',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
);
}
_sortField = sortField;
isLoading = false;
try_setState(); //避免如下异常报错
});
}
}
}