heavy_sign_page.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:amap_location_flutter_plugin/amap_location_flutter_plugin.dart';
  4. import 'package:amap_location_flutter_plugin/amap_location_option.dart';
  5. import 'package:amap_map_fluttify/amap_map_fluttify.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:liftmanager/common/common.dart';
  8. import 'package:liftmanager/common/user_db.dart';
  9. import 'package:liftmanager/internal/heavy/heavy_router.dart';
  10. import 'package:liftmanager/internal/heavy/model/heavy_user_entity.dart';
  11. import 'package:liftmanager/net/api_service.dart';
  12. import 'package:liftmanager/res/resources.dart';
  13. import 'package:liftmanager/routers/fluro_navigator.dart';
  14. import 'package:liftmanager/utils/theme_utils.dart';
  15. import 'package:liftmanager/utils/toast.dart';
  16. import 'package:liftmanager/widgets/app_bar.dart';
  17. import 'package:permission_handler/permission_handler.dart';
  18. import 'package:flustars/flustars.dart' as f;
  19. class HeavySignPage extends StatefulWidget {
  20. HeavySignPage(this.projectId);
  21. String projectId;
  22. @override
  23. State<StatefulWidget> createState() {
  24. return HeavySignPageState();
  25. }
  26. }
  27. class HeavySignPageState extends State<HeavySignPage> {
  28. //计时器。
  29. Timer _timer;
  30. String _nowTimeStr = "";
  31. LatLng latLng = LatLng(0, 0);
  32. String currentAddress = "";
  33. List<HeavyUserEntity> list = [];
  34. BuildContext mContext;
  35. List<MarkerOption> _markers = [];
  36. AmapController _controller;
  37. Map<String, Object> _locationResult;
  38. StreamSubscription<Map<String, Object>> _locationListener;
  39. AmapLocationFlutterPlugin _locationPlugin = new AmapLocationFlutterPlugin();
  40. startTime() async {
  41. _timer = Timer.periodic(Duration(seconds: 1), (timer) {
  42. if (!mounted) return;
  43. setState(() {
  44. _nowTimeStr = DateTime.now().toString().split(" ")[1].split(".")[0];
  45. });
  46. });
  47. }
  48. @override
  49. void initState() {
  50. super.initState();
  51. mContext = context;
  52. _locationListener = _locationPlugin
  53. .onLocationChanged()
  54. .listen((Map<String, Object> result) {
  55. setState(() {
  56. _locationPlugin.stopLocation();
  57. _locationResult = result;
  58. // address latitude longitude
  59. _locationResult.forEach((key, value) {
  60. if(key == 'address'){
  61. currentAddress = '$value';
  62. setState(() {});
  63. }else if(key == 'latitude'){
  64. latLng.latitude = double.parse('$value');
  65. setState(() {});
  66. }else if(key == 'longitude'){
  67. latLng.longitude = double.parse('$value');
  68. setState(() {});
  69. }
  70. print(111);
  71. print('key:$key :');
  72. print('value:$value :');
  73. });
  74. });
  75. });
  76. startTime();
  77. getTodayList();
  78. getHasRole();
  79. getLocation();
  80. }
  81. @override
  82. void didChangeDependencies() {
  83. super.didChangeDependencies();
  84. mContext.dependOnInheritedWidgetOfExactType();
  85. }
  86. Future<LatLng> getLocation() async {
  87. if (await requestPermission()) {
  88. if (null != _locationPlugin) {
  89. ///开始定位之前设置定位参数
  90. _setLocationOption();
  91. _locationPlugin.startLocation();
  92. }
  93. }
  94. return latLng;
  95. }
  96. bool noRole = true;
  97. getHasRole() async {
  98. var role = await User().getCompanyRole();
  99. if (role == Constant.RoleAdmin ||
  100. role == Constant.RoleRegion ||
  101. role == Constant.RoleWork) {
  102. noRole = false;
  103. setState(() {});
  104. }
  105. }
  106. void _setLocationOption() {
  107. if (null != _locationPlugin) {
  108. AMapLocationOption locationOption = new AMapLocationOption();
  109. ///是否单次定位
  110. locationOption.onceLocation = true;
  111. ///是否需要返回逆地理信息
  112. locationOption.needAddress = true;
  113. ///逆地理信息的语言类型
  114. locationOption.geoLanguage = GeoLanguage.DEFAULT;
  115. ///设置Android端连续定位的定位间隔
  116. locationOption.locationInterval = 20000;
  117. ///设置Android端的定位模式<br>
  118. ///可选值:<br>
  119. ///<li>[AMapLocationMode.Battery_Saving]</li>
  120. ///<li>[AMapLocationMode.Device_Sensors]</li>
  121. ///<li>[AMapLocationMode.Hight_Accuracy]</li>
  122. locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
  123. ///设置iOS端的定位最小更新距离<br>
  124. locationOption.distanceFilter = -1;
  125. ///设置iOS端期望的定位精度
  126. /// 可选值:<br>
  127. /// <li>[DesiredAccuracy.Best] 最高精度</li>
  128. /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
  129. /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
  130. /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
  131. /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
  132. locationOption.desiredAccuracy = DesiredAccuracy.NearestTenMeters;
  133. ///设置iOS端是否允许系统暂停定位
  134. locationOption.pausesLocationUpdatesAutomatically = false;
  135. ///将定位参数设置给定位插件
  136. _locationPlugin.setLocationOption(locationOption);
  137. }
  138. }
  139. @override
  140. void dispose() {
  141. _timer.cancel();
  142. if (null != _locationListener) {
  143. _locationListener.cancel();
  144. }
  145. ///销毁定位
  146. if (null != _locationPlugin) {
  147. _locationPlugin.destroy();
  148. }
  149. super.dispose();
  150. }
  151. getTodayList() {
  152. ApiService(context: context).heavyUserList(
  153. widget.projectId, true, DateTime.now().toString().split(" ")[0],
  154. onSuccess: (data) {
  155. list = data;
  156. }, onError: (code, msg) {
  157. toasts(msg);
  158. });
  159. }
  160. getSignAdd() {
  161. if (currentAddress.length == 0) {
  162. toasts("定位正在初始化,请重试。");
  163. return;
  164. }
  165. showLoading(context, "正在签到");
  166. ApiService(context: context).heavySignAdd(
  167. "${latLng.longitude},${latLng.latitude}",
  168. currentAddress,
  169. widget.projectId, onSuccess: (res) {
  170. dismissLoading(context);
  171. toasts("签到成功");
  172. getTodayList();
  173. }, onError: (code, msg) {
  174. dismissLoading(context);
  175. toasts(msg);
  176. });
  177. }
  178. Future<bool> requestPermission() async {
  179. final permissions = await PermissionHandler()
  180. .requestPermissions([PermissionGroup.location]);
  181. if (permissions[PermissionGroup.location] == PermissionStatus.granted) {
  182. // toasts("已经定位.");
  183. return true;
  184. } else {
  185. toasts('需要定位权限!');
  186. return false;
  187. }
  188. }
  189. @override
  190. Widget build(BuildContext context) {
  191. return Scaffold(
  192. appBar: MyAppBar(
  193. centerTitle: "人员签到",
  194. actions: <Widget>[
  195. FlatButton(
  196. child: Text("考勤记录", key: const Key('actionName')),
  197. textColor: Colours.dark_text,
  198. highlightColor: Colors.transparent,
  199. onPressed: () {
  200. NavigatorUtils.push(context,
  201. "${HeavyRouter.heavyUserPage}?id=" + widget.projectId);
  202. },
  203. )
  204. ],
  205. ),
  206. body: Container(
  207. child: Column(
  208. children: <Widget>[
  209. Container(
  210. color: ThemeUtils.getTabsBg(context),
  211. padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
  212. child: Row(
  213. children: <Widget>[
  214. Expanded(
  215. flex: 1,
  216. child: Text(
  217. "当前位置:${currentAddress ?? ''}",
  218. maxLines: 1,
  219. overflow: TextOverflow.ellipsis,
  220. ),
  221. )
  222. ],
  223. )),
  224. Container(
  225. height: 345,
  226. child: Stack(
  227. children: <Widget>[
  228. AmapView(
  229. mapType: MapType.Standard,
  230. showZoomControl: false,
  231. zoomLevel: 17,
  232. maskDelay: Duration(milliseconds: 500),
  233. onMapCreated: (controller) async {
  234. _controller = controller;
  235. await _controller?.showMyLocation(MyLocationOption(
  236. myLocationType: MyLocationType.Locate,
  237. ));
  238. },
  239. ),
  240. // AmapView(
  241. // mapType: MapType.Standard,
  242. // // 是否显示缩放控件
  243. // showZoomControl: false,
  244. // // 是否显示指南针控件
  245. // showCompass: false,
  246. // // 是否显示比例尺控件
  247. // showScaleControl: false,
  248. // // 是否使能缩放手势
  249. // zoomGesturesEnabled: true,
  250. // // 是否使能滚动手势
  251. // scrollGesturesEnabled: true,
  252. // // 是否使能旋转手势
  253. // rotateGestureEnabled: true,
  254. // // 是否使能倾斜手势
  255. // tiltGestureEnabled: true,
  256. // // 缩放级别
  257. // zoomLevel: 18,
  258. // markers: _markers,
  259. // // 中心点坐标
  260. // centerCoordinate: latLng,
  261. // // 标记
  262. // onMapCreated: (controller) async {
  263. // _controller = controller;
  264. //// await getLocation();
  265. // if (Platform.isIOS) {
  266. // await getLocation();
  267. // setState(() {
  268. //
  269. // });
  270. // } else {
  271. // if (await requestPermission()) {
  272. // await _controller?.showMyLocation(MyLocationOption(
  273. // show: true,
  274. // ));
  275. // }
  276. // }
  277. // },
  278. // ),
  279. // BoxShadow(color: Colors.grey[300],offset: Offset(1, 1),
  280. // ///模糊阴影半径
  281. // blurRadius: 5,
  282. // )
  283. Positioned(
  284. right: 14,
  285. bottom: 19,
  286. child: Offstage(
  287. offstage: noRole,
  288. child: GestureDetector(
  289. onTap: () {
  290. getSignAdd();
  291. },
  292. child: Container(
  293. height: 75,
  294. width: 75,
  295. decoration: BoxDecoration(
  296. color: Colours.app_main,
  297. boxShadow: [
  298. ///阴影颜色/位置/大小等
  299. BoxShadow(
  300. color: Colors.grey[300],
  301. offset: Offset(1, 1),
  302. ///模糊阴影半径
  303. blurRadius: 5,
  304. ),
  305. BoxShadow(
  306. color: Colors.grey[300],
  307. offset: Offset(-1, -1),
  308. blurRadius: 5),
  309. BoxShadow(
  310. color: Colors.grey[300],
  311. offset: Offset(1, -1),
  312. blurRadius: 5),
  313. BoxShadow(
  314. color: Colors.grey[300],
  315. offset: Offset(-1, 1),
  316. blurRadius: 5)
  317. ],
  318. borderRadius: BorderRadius.circular(73)),
  319. child: Column(
  320. mainAxisAlignment: MainAxisAlignment.center,
  321. children: <Widget>[
  322. Text(
  323. "打卡",
  324. style: TextStyle(
  325. fontSize: 13,
  326. fontWeight: FontWeight.w500,
  327. color: Colors.white),
  328. ),
  329. Text("${_nowTimeStr}",
  330. style: TextStyle(
  331. fontSize: 13,
  332. fontWeight: FontWeight.w500,
  333. color: Colors.white))
  334. ],
  335. ),
  336. ),
  337. ),
  338. )),
  339. ],
  340. )),
  341. Container(
  342. padding: EdgeInsets.only(left: 10),
  343. alignment: Alignment.centerLeft,
  344. height: 45,
  345. decoration: BoxDecoration(
  346. color: ThemeUtils.getTabsBg(context),
  347. border: Border(
  348. bottom: BorderSide(width: 0.5, color: Colours.line),
  349. ),
  350. ),
  351. child: Text(
  352. "今日打卡记录",
  353. style: TextStyle(fontSize: 14, color: Color(0xFF333333)),
  354. ),
  355. ),
  356. ListView.separated(
  357. shrinkWrap: true,
  358. itemCount: list.length > 0 ? list[0].attendanceRecord.length : 0,
  359. separatorBuilder: (BuildContext context, int index) {
  360. return Container(
  361. height: 0.5,
  362. color: Color(0xFFF5F5F5),
  363. );
  364. },
  365. itemBuilder: (_, index) {
  366. return Container(
  367. color: ThemeUtils.getTabsBg(context),
  368. padding: const EdgeInsets.symmetric(
  369. horizontal: 15.0, vertical: 12.0),
  370. alignment: Alignment.centerLeft,
  371. child: Column(
  372. crossAxisAlignment: CrossAxisAlignment.start,
  373. mainAxisAlignment: MainAxisAlignment.start,
  374. children: <Widget>[
  375. Text(
  376. "入场时间:${list[0].attendanceRecord[index].approachTime}"),
  377. Text(
  378. "离场时间:${list[0].attendanceRecord[index].leavingTime}"),
  379. // Text("时间:${list[index].createDate}"),
  380. // Text("地址:${list[index].address}"),
  381. // Text("状态:${list[index].statusDesc}")
  382. ],
  383. ),
  384. );
  385. },
  386. )
  387. ],
  388. ),
  389. ),
  390. );
  391. }
  392. }