sign_page.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. import 'dart:async';
  2. import 'package:amap_location_flutter_plugin/amap_location_flutter_plugin.dart';
  3. import 'package:amap_location_flutter_plugin/amap_location_option.dart';
  4. import 'package:amap_map_fluttify/amap_map_fluttify.dart';
  5. // import 'package:flustars/flustars.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:flutter_screenutil/flutter_screenutil.dart';
  8. import 'package:liftmanager/internal/sign/model/sign_config_item.dart';
  9. import 'package:liftmanager/internal/sign/model/sign_list_entity.dart';
  10. import 'package:liftmanager/internal/sign/sign_router.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/toast.dart';
  15. import 'package:liftmanager/widgets/app_bar.dart';
  16. import 'package:permission_handler/permission_handler.dart';
  17. class SignPage extends StatefulWidget {
  18. @override
  19. State<StatefulWidget> createState() {
  20. return SignPageState();
  21. }
  22. }
  23. class SignPageState extends State<SignPage> {
  24. Map<String, Object> _locationResult;
  25. StreamSubscription<Map<String, Object>> _locationListener;
  26. AmapLocationFlutterPlugin _locationPlugin = new AmapLocationFlutterPlugin();
  27. //计时器。
  28. Timer _timer;
  29. String _nowTimeStr = "";
  30. LatLng latLng = LatLng(0, 0);
  31. String currentAddress = "";
  32. SignConfigItem configItem = SignConfigItem();
  33. List<SignListItem> list = [];
  34. BuildContext mContext;
  35. AmapController _controller;
  36. startTime() async {
  37. _timer = Timer.periodic(Duration(seconds: 1), (timer) {
  38. if (!mounted) return;
  39. setState(() {
  40. _nowTimeStr = DateTime.now().toString().split(" ")[1].split(".")[0];
  41. });
  42. });
  43. }
  44. @override
  45. void initState() {
  46. super.initState();
  47. _locationListener = _locationPlugin
  48. .onLocationChanged()
  49. .listen((Map<String, Object> result) {
  50. setState(() {
  51. _locationPlugin.stopLocation();
  52. _locationResult = result;
  53. // address latitude longitude
  54. _locationResult.forEach((key, value) {
  55. if (key == 'address') {
  56. currentAddress = '$value';
  57. setState(() {});
  58. } else if (key == 'latitude') {
  59. latLng.latitude = double.parse('$value');
  60. setState(() {});
  61. } else if (key == 'longitude') {
  62. latLng.longitude = double.parse('$value');
  63. setState(() {});
  64. }
  65. print(111);
  66. print('key:$key :');
  67. print('value:$value :');
  68. });
  69. });
  70. });
  71. mContext = context;
  72. startTime();
  73. getSignConfig();
  74. getTodayList();
  75. getLocation();
  76. }
  77. void _setLocationOption() {
  78. if (null != _locationPlugin) {
  79. AMapLocationOption locationOption = new AMapLocationOption();
  80. ///是否单次定位
  81. locationOption.onceLocation = true;
  82. ///是否需要返回逆地理信息
  83. locationOption.needAddress = true;
  84. ///逆地理信息的语言类型
  85. locationOption.geoLanguage = GeoLanguage.DEFAULT;
  86. ///设置Android端连续定位的定位间隔
  87. locationOption.locationInterval = 20000;
  88. ///设置Android端的定位模式<br>
  89. ///可选值:<br>
  90. ///<li>[AMapLocationMode.Battery_Saving]</li>
  91. ///<li>[AMapLocationMode.Device_Sensors]</li>
  92. ///<li>[AMapLocationMode.Hight_Accuracy]</li>
  93. locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
  94. ///设置iOS端的定位最小更新距离<br>
  95. locationOption.distanceFilter = -1;
  96. ///设置iOS端期望的定位精度
  97. /// 可选值:<br>
  98. /// <li>[DesiredAccuracy.Best] 最高精度</li>
  99. /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
  100. /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
  101. /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
  102. /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
  103. locationOption.desiredAccuracy = DesiredAccuracy.NearestTenMeters;
  104. ///设置iOS端是否允许系统暂停定位
  105. locationOption.pausesLocationUpdatesAutomatically = false;
  106. ///将定位参数设置给定位插件
  107. _locationPlugin.setLocationOption(locationOption);
  108. }
  109. }
  110. @override
  111. void didChangeDependencies() {
  112. super.didChangeDependencies();
  113. mContext.dependOnInheritedWidgetOfExactType();
  114. }
  115. getLocation() async {
  116. if (await requestPermission()) {
  117. if (null != _locationPlugin) {
  118. ///开始定位之前设置定位参数
  119. _setLocationOption();
  120. _locationPlugin.startLocation();
  121. }
  122. }
  123. }
  124. @override
  125. void dispose() {
  126. _timer.cancel();
  127. if (null != _locationListener) {
  128. _locationListener.cancel();
  129. }
  130. ///销毁定位
  131. if (null != _locationPlugin) {
  132. _locationPlugin.destroy();
  133. }
  134. super.dispose();
  135. }
  136. getSignConfig() {
  137. ApiService(context: context).signConfig(
  138. onSuccess: (res) {
  139. configItem = res;
  140. setState(() {});
  141. },
  142. onError: (code, msg) {});
  143. }
  144. getTodayList() {
  145. ApiService(context: context).signList(
  146. 1, 10, DateTime.now().toString().split(" ")[0], onSuccess: (data) {
  147. list = data.rows;
  148. }, onError: (code, msg) {
  149. toasts(msg);
  150. });
  151. }
  152. getSignAdd() {
  153. if (configItem.topTime.length == 0) {
  154. toasts("未设置打卡");
  155. return;
  156. }
  157. if (currentAddress.length == 0) {
  158. toasts("定位正在初始化,请重试。");
  159. return;
  160. }
  161. NavigatorUtils.pushResult(context,
  162. "${SignRouter.signAddPage}?address=${Uri.encodeComponent(currentAddress)}&coordinate=${latLng.longitude},${latLng.latitude}&toptime=${configItem.topTime}&downtime=${configItem.downTime}&toptimepm=${configItem.topTimePm}&downtimepm=${configItem.downTimePm}&toptimeot=${configItem.topTimeOt}&downtimeot=${configItem.downTimeOt}",
  163. (res) {
  164. getTodayList();
  165. });
  166. }
  167. Future<bool> requestPermission() async {
  168. final permissions = await PermissionHandler()
  169. .requestPermissions([PermissionGroup.location]);
  170. if (permissions[PermissionGroup.location] == PermissionStatus.granted) {
  171. // toasts("已经定位.");
  172. return true;
  173. } else {
  174. toasts('需要定位权限!');
  175. return false;
  176. }
  177. }
  178. @override
  179. Widget build(BuildContext context) {
  180. return Scaffold(
  181. appBar: MyAppBar(
  182. centerTitle: "考勤",
  183. actions: <Widget>[
  184. FlatButton(
  185. child: Text("考勤记录", key: const Key('actionName')),
  186. textColor: Colours.text,
  187. highlightColor: Colors.transparent,
  188. onPressed: () {
  189. NavigatorUtils.push(context, SignRouter.signListPage);
  190. },
  191. )
  192. ],
  193. ),
  194. body: Container(
  195. color: Colors.white,
  196. child: Column(
  197. children: <Widget>[
  198. // Container(
  199. // color: ThemeUtils.getTabsBg(context),
  200. // padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
  201. // child: Row(
  202. // children: <Widget>[
  203. // Expanded(
  204. // flex: 1,
  205. // child: Text(
  206. // "当前位置:${currentAddress ?? ''}",
  207. // maxLines: 1,
  208. // overflow: TextOverflow.ellipsis,
  209. // ),
  210. // )
  211. // ],
  212. // )),
  213. Container(
  214. height: ScreenUtil().setHeight(250),
  215. child: Stack(
  216. children: <Widget>[
  217. AmapView(
  218. mapType: MapType.Standard,
  219. showZoomControl: false,
  220. centerCoordinate: latLng,
  221. zoomLevel: 17,
  222. maskDelay: Duration(milliseconds: 500),
  223. onMapCreated: (controller) async {
  224. _controller = controller;
  225. await _controller?.showMyLocation(MyLocationOption(
  226. myLocationType: MyLocationType.Locate,
  227. ));
  228. },
  229. ),
  230. Positioned(
  231. top: ScreenUtil().setHeight(140),
  232. left: ScreenUtil().setWidth(130),
  233. child:
  234. ClipRRect(
  235. borderRadius: BorderRadius.circular(4),
  236. child: Container(
  237. width: ScreenUtil().setWidth(222),
  238. padding: EdgeInsets.all(5),
  239. color: Colours.blue_app_main,
  240. child:Text(
  241. " 当前位置:${currentAddress ?? ''} ",
  242. style: TextStyle(color: Colors.white),
  243. maxLines: 1,
  244. overflow: TextOverflow.ellipsis,
  245. ), ),
  246. )
  247. )
  248. // AmapView(
  249. // mapType: MapType.Standard,
  250. // // 是否显示缩放控件
  251. // showZoomControl: false,
  252. // // 是否显示指南针控件
  253. // showCompass: false,
  254. // // 是否显示比例尺控件
  255. // showScaleControl: false,
  256. // // 是否使能缩放手势
  257. // zoomGesturesEnabled: true,
  258. // // 是否使能滚动手势
  259. // scrollGesturesEnabled: true,
  260. // // 是否使能旋转手势
  261. // rotateGestureEnabled: true,
  262. // // 是否使能倾斜手势
  263. // tiltGestureEnabled: true,
  264. // // 缩放级别
  265. // zoomLevel: 18,
  266. //// markers: _markers,
  267. // // 中心点坐标
  268. // centerCoordinate: latLng,
  269. // // 标记
  270. // onMapCreated: (controller) async {
  271. // if (await requestPermission()) {
  272. // await controller.showMyLocation(MyLocationOption(show: true));
  273. // }
  274. //// await getLocation();
  275. //// _markers = [
  276. //// MarkerOption(
  277. //// title: "我的位置",
  278. //// latLng: latLng,
  279. //// iconUri: _assetsIcon,
  280. //// imageConfig:
  281. //// createLocalImageConfiguration(mContext),
  282. //// width: 28,
  283. //// height: 28)
  284. //// ];
  285. //// controller.setCenterCoordinate(latLng);
  286. //// controller.showMyLocation(MyLocationOption());
  287. //// setState(() {});
  288. // },
  289. // ),
  290. // BoxShadow(color: Colors.grey[300],offset: Offset(1, 1),
  291. // ///模糊阴影半径
  292. // blurRadius: 5,
  293. // )
  294. // Positioned(
  295. // right: 14,
  296. // bottom: 19,
  297. // child: GestureDetector(
  298. // onTap: () {
  299. // getSignAdd();
  300. // },
  301. // child: Container(
  302. // height: 75,
  303. // width: 75,
  304. // decoration: BoxDecoration(
  305. // color: Colours.app_main,
  306. // boxShadow: [
  307. // ///阴影颜色/位置/大小等
  308. // BoxShadow(
  309. // color: Colors.grey[300], offset: Offset(1, 1),
  310. // ///模糊阴影半径
  311. // blurRadius: 5,
  312. // ),
  313. // BoxShadow(
  314. // color: Colors.grey[300],
  315. // offset: Offset(-1, -1),
  316. // blurRadius: 5),
  317. // BoxShadow(
  318. // color: Colors.grey[300],
  319. // offset: Offset(1, -1),
  320. // blurRadius: 5),
  321. // BoxShadow(
  322. // color: Colors.grey[300],
  323. // offset: Offset(-1, 1),
  324. // blurRadius: 5)
  325. // ],
  326. // borderRadius: BorderRadius.circular(73)),
  327. // child: Column(
  328. // mainAxisAlignment: MainAxisAlignment.center,
  329. // children: <Widget>[
  330. // Text(
  331. // "打卡",
  332. // style: TextStyle(
  333. // fontSize: 13,
  334. // fontWeight: FontWeight.w500,
  335. // color: Colors.white),
  336. // ),
  337. // Text("${_nowTimeStr}",
  338. // style: TextStyle(
  339. // fontSize: 13,
  340. // fontWeight: FontWeight.w500,
  341. // color: Colors.white))
  342. // ],
  343. // ),
  344. // ),
  345. // ),
  346. // ),
  347. ],
  348. )),
  349. Container(
  350. // padding: EdgeInsets.only(left: 10),
  351. alignment: Alignment.centerLeft,
  352. height: 45,
  353. decoration: BoxDecoration(
  354. border: Border(
  355. bottom: BorderSide(width: 0.5, color: Colours.line),
  356. ),
  357. ),
  358. child:Row(
  359. children: [
  360. Container(
  361. // margin: EdgeInsets.only(left: 10),
  362. height:13 ,width: 2,color: Colours.blue_app_main,),
  363. SizedBox(width: 10,),
  364. Text(
  365. "今日打卡记录",
  366. style: TextStyle(fontSize: 14, color: Colours.text),
  367. ),
  368. ],
  369. )
  370. ),
  371. Expanded(
  372. flex: 1,
  373. child: Column(
  374. crossAxisAlignment: CrossAxisAlignment.start,
  375. children: [
  376. list.length>0? Container(
  377. color: Colors.white,
  378. padding: const EdgeInsets.symmetric(
  379. horizontal: 15.0, vertical: 12.0),
  380. alignment: Alignment.centerLeft,
  381. child: RichText(
  382. text: TextSpan(
  383. // style: DefaultTextStyle.of(context).style,
  384. children: <InlineSpan>[
  385. TextSpan(
  386. text: '${list[0].createDate}',
  387. style: TextStyle(color: Colours.text)),
  388. TextSpan(text: ' ${list[0].typeDesc}',
  389. style: TextStyle(color: Colours.blue_app_main)
  390. ),
  391. ])),
  392. ):Container(),
  393. list.length > 1
  394. ? Container(
  395. height: 22,
  396. width: 2,
  397. color: Colours.new_dark_line,
  398. margin: EdgeInsets.only(left: 90),
  399. )
  400. : Container(),
  401. list.length > 1
  402. ? Container(
  403. color: Colors.white,
  404. padding: const EdgeInsets.symmetric(
  405. horizontal: 15.0, vertical: 12.0),
  406. alignment: Alignment.centerLeft,
  407. child: Text(
  408. "${list[1].createDate} ${list[1].typeDesc}",
  409. style: TextStyle(color: Colours.text_gray),
  410. ),
  411. )
  412. : Container()
  413. ],
  414. )
  415. // ListView.separated(
  416. // shrinkWrap: true,
  417. // itemCount: list.length,
  418. // separatorBuilder: (BuildContext context, int index) {
  419. // return Container(
  420. // height: 0.5,
  421. // color: Color(0xFFF5F5F5),
  422. // );
  423. // },
  424. // itemBuilder: (_, index) {
  425. // return Container(
  426. // color: Colors.white,
  427. // padding: const EdgeInsets.symmetric(
  428. // horizontal: 15.0, vertical: 12.0),
  429. // alignment: Alignment.centerLeft,
  430. // child: Row(
  431. // children: [
  432. // Text("${list[index].createDate} ${list[index].typeDesc}"),
  433. // ],
  434. // )
  435. // // Column(
  436. // // crossAxisAlignment: CrossAxisAlignment.start,
  437. // // mainAxisAlignment: MainAxisAlignment.start,
  438. // // children: <Widget>[
  439. // // // Text("类型:${list[index].typeDesc}"),
  440. // // // Text("时间:${list[index].createDate}"),
  441. // // // Text("地址:${list[index].address}"),
  442. // // // Text("状态:${list[index].statusDesc}")
  443. // // ],
  444. // // ),
  445. // );
  446. // },
  447. // )
  448. ),
  449. GestureDetector(
  450. onTap: () {
  451. getSignAdd();
  452. },
  453. child: Container(
  454. height: 110,
  455. width: 110,
  456. decoration: BoxDecoration(
  457. color: Colours.blue_app_main,
  458. boxShadow: [
  459. ///阴影颜色/位置/大小等
  460. BoxShadow(
  461. color: Colors.grey[300], offset: Offset(1, 1),
  462. ///模糊阴影半径
  463. blurRadius: 5,
  464. ),
  465. BoxShadow(
  466. color: Colors.grey[300],
  467. offset: Offset(-1, -1),
  468. blurRadius: 5),
  469. BoxShadow(
  470. color: Colors.grey[300],
  471. offset: Offset(1, -1),
  472. blurRadius: 5),
  473. BoxShadow(
  474. color: Colors.grey[300],
  475. offset: Offset(-1, 1),
  476. blurRadius: 5)
  477. ],
  478. borderRadius: BorderRadius.circular(73)),
  479. child: Column(
  480. mainAxisAlignment: MainAxisAlignment.center,
  481. children: <Widget>[
  482. Text("${_nowTimeStr}",
  483. style: TextStyle(
  484. fontSize: 22,
  485. fontWeight: FontWeight.w500,
  486. color: Colors.white)),
  487. Text(
  488. "打卡",
  489. style: TextStyle(
  490. fontSize: 14,
  491. fontWeight: FontWeight.w500,
  492. color: Colors.white),
  493. ),
  494. ],
  495. ),
  496. ),
  497. ),
  498. SizedBox(
  499. height: ScreenUtil().setHeight(30),
  500. )
  501. ],
  502. ),
  503. ),
  504. );
  505. }
  506. }