123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- import 'dart:async';
- import 'package:flutter/material.dart';
- import 'package:geolocation/models/position.dart';
- import 'package:get/get.dart';
- import 'package:o2oa_all_platform/common/extension/index.dart';
- import '../../../../common/api/index.dart';
- import '../../../../common/models/index.dart';
- import '../../../../common/services/index.dart';
- import '../../../../common/utils/index.dart';
- import '../../../../common/widgets/index.dart';
- import 'index.dart';
- class OldCheckInController extends GetxController {
- OldCheckInController();
- final state = OldCheckInState();
- Record? lastRecord;
- // 外勤打卡,需要输入说明
- final TextEditingController outsideCheckInDescInputController =
- TextEditingController();
- // 定时器
- Timer? _timer;
- GeolocatorHelper? _geoHelper;
- /// 当前定位信息
- GeoPosition? myPosition;
- // 工作地点
- List<WorkplaceInfo> workplaceList = [];
- WorkplaceInfo? nearLeastWorkplace; // 最近的打卡地点
- /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
- @override
- void onReady() {
- /// 循环执行
- /// 间隔1秒
- _timer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
- ///定时任务
- _updateTimePerSecond();
- });
- // 初始化定位程序
- _geoHelper = GeolocatorHelper(callback: (position){
- myPosition = position;
- _calNearestWorkplace();
- });
- _geoHelper?.startLocation();
- // 初始化数据
- _loadAllWorkPalce();
- _loadRecordList();
- super.onReady();
- }
- /// 在 [onDelete] 方法之前调用。
- @override
- void onClose() {
- // 取消定时器
- _timer?.cancel();
- _geoHelper?.stopLocation();
- super.onClose();
- }
- _loadAllWorkPalce() async {
- final result = await AttendanceAssembleControlService.to.listAllAttendanceWorkPlace();
- if (result != null) {
- workplaceList.clear();
- workplaceList.addAll(result);
- }
- }
- _loadRecordList() async {
- final result = await AttendanceAssembleControlService.to.listMyRecords();
- if (result != null) {
- final rList = result.records ?? [];
- if (rList.isNotEmpty) {
- lastRecord = rList.last;
- }
- state.recordList.clear();
- var unCheckNumber = 0;
- final list = result.scheduleInfos?.map((s) {
- //是否已打卡
- final record = rList.firstWhereOrNull((element) => element.checkinType == s.checkinType);
- if (record != null) {
- s.checkinStatus = 'attendance_record_check_time'.tr;
- s.checkinTime = record.signTime;
- s.recordId = record.id;
- if (lastRecord != null && lastRecord?.id == record.id) {
- s.lastRecord = record;
- }
- unCheckNumber = 0; //清零
- }else{
- s.checkinStatus = 'attendance_uncheckin'.tr;
- unCheckNumber++;
- }
- return s;
- }).toList();
- state.recordList.addAll(list??[]);
- state.todayNeedCheck = (unCheckNumber > 0) ;
- } else {
- state.todayNeedCheck = false;
- }
- }
-
- /// 查找最近的打卡地点
- void _calNearestWorkplace() async {
- if (myPosition != null && workplaceList.isNotEmpty) {
- double minDistance = -1.0;
- for (var workplace in workplaceList) {
- OLogger.d('工作地点: ${workplace.latitude} ${workplace.longitude}');
- double startLatitude = myPosition?.latitude ?? 0;
- double startLongitude = myPosition?.longitude ?? 0;
- double endLatitude = double.tryParse(workplace.latitude ?? '0') ?? 0;
- double endLongitude = double.tryParse(workplace.longitude ?? '0') ?? 0;
- if (startLatitude != 0 && startLongitude != 0 && endLatitude != 0 && endLongitude != 0) {
- OLogger.d('坐标 workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- final wgs84 = BaiduLocationTransformHelper.bd09towgs84(endLongitude, endLatitude);
- final wgs84Lng = wgs84[0];
- final wgs84Lat = wgs84[1];
- OLogger.d('转化后的gps 坐标 workplace wgs84Lat:$wgs84Lat wgs84Lng:$wgs84Lng myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- final distance = _geoHelper?.distanceInMeters(startLatitude, startLongitude, wgs84Lat, wgs84Lng) ?? 0;
- int range = workplace.errorRange ?? 100; // 默认 100 米
- OLogger.d('距离计算:$distance $range');
- if (minDistance == -1.0) {
- minDistance = distance;
- nearLeastWorkplace = workplace;
- } else {
- if (minDistance > distance) {
- minDistance = distance;
- nearLeastWorkplace = workplace;
- }
- }
- } else {
- OLogger.e(' 错误的坐标 workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- }
- }
- OLogger.d('找到最近的打卡点? ${nearLeastWorkplace?.placeName ?? '无'}');
- _checkIsInWorkplace();
- } else {
- OLogger.e('还没有定位成功,或没有查询到工作列表!');
- }
- }
- /// 检查当前定位是否在打卡地点的范围内
- void _checkIsInWorkplace() async {
- if (myPosition != null && nearLeastWorkplace != null) {
- double startLatitude = myPosition?.latitude ?? 0;
- double startLongitude = myPosition?.longitude ?? 0;
- double endLatitude = double.tryParse(nearLeastWorkplace?.latitude ?? '0') ?? 0;
- double endLongitude = double.tryParse(nearLeastWorkplace?.longitude ?? '0') ?? 0;
- if (startLatitude != 0 && startLongitude != 0 && endLatitude != 0 && endLongitude != 0) {
- OLogger.d('坐标 workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- final wgs84 = BaiduLocationTransformHelper.bd09towgs84(endLongitude, endLatitude);
- final wgs84Lng = wgs84[0];
- final wgs84Lat = wgs84[1];
- OLogger.d('转化后的gps 坐标 workplace wgs84Lat:$wgs84Lat wgs84Lng:$wgs84Lng myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- final distance = _geoHelper?.distanceInMeters(startLatitude, startLongitude, wgs84Lat, wgs84Lng) ?? 0;
- int range = nearLeastWorkplace?.errorRange ?? 100; // 默认 100 米
- if (distance != 0 && distance <= range) {
- state.currentAddress = nearLeastWorkplace!.placeName;
- state.isInCheckInPositionRange = true;
- } else {
- state.currentAddress = 'attendance_checkin_not_in_workplace_error'.tr;
- state.isInCheckInPositionRange = false;
- }
- } else {
- OLogger.e(' 错误的坐标 workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
- }
- }
- }
- /// 每秒更新一次时间
- void _updateTimePerSecond() {
- state.currentTime = DateTime.now().hms();
- }
- ///
- /// 打卡
- ///
- void clickCheckIn() {
- OLogger.d('点击打卡');
- if (!state.todayNeedCheck) {
- OLogger.e('今日不需要打卡了,已经完成!');
- return;
- }
- _checkinClickOrUpdate(recordType: _calCheckType());
- }
- void clickUpdateRecord(Feature info) {
- final context = Get.context;
- if(context == null) {
- return;
- }
- O2UI.showConfirm(context, 'attendance_update_confirm_content'.tr, okPressed: (){
- _checkinClickOrUpdate(recordType: info.checkinType, recordId: info.lastRecord?.id);
- });
- }
- String _calCheckType() {
- final checkItem = state.recordList.firstWhereOrNull((element) => element.checkinStatus == 'attendance_uncheckin'.tr);
- if (checkItem != null) {
- return checkItem.checkinType ?? '';
- }
- return '';
- }
- ///
- /// 打卡处理
- ///
- /// @param recordId 更新打卡的id
- /// @param recordType 更新打卡的类型
- void _checkinClickOrUpdate({String? recordId, String? recordType}) {
- if (myPosition == null) {
- Loading.toast('attendance_checkin_need_location'.tr);
- return;
- }
- if (state.isInCheckInPositionRange && nearLeastWorkplace != null) {
- // 正常打卡
- OLogger.d('正常打卡!');
- // 计算checkin type
- try {
- String checkType = recordType ?? '';
- String id = recordId ?? '';
-
- _postCheckIn('${myPosition!.latitude}', '${myPosition!.longitude}',
- '${myPosition!.address}', checkType,
- workPlaceId: nearLeastWorkplace!.id ?? '',
- workAddress: nearLeastWorkplace!.placeName ?? '',
- id: id);
- } catch (e) {
- OLogger.e(e);
- Loading.toast('attendance_checkin_type_empty'.tr);
- }
- } else {
- // 外勤打开
- OLogger.d('外勤打卡');
- _outsideCheckIn(recordId: recordId, recordType: recordType);
- }
- }
- /// 外勤打卡
- void _outsideCheckIn({String? recordId, String? recordType}) async {
- final context = Get.context;
- if(context == null) {
- return;
- }
- // 确认外勤打卡 dialog
- var result = await O2UI.showCustomDialog(
- context,
- 'attendance_checkin_outside_dialog_title'.tr,
- TextField(
- controller: outsideCheckInDescInputController,
- maxLines: 1,
- style: Theme.of(context).textTheme.bodyMedium,
- keyboardType: TextInputType.text,
- textInputAction: TextInputAction.done,
- decoration: InputDecoration(
- hintText: 'attendance_checkin_outside_dialog_hint'.tr,
- ),
- ));
- OLogger.d('外勤打卡,返回结果$result');
- if (result != null && result == O2DialogAction.positive) {
- var desc = outsideCheckInDescInputController.text;
- // 计算checkin type
- try {
- _postCheckIn('${myPosition!.latitude}', '${myPosition!.longitude}',
- '${myPosition!.address}', recordType ?? '',
- signDesc: desc, isExternal: true, id: recordId?? '');
- } catch (e) {
- OLogger.e(e);
- Loading.toast('attendance_checkin_type_empty'.tr);
- }
-
- }
- }
- ///
- /// 提交打卡
- ///
- void _postCheckIn(
- String latitude, String longitude, String addrStr, String checkType,
- {String workPlaceId = '',
- String signDesc = '',
- String id = '',
- bool isExternal = false,
- String workAddress = ''}) async {
- if (isExternal) {
- // 外勤打开
- if (signDesc.isEmpty) {
- Loading.toast('attendance_outside_need_desc'.tr);
- return;
- }
- }
- Loading.show();
- final now = DateTime.now();
- var post = MobileCheckPost(
- latitude: latitude,
- longitude: longitude,
- recordAddress: addrStr,
- workAddress: workPlaceId,
- checkin_type: checkType,
- isExternal: isExternal,
- description: signDesc,
- signTime: now.hms(),
- recordDateString: now.ymd()
- );
- if (id.isNotEmpty) {
- post.id = id;
- }
- var deviceType = SharedPreferenceService.to.getString(SharedPreferenceService.currentDeviceTypeKey);
- post.optMachineType = deviceType;
- var iddata = await AttendanceAssembleControlService.to.checkInPost(post);
- if (iddata != null) {
- Loading.dismiss();
- _loadRecordList();
- }
- }
- }
|