sign_page.dart 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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/internal/sign/model/sign_config_item.dart';
  8. import 'package:liftmanager/internal/sign/model/sign_list_entity.dart';
  9. import 'package:liftmanager/internal/sign/sign_router.dart';
  10. import 'package:liftmanager/net/api_service.dart';
  11. import 'package:liftmanager/res/resources.dart';
  12. import 'package:liftmanager/routers/fluro_navigator.dart';
  13. import 'package:liftmanager/utils/theme_utils.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.dark_text,
  187. highlightColor: Colors.transparent,
  188. onPressed: () {
  189. NavigatorUtils.push(context, SignRouter.signListPage);
  190. },
  191. )
  192. ],
  193. ),
  194. body: Container(
  195. child: Column(
  196. children: <Widget>[
  197. Container(
  198. color: ThemeUtils.getTabsBg(context),
  199. padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
  200. child: Row(
  201. children: <Widget>[
  202. Expanded(
  203. flex: 1,
  204. child: Text(
  205. "当前位置:${currentAddress ?? ''}",
  206. maxLines: 1,
  207. overflow: TextOverflow.ellipsis,
  208. ),
  209. )
  210. ],
  211. )),
  212. Container(
  213. height: 345,
  214. child: Stack(
  215. children: <Widget>[
  216. AmapView(
  217. mapType: MapType.Standard,
  218. showZoomControl: false,
  219. centerCoordinate: latLng,
  220. zoomLevel: 17,
  221. maskDelay: Duration(milliseconds: 500),
  222. onMapCreated: (controller) async {
  223. _controller = controller;
  224. await _controller?.showMyLocation(MyLocationOption(
  225. myLocationType: MyLocationType.Locate,
  226. ));
  227. },
  228. ),
  229. // AmapView(
  230. // mapType: MapType.Standard,
  231. // // 是否显示缩放控件
  232. // showZoomControl: false,
  233. // // 是否显示指南针控件
  234. // showCompass: false,
  235. // // 是否显示比例尺控件
  236. // showScaleControl: false,
  237. // // 是否使能缩放手势
  238. // zoomGesturesEnabled: true,
  239. // // 是否使能滚动手势
  240. // scrollGesturesEnabled: true,
  241. // // 是否使能旋转手势
  242. // rotateGestureEnabled: true,
  243. // // 是否使能倾斜手势
  244. // tiltGestureEnabled: true,
  245. // // 缩放级别
  246. // zoomLevel: 18,
  247. //// markers: _markers,
  248. // // 中心点坐标
  249. // centerCoordinate: latLng,
  250. // // 标记
  251. // onMapCreated: (controller) async {
  252. // if (await requestPermission()) {
  253. // await controller.showMyLocation(MyLocationOption(show: true));
  254. // }
  255. //// await getLocation();
  256. //// _markers = [
  257. //// MarkerOption(
  258. //// title: "我的位置",
  259. //// latLng: latLng,
  260. //// iconUri: _assetsIcon,
  261. //// imageConfig:
  262. //// createLocalImageConfiguration(mContext),
  263. //// width: 28,
  264. //// height: 28)
  265. //// ];
  266. //// controller.setCenterCoordinate(latLng);
  267. //// controller.showMyLocation(MyLocationOption());
  268. //// setState(() {});
  269. // },
  270. // ),
  271. // BoxShadow(color: Colors.grey[300],offset: Offset(1, 1),
  272. // ///模糊阴影半径
  273. // blurRadius: 5,
  274. // )
  275. Positioned(
  276. right: 14,
  277. bottom: 19,
  278. child: GestureDetector(
  279. onTap: () {
  280. getSignAdd();
  281. },
  282. child: Container(
  283. height: 75,
  284. width: 75,
  285. decoration: BoxDecoration(
  286. color: Colours.app_main,
  287. boxShadow: [
  288. ///阴影颜色/位置/大小等
  289. BoxShadow(
  290. color: Colors.grey[300], offset: Offset(1, 1),
  291. ///模糊阴影半径
  292. blurRadius: 5,
  293. ),
  294. BoxShadow(
  295. color: Colors.grey[300],
  296. offset: Offset(-1, -1),
  297. blurRadius: 5),
  298. BoxShadow(
  299. color: Colors.grey[300],
  300. offset: Offset(1, -1),
  301. blurRadius: 5),
  302. BoxShadow(
  303. color: Colors.grey[300],
  304. offset: Offset(-1, 1),
  305. blurRadius: 5)
  306. ],
  307. borderRadius: BorderRadius.circular(73)),
  308. child: Column(
  309. mainAxisAlignment: MainAxisAlignment.center,
  310. children: <Widget>[
  311. Text(
  312. "打卡",
  313. style: TextStyle(
  314. fontSize: 13,
  315. fontWeight: FontWeight.w500,
  316. color: Colors.white),
  317. ),
  318. Text("${_nowTimeStr}",
  319. style: TextStyle(
  320. fontSize: 13,
  321. fontWeight: FontWeight.w500,
  322. color: Colors.white))
  323. ],
  324. ),
  325. ),
  326. ),
  327. ),
  328. ],
  329. )),
  330. Container(
  331. padding: EdgeInsets.only(left: 10),
  332. alignment: Alignment.centerLeft,
  333. height: 45,
  334. decoration: BoxDecoration(
  335. border: Border(
  336. bottom: BorderSide(width: 0.5, color: Colours.line),
  337. ),
  338. ),
  339. child: Text(
  340. "今日打卡记录",
  341. style: TextStyle(fontSize: 14, color: Color(0xFF333333)),
  342. ),
  343. ),
  344. Expanded(
  345. flex: 1,
  346. child: ListView.separated(
  347. shrinkWrap: true,
  348. itemCount: list.length,
  349. separatorBuilder: (BuildContext context, int index) {
  350. return Container(
  351. height: 0.5,
  352. color: Color(0xFFF5F5F5),
  353. );
  354. },
  355. itemBuilder: (_, index) {
  356. return Container(
  357. color: Colors.white,
  358. padding: const EdgeInsets.symmetric(
  359. horizontal: 15.0, vertical: 12.0),
  360. alignment: Alignment.centerLeft,
  361. child: Column(
  362. crossAxisAlignment: CrossAxisAlignment.start,
  363. mainAxisAlignment: MainAxisAlignment.start,
  364. children: <Widget>[
  365. Text("类型:${list[index].typeDesc}"),
  366. Text("时间:${list[index].createDate}"),
  367. Text("地址:${list[index].address}"),
  368. Text("状态:${list[index].statusDesc}")
  369. ],
  370. ),
  371. );
  372. },
  373. ))
  374. ],
  375. ),
  376. ),
  377. );
  378. }
  379. }