Răsfoiți Sursa

考勤打卡界面更新

fancy 5 ani în urmă
părinte
comite
7ea8fe58c4

+ 16 - 0
o2ios/O2Platform.xcodeproj/project.pbxproj

@@ -239,6 +239,10 @@
 		B1B7470721523ED70041948D /* SignatureViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1B7470521523ED60041948D /* SignatureViewCell.xib */; };
 		B1B7470921523F010041948D /* O2UISignatureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B7470821523F010041948D /* O2UISignatureView.swift */; };
 		B1BA42B824133AC40081CED8 /* TaskCreateData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1BA42B724133AC40081CED8 /* TaskCreateData.swift */; };
+		B1BB678024C6D1DD0020BD7D /* OOAttendanceCheckInNewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1BB677E24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.swift */; };
+		B1BB678124C6D1DD0020BD7D /* OOAttendanceCheckInNewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1BB677F24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.xib */; };
+		B1BB67B224C6E0320020BD7D /* OOAttendanceScheduleViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1BB67B024C6E0320020BD7D /* OOAttendanceScheduleViewCell.swift */; };
+		B1BB67B324C6E0320020BD7D /* OOAttendanceScheduleViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1BB67B124C6E0320020BD7D /* OOAttendanceScheduleViewCell.xib */; };
 		B1BC8CDA216B3D5F00AF571F /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B1BC8CD9216B3D5E00AF571F /* libc++.tbd */; };
 		B1C19025211437E200935829 /* OOCalendarLeftMenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C19024211437E200935829 /* OOCalendarLeftMenuController.swift */; };
 		B1C1905D2114410D00935829 /* CalendarTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C1905C2114410D00935829 /* CalendarTableViewCell.swift */; };
@@ -1576,6 +1580,10 @@
 		B1B7470521523ED60041948D /* SignatureViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SignatureViewCell.xib; sourceTree = "<group>"; };
 		B1B7470821523F010041948D /* O2UISignatureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = O2UISignatureView.swift; sourceTree = "<group>"; };
 		B1BA42B724133AC40081CED8 /* TaskCreateData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskCreateData.swift; sourceTree = "<group>"; };
+		B1BB677E24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OOAttendanceCheckInNewController.swift; sourceTree = "<group>"; };
+		B1BB677F24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OOAttendanceCheckInNewController.xib; sourceTree = "<group>"; };
+		B1BB67B024C6E0320020BD7D /* OOAttendanceScheduleViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OOAttendanceScheduleViewCell.swift; sourceTree = "<group>"; };
+		B1BB67B124C6E0320020BD7D /* OOAttendanceScheduleViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OOAttendanceScheduleViewCell.xib; sourceTree = "<group>"; };
 		B1BC8CD9216B3D5E00AF571F /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
 		B1C19024211437E200935829 /* OOCalendarLeftMenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OOCalendarLeftMenuController.swift; sourceTree = "<group>"; };
 		B1C1905C2114410D00935829 /* CalendarTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarTableViewCell.swift; sourceTree = "<group>"; };
@@ -3375,6 +3383,8 @@
 				E428AF5F20AD4DCE00D964B9 /* OOAttanceCheckInController.xib */,
 				E4B2320D20B2A9F60082F30A /* OOAttandanceWorkPlaceController.swift */,
 				E4B2320E20B2A9F60082F30A /* OOAttandanceWorkPlaceController.xib */,
+				B1BB677E24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.swift */,
+				B1BB677F24C6D1DD0020BD7D /* OOAttendanceCheckInNewController.xib */,
 			);
 			path = c;
 			sourceTree = "<group>";
@@ -3408,6 +3418,8 @@
 				E40E246720B5521B009F8BE7 /* OOAttandanceTotalItemCell.xib */,
 				E40E246A20B68AEB009F8BE7 /* OOAttandanceTotalHeaderView.swift */,
 				E40E246C20B68AF6009F8BE7 /* OOAttandanceTotalHeaderView.xib */,
+				B1BB67B024C6E0320020BD7D /* OOAttendanceScheduleViewCell.swift */,
+				B1BB67B124C6E0320020BD7D /* OOAttendanceScheduleViewCell.xib */,
 			);
 			path = v;
 			sourceTree = "<group>";
@@ -5583,6 +5595,7 @@
 				E46E6C771DD41F5D00AB7561 /* ZSSh2.png in Resources */,
 				E4C24C54208D7EDE00E426B0 /* Contacts_new.storyboard in Resources */,
 				E46E6C7A1DD41F5D00AB7561 /* ZSSh3@2x.png in Resources */,
+				B1BB67B324C6E0320020BD7D /* OOAttendanceScheduleViewCell.xib in Resources */,
 				E46E6C681DD41F5D00AB7561 /* editor.html in Resources */,
 				E46E6C791DD41F5D00AB7561 /* ZSSh3.png in Resources */,
 				E46E6C6B1DD41F5D00AB7561 /* ZSSbold.png in Resources */,
@@ -5653,6 +5666,7 @@
 				E46E6C881DD41F5D00AB7561 /* ZSSindent@2x.png in Resources */,
 				E46E6C861DD41F5D00AB7561 /* ZSSimageDevice@2x.png in Resources */,
 				B17126C121084A2F00369F15 /* calendar.storyboard in Resources */,
+				B1BB678124C6D1DD0020BD7D /* OOAttendanceCheckInNewController.xib in Resources */,
 				E46E6C831DD41F5D00AB7561 /* ZSSimage.png in Resources */,
 				E46E6CA31DD41F5D00AB7561 /* ZSSsubscript.png in Resources */,
 				E428AF5220AA7A2400D964B9 /* OOAttanceHeaderView.xib in Resources */,
@@ -6054,6 +6068,7 @@
 				E4B781A01DFA9B23007B58A9 /* CMSItemDetailViewController.swift in Sources */,
 				E4B8887F1D9D48F1002E1A46 /* MainFileViewController.swift in Sources */,
 				E4B888DC1D9D48F1002E1A46 /* SettingViewController.swift in Sources */,
+				B1BB678024C6D1DD0020BD7D /* OOAttendanceCheckInNewController.swift in Sources */,
 				E4B781711DF8F36F007B58A9 /* CMSApplicationTableViewController.swift in Sources */,
 				E4C24BA320844F3C00E426B0 /* FileViewController.swift in Sources */,
 				E4C24C50208D7EDE00E426B0 /* OOContactSearchSectionHeaderView.swift in Sources */,
@@ -6295,6 +6310,7 @@
 				E4C24B4020844F3C00E426B0 /* JMSGConversation+.swift in Sources */,
 				B1FB9FE123029EC900A90722 /* UnitBreadcrumbViewCell.swift in Sources */,
 				E4B697002075DE5F0062F6E8 /* OOGuidePageController.swift in Sources */,
+				B1BB67B224C6E0320020BD7D /* OOAttendanceScheduleViewCell.swift in Sources */,
 				E4B888F81D9D48F1002E1A46 /* CreateProcessBean.swift in Sources */,
 				E40502C920722208009A8D30 /* ImageRow.swift in Sources */,
 				E40E24CB20B7DA3C009F8BE7 /* OOFormTextItemView.swift in Sources */,

+ 385 - 0
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttendanceCheckInNewController.swift

@@ -0,0 +1,385 @@
+//
+//  OOAttendanceCheckInNewController.swift
+//  O2Platform
+//
+//  Created by FancyLou on 2020/7/21.
+//  Copyright © 2020 zoneland. All rights reserved.
+//
+
+import UIKit
+import CocoaLumberjack
+import O2OA_Auth_SDK
+
+class OOAttendanceCheckInNewController: UIViewController {
+
+
+    @IBOutlet weak var checkInBtnTimeLabel: UILabel!
+    @IBOutlet weak var checkInBtnLable: UILabel!
+    @IBOutlet weak var checkInBtnView: UIView!
+    @IBOutlet weak var locationCheckImageView: UIImageView!
+    @IBOutlet weak var locationLabel: UILabel!
+    @IBOutlet weak var schedulesView: UICollectionView!
+
+    fileprivate let itemNumberInRow = 2
+
+    //定位
+    private var userLocation: BMKUserLocation!
+    private var locService: BMKLocationManager!
+    private var searchAddress: BMKGeoCodeSearch!
+    private var workPlaces: [OOAttandanceWorkPlace] = []
+
+    //定时器
+    private var timer: Timer?
+    private lazy var viewModel: OOAttandanceViewModel = {
+        return OOAttandanceViewModel()
+    }()
+    //打卡和班次
+    private var schedules: [OOAttandanceMobileScheduleInfo] = []
+    private var lastRecord: OOAttandanceMobileDetail? = nil
+    private var needCheckIn = false
+    private var isInWorkPlace = false
+    private var bmkResult: BMKReverseGeoCodeSearchResult? = nil
+    //打卡对象
+    var checkinForm: OOAttandanceMobileCheckinForm = OOAttandanceMobileCheckinForm()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        self.schedulesView.delegate = self
+        self.schedulesView.dataSource = self
+        self.schedulesView.register(UINib(nibName: "OOAttendanceScheduleViewCell", bundle: nil), forCellWithReuseIdentifier: "OOAttendanceScheduleViewCell")
+        self.checkInBtnView.addTapGesture { (tap) in
+            self.postCheckinButton(nil)
+        }
+
+        //初始化定时器
+        self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timeTick), userInfo: nil, repeats: true)
+        //获取数据
+        self.loadMyRecords()
+        //工作地址
+        self.loadWorkPlace()
+    }
+
+    override func viewWillAppear(_ animated: Bool) {
+        self.timer?.fire()
+        self.startLocationService()
+    }
+
+    override func viewWillDisappear(_ animated: Bool) {
+        self.timer?.invalidate()
+        self.stopLocationService()
+    }
+
+    ///打卡
+    private func postCheckinButton(_ scheduleInfo: OOAttandanceMobileScheduleInfo?) {
+        if !self.needCheckIn {
+            self.showError(title: "当前不需要打卡!")
+            return
+        }
+        if !self.isInWorkPlace {
+            self.showError(title: "不在打卡范围内!")
+            return
+        }
+
+
+        if let info = scheduleInfo, info.recordId != nil { //更新打卡
+            self.showDefaultConfirm(title: "更新打卡", message: "确定要更新这条打卡数据吗?") { (action) in
+                self.showLoading()
+                self.checkinForm.id = info.recordId
+                self.checkinForm.recordAddress = self.bmkResult?.address
+                self.checkinForm.desc = self.bmkResult?.sematicDescription
+                self.checkinForm.longitude = String(self.bmkResult?.location.longitude ?? 0.0)
+                self.checkinForm.latitude = String(self.bmkResult?.location.latitude ?? 0.0)
+                self.checkinForm.empNo = O2AuthSDK.shared.myInfo()?.employee
+                self.checkinForm.empName = O2AuthSDK.shared.myInfo()?.name
+                let currenDate = Date()
+                self.checkinForm.recordDateString = currenDate.toString("yyyy-MM-dd")
+                self.checkinForm.signTime = currenDate.toString("HH:mm:ss")
+                self.checkinForm.optMachineType = UIDevice.deviceModelReadable()
+                self.checkinForm.optSystemName = "\(UIDevice.systemName()) \(UIDevice.systemVersion())"
+                self.checkinForm.checkin_type = info.checkinType
+                self.viewModel.postMyCheckin(self.checkinForm) { (result) in
+                    DispatchQueue.main.async {
+                        self.hideLoading()
+                    }
+                    switch result {
+                    case .ok(_):
+                        self.loadMyRecords()
+                        break
+                    case .fail(let errorMessage):
+                        DDLogError(errorMessage)
+                        break
+                    default:
+                        break
+                    }
+                }
+            }
+        } else {
+            let reversed = self.schedules.reversed()
+            var newList: [OOAttandanceMobileScheduleInfo] = []
+            reversed.forEach { (info) in
+                if info.checkinStatus == "未打卡" {
+                    newList.append(info)
+                }
+            }
+            let checkType = newList.count > 0 ? newList.last!.checkinType : ""
+            self.showLoading()
+            checkinForm.id = nil
+            checkinForm.recordAddress = self.bmkResult?.address
+            checkinForm.desc = self.bmkResult?.sematicDescription
+            checkinForm.longitude = String(self.bmkResult?.location.longitude ?? 0.0)
+            checkinForm.latitude = String(self.bmkResult?.location.latitude ?? 0.0)
+            checkinForm.empNo = O2AuthSDK.shared.myInfo()?.employee
+            checkinForm.empName = O2AuthSDK.shared.myInfo()?.name
+            let currenDate = Date()
+            checkinForm.recordDateString = currenDate.toString("yyyy-MM-dd")
+            checkinForm.signTime = currenDate.toString("HH:mm:ss")
+            checkinForm.optMachineType = UIDevice.deviceModelReadable()
+            checkinForm.optSystemName = "\(UIDevice.systemName()) \(UIDevice.systemVersion())"
+            checkinForm.checkin_type = checkType
+            viewModel.postMyCheckin(checkinForm) { (result) in
+                DispatchQueue.main.async {
+                    self.hideLoading()
+                }
+                switch result {
+                case .ok(_):
+                    self.loadMyRecords()
+                    break
+                case .fail(let errorMessage):
+                    DDLogError(errorMessage)
+                    break
+                default:
+                    break
+                }
+            }
+        }
+
+
+    }
+
+    ///接收到位置信息
+    private func locationReceive(bmkResult: BMKReverseGeoCodeSearchResult, isIn: Bool, workPlace: OOAttandanceWorkPlace?) {
+        self.isInWorkPlace = isIn
+        self.bmkResult = bmkResult
+        if isIn {
+            // 打卡按钮启用
+            self.locationLabel.text = workPlace?.placeName
+            self.locationCheckImageView.image = UIImage(named: "icon__ok2_click")
+        } else {
+            //打卡按钮禁用
+            self.locationLabel.text = bmkResult.address
+            self.locationCheckImageView.image = UIImage(named: "icon_delete_1")
+        }
+    }
+
+    ///定位
+    private func startLocationService() {
+        locService = BMKLocationManager()
+        locService.desiredAccuracy = kCLLocationAccuracyBest
+        //设置返回位置的坐标系类型
+        locService.coordinateType = .BMK09LL
+        //设置距离过滤参数
+        locService.distanceFilter = kCLDistanceFilterNone;
+        //设置预期精度参数
+        locService.desiredAccuracy = kCLLocationAccuracyBest;
+        //设置应用位置类型
+        locService.activityType = .automotiveNavigation
+        //设置是否自动停止位置更新
+        locService.pausesLocationUpdatesAutomatically = false
+
+        locService.delegate = self
+        locService.startUpdatingLocation()
+
+        searchAddress = BMKGeoCodeSearch()
+        searchAddress.delegate = self
+    }
+    ///结束定位
+    private func stopLocationService() {
+        locService.stopUpdatingLocation()
+        locService.delegate = nil
+        searchAddress.delegate = nil
+    }
+
+    ///查询工作地址
+    private func loadWorkPlace() {
+        self.viewModel.getLocationWorkPlace { (myResult) in
+            switch myResult {
+            case .ok(let result):
+                if let model = result as? [OOAttandanceWorkPlace] {
+                    DispatchQueue.main.async {
+                        self.workPlaces = model
+                    }
+                }
+                break
+            case .fail(let s):
+                self.showError(title: "错误:\n\(s)")
+                break
+            default:
+                break
+            }
+        }
+    }
+    ///获取打卡记录和班次数据
+    private func loadMyRecords() {
+        self.viewModel.listMyRecords { (result) in
+            switch result {
+            case .ok(let record):
+                let model = record as? OOMyAttandanceRecords
+                let records = model?.records ?? []
+                self.lastRecord = records.last
+                var unCheckNumber = 0
+                self.schedules.removeAll()
+                model?.scheduleInfos?.forEach({ (f) in
+                    let info = OOAttandanceMobileScheduleInfo()
+                    info.signTime = f.signTime
+                    info.signDate = f.signDate
+                    info.checkinType = f.checkinType
+                    info.signSeq = f.signSeq
+                    let anyRecord = records.first { (detail) -> Bool in
+                        detail.checkin_type == f.checkinType
+                    }
+                    if anyRecord != nil {
+                        info.checkinStatus = "已打卡"
+                        info.recordId = anyRecord?.id
+                        info.checkinTime = anyRecord?.signTime
+                        unCheckNumber = 0
+                    } else {
+                        info.checkinStatus = "未打卡"
+                        unCheckNumber += 1
+                    }
+                    self.schedules.append(info)
+                })
+                DispatchQueue.main.async {
+                    if unCheckNumber > 0 {
+                        self.needCheckIn = true
+                        self.setCheckInBtnEnableStyle()
+                    } else {
+                        self.needCheckIn = false
+                        self.setCheckInBtnDisableStyle()
+                    }
+                    self.schedulesView.reloadData()
+                }
+                break
+            case .fail(let err):
+                DDLogError(err)
+                DispatchQueue.main.async {
+                    self.needCheckIn = false
+                    self.setCheckInBtnDisableStyle()
+                }
+                break
+            default:
+                DDLogError("default ..................")
+                break
+            }
+        }
+    }
+
+    private func setCheckInBtnDisableStyle() {
+        self.checkInBtnView.backgroundColor = UIColor(hex: "#cccccc")
+    }
+    private func setCheckInBtnEnableStyle() {
+        self.checkInBtnView.backgroundColor = base_color
+    }
+
+    ///刷新按钮时间
+    @objc private func timeTick() {
+        let now = Date().toString("HH:mm:ss")
+        self.checkInBtnTimeLabel.text = now
+    }
+
+}
+
+extension OOAttendanceCheckInNewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return self.schedules.count
+    }
+
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OOAttendanceScheduleViewCell", for: indexPath) as? OOAttendanceScheduleViewCell {
+            let s = self.schedules[indexPath.row]
+            let isLastRecord = s.recordId == self.lastRecord?.id
+            cell.setData(info: s, isLastRecord: isLastRecord)
+            return cell
+        }
+        return UICollectionViewCell()
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        let s = self.schedules[indexPath.row]
+        if let last = self.lastRecord, last.id == s.recordId {
+            self.postCheckinButton(s)
+        }
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        return CGSize(width: ((SCREEN_WIDTH - 52) / 2), height: 64)
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
+        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+    }
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 5.0
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
+        return 0.0
+    }
+
+}
+
+
+
+extension OOAttendanceCheckInNewController: BMKLocationManagerDelegate {
+
+    func bmkLocationManager(_ manager: BMKLocationManager, didUpdate location: BMKLocation?, orError error: Error?) {
+        if let loc = location?.location {
+            DDLogDebug("当前位置,\(loc.coordinate.latitude),\(loc.coordinate.longitude)")
+            //搜索到指定的地点
+            let re = BMKReverseGeoCodeSearchOption()
+            re.location = CLLocationCoordinate2D(latitude: loc.coordinate.latitude, longitude: loc.coordinate.longitude)
+            let _ = searchAddress.reverseGeoCode(re)
+        } else {
+            DDLogError("没有获取到定位信息!!!!!")
+        }
+    }
+
+
+}
+
+extension OOAttendanceCheckInNewController: BMKGeoCodeSearchDelegate {
+
+    /// 计算所有位置是否有一个位置在误差范围内
+    func calcErrorRange(_ checkinLocation: CLLocationCoordinate2D) -> (Bool, OOAttandanceWorkPlace?) {
+        var result = false
+        for item in self.workPlaces {
+            let longitude = Double((item.longitude)!)
+            let latitude = Double((item.latitude)!)
+            let eRange = item.errorRange!
+            let theLocation = CLLocationCoordinate2DMake(latitude!, longitude!)
+            result = BMKCircleContainsCoordinate(theLocation, checkinLocation, Double(eRange))
+            if result == true {
+                return (true, item)
+            }
+        }
+        return (false, nil)
+    }
+
+    func onGetReverseGeoCodeResult(_ searcher: BMKGeoCodeSearch?, result: BMKReverseGeoCodeSearchResult?, errorCode error: BMKSearchErrorCode) {
+        //发送定位的实时位置及名称信息
+        if let location = result?.location {
+            let calResult = calcErrorRange(location)
+            self.locationReceive(bmkResult: result!, isIn: calResult.0, workPlace: calResult.1)
+        }
+    }
+
+    func onGetGeoCodeResult(_ searcher: BMKGeoCodeSearch!, result: BMKGeoCodeSearchResult!, errorCode error: BMKSearchErrorCode) {
+        if Int(error.rawValue) == 0 {
+            DDLogDebug("result \(String(describing: result))")
+        } else {
+            DDLogDebug("result error  errorCode = \(Int(error.rawValue))")
+        }
+
+    }
+}
+

+ 125 - 0
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttendanceCheckInNewController.xib

@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina3_5" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="OOAttendanceCheckInNewController" customModule="O2Platform" customModuleProvider="target">
+            <connections>
+                <outlet property="checkInBtnLable" destination="X8B-av-xbY" id="ARp-kb-JGy"/>
+                <outlet property="checkInBtnTimeLabel" destination="PfA-VZ-bun" id="R84-Ot-xdP"/>
+                <outlet property="checkInBtnView" destination="isk-yQ-nXu" id="Jls-VF-uRR"/>
+                <outlet property="locationCheckImageView" destination="Bky-wJ-u7u" id="XEQ-ZH-CCw"/>
+                <outlet property="locationLabel" destination="vtH-4m-Kff" id="SGf-uJ-Fwc"/>
+                <outlet property="schedulesView" destination="s92-Qx-1Ry" id="rio-2o-BCr"/>
+                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="egU-OR-wFM">
+                    <rect key="frame" x="12" y="12" width="296" height="456"/>
+                    <subviews>
+                        <stackView opaque="NO" contentMode="scaleToFill" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="PGo-Jh-aHg">
+                            <rect key="frame" x="78.5" y="392" width="139" height="16"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_delete_1" translatesAutoresizingMaskIntoConstraints="NO" id="Bky-wJ-u7u">
+                                    <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="16" id="iTA-8k-nxI"/>
+                                        <constraint firstAttribute="width" constant="16" id="xJc-Yz-Adr"/>
+                                    </constraints>
+                                </imageView>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="位置信息还在查询中..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vtH-4m-Kff">
+                                    <rect key="frame" x="18" y="0.0" width="121" height="16"/>
+                                    <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
+                                    <nil key="textColor"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                            </subviews>
+                        </stackView>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="isk-yQ-nXu">
+                            <rect key="frame" x="84" y="240" width="128" height="128"/>
+                            <subviews>
+                                <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="PW9-7D-c8h">
+                                    <rect key="frame" x="28.5" y="39.5" width="71.5" height="49"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="打卡" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X8B-av-xbY">
+                                            <rect key="frame" x="18" y="0.0" width="35" height="20.5"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PfA-VZ-bun">
+                                            <rect key="frame" x="0.0" y="28.5" width="71.5" height="20.5"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                    </subviews>
+                                </stackView>
+                            </subviews>
+                            <color key="backgroundColor" red="0.98431372549999996" green="0.2784313725" blue="0.2784313725" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstItem="PW9-7D-c8h" firstAttribute="centerX" secondItem="isk-yQ-nXu" secondAttribute="centerX" id="01W-Hw-xyf"/>
+                                <constraint firstAttribute="height" constant="128" id="5oX-T9-tW0"/>
+                                <constraint firstAttribute="width" constant="128" id="QPk-5x-r92"/>
+                                <constraint firstItem="PW9-7D-c8h" firstAttribute="centerY" secondItem="isk-yQ-nXu" secondAttribute="centerY" id="to5-sg-0eV"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="64"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="s92-Qx-1Ry">
+                            <rect key="frame" x="12" y="24" width="272" height="192"/>
+                            <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                            <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="dXI-In-6zV">
+                                <size key="itemSize" width="128" height="128"/>
+                                <size key="headerReferenceSize" width="0.0" height="0.0"/>
+                                <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                                <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                            </collectionViewFlowLayout>
+                        </collectionView>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                    <constraints>
+                        <constraint firstItem="isk-yQ-nXu" firstAttribute="centerX" secondItem="egU-OR-wFM" secondAttribute="centerX" id="IcG-Rs-VhU"/>
+                        <constraint firstItem="s92-Qx-1Ry" firstAttribute="top" secondItem="egU-OR-wFM" secondAttribute="top" constant="24" id="Loh-oU-T2I"/>
+                        <constraint firstItem="PGo-Jh-aHg" firstAttribute="top" secondItem="isk-yQ-nXu" secondAttribute="bottom" constant="24" id="Zyi-gV-MYQ"/>
+                        <constraint firstAttribute="trailing" secondItem="s92-Qx-1Ry" secondAttribute="trailing" constant="12" id="cJX-mr-t3Y"/>
+                        <constraint firstItem="PGo-Jh-aHg" firstAttribute="centerX" secondItem="egU-OR-wFM" secondAttribute="centerX" id="cR7-GH-ohB"/>
+                        <constraint firstAttribute="bottom" secondItem="PGo-Jh-aHg" secondAttribute="bottom" constant="48" id="dNf-ci-mHw"/>
+                        <constraint firstItem="isk-yQ-nXu" firstAttribute="top" secondItem="s92-Qx-1Ry" secondAttribute="bottom" constant="24" id="ktB-yM-pA2"/>
+                        <constraint firstItem="s92-Qx-1Ry" firstAttribute="leading" secondItem="egU-OR-wFM" secondAttribute="leading" constant="12" id="miN-UF-2J7"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="24"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="0.94509803921568625" green="0.95294117647058818" blue="0.95686274509803915" alpha="1" colorSpace="calibratedRGB"/>
+            <constraints>
+                <constraint firstItem="egU-OR-wFM" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="12" id="2Jf-5x-ypY"/>
+                <constraint firstItem="egU-OR-wFM" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="12" id="o5Z-fa-Ogi"/>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="egU-OR-wFM" secondAttribute="bottom" constant="12" id="sS7-6u-vWD"/>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="egU-OR-wFM" secondAttribute="trailing" constant="12" id="zXe-8L-dIJ"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
+            <point key="canvasLocation" x="131.8840579710145" y="152.67857142857142"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="icon_delete_1" width="22" height="22"/>
+    </resources>
+</document>

+ 53 - 40
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OONewAttanceController.swift

@@ -10,66 +10,79 @@ import UIKit
 import Promises
 
 public class OONewAttanceController: UITabBarController, UITabBarControllerDelegate {
-    
-    private var viewModel:OOAttandanceViewModel = {
-       return OOAttandanceViewModel()
+
+    private var viewModel: OOAttandanceViewModel = {
+        return OOAttandanceViewModel()
     }()
-    
+
     public required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
 //        self.tabBarItemsAttributes = OONewAttanceController.items
         self.viewControllers = OONewAttanceController.myViewControllers
     }
-    
+
     override public func viewDidLoad() {
         super.viewDidLoad()
     }
-    
-    private func commonInit(_ result:Bool){
-        if result == true {
-//            self.tabBarItemsAttributes = OONewAttanceController.items
-            self.viewControllers = OONewAttanceController.myViewControllers
-        }else{
-//            self.tabBarItemsAttributes = OONewAttanceController.items1
-            self.viewControllers = OONewAttanceController.myViewControllers1
-        }
-    }
+
+//    private func commonInit(_ result:Bool){
+//        if result == true {
+////            self.tabBarItemsAttributes = OONewAttanceController.items
+//            self.viewControllers = OONewAttanceController.myViewControllers
+//        }else{
+////            self.tabBarItemsAttributes = OONewAttanceController.items1
+//            self.viewControllers = OONewAttanceController.myViewControllers1
+//        }
+//    }
 
     override public func didReceiveMemoryWarning() {
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
     }
-    
-    
-   private static let myViewControllers: [UIViewController] = {
+
+
+    private static let myViewControllers: [UIViewController] = {
         //打卡
-        let vc1 = OOAttanceCheckInController(nibName: "OOAttanceCheckInController", bundle: nil)
+        if let value = StandDefaultUtil.share.userDefaultGetValue(key: O2.O2_Attendance_version_key) as? Bool, value == true {
+            let vc1 = OOAttendanceCheckInNewController(nibName: "OOAttendanceCheckInNewController", bundle: nil)
+            vc1.tabBarItem = UITabBarItem(title: "打卡", image: UIImage(named: "icon_daka_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_daka")!)
+            let vc2 = OOAttanceTotalController(nibName: "OOAttanceTotalController", bundle: nil)
+            //        let nav2 = ZLNavigationController(rootViewController: vc2)
+            vc2.tabBarItem = UITabBarItem(title: "统计", image: UIImage(named: "icon_tongji_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_tongji")!)
+            //设置
+            let vc3 = OOAttanceSettingController(nibName: "OOAttanceSettingController", bundle: nil)
+            //        let nav3 = ZLNavigationController(rootViewController: vc3)
+            vc3.tabBarItem = UITabBarItem(title: "设置", image: UIImage(named: "icon_setup_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_setting")!)
+            return [vc1, vc2, vc3]
+        } else {
+            let vc1 = OOAttanceCheckInController(nibName: "OOAttanceCheckInController", bundle: nil)
 //        let nav1 = ZLNavigationController(rootViewController: vc1)
-        vc1.tabBarItem = UITabBarItem(title: "打卡", image: UIImage(named: "icon_daka_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_daka")!)
-        //统计
-        let vc2 = OOAttanceTotalController(nibName: "OOAttanceTotalController", bundle: nil)
+            vc1.tabBarItem = UITabBarItem(title: "打卡", image: UIImage(named: "icon_daka_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_daka")!)
+            //统计
+            let vc2 = OOAttanceTotalController(nibName: "OOAttanceTotalController", bundle: nil)
 //        let nav2 = ZLNavigationController(rootViewController: vc2)
-        vc2.tabBarItem = UITabBarItem(title: "统计", image: UIImage(named: "icon_tongji_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_tongji")!)
-        //设置
-        let vc3 = OOAttanceSettingController(nibName: "OOAttanceSettingController", bundle: nil)
+            vc2.tabBarItem = UITabBarItem(title: "统计", image: UIImage(named: "icon_tongji_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_tongji")!)
+            //设置
+            let vc3 = OOAttanceSettingController(nibName: "OOAttanceSettingController", bundle: nil)
 //        let nav3 = ZLNavigationController(rootViewController: vc3)
-        vc3.tabBarItem = UITabBarItem(title: "设置", image: UIImage(named: "icon_setup_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_setting")!)
-        return [vc1,vc2,vc3]
+            vc3.tabBarItem = UITabBarItem(title: "设置", image: UIImage(named: "icon_setup_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_setting")!)
+            return [vc1, vc2, vc3]
+        }
     }()
 
-    
-    private static let myViewControllers1: [UIViewController] = {
-        //打卡
-        let vc1 = OOAttanceCheckInController(nibName: "OOAttanceCheckInController", bundle: nil)
-        let nav1 = ZLNavigationController(rootViewController: vc1)
-        nav1.tabBarItem = UITabBarItem(title: "打卡", image: UIImage(named: "icon_daka_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_daka")!)
-        //统计
-        let vc2 = OOAttanceTotalController(nibName: "OOAttanceTotalController", bundle: nil)
-        let nav2 = ZLNavigationController(rootViewController: vc2)
-        nav2.tabBarItem = UITabBarItem(title: "统计", image: UIImage(named: "icon_tongji_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_tongji")!)
-        return [nav1,nav2]
-    }()
-    
+
+//    private static let myViewControllers1: [UIViewController] = {
+//        //打卡
+//        let vc1 = OOAttanceCheckInController(nibName: "OOAttanceCheckInController", bundle: nil)
+//        let nav1 = ZLNavigationController(rootViewController: vc1)
+//        nav1.tabBarItem = UITabBarItem(title: "打卡", image: UIImage(named: "icon_daka_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_daka")!)
+//        //统计
+//        let vc2 = OOAttanceTotalController(nibName: "OOAttanceTotalController", bundle: nil)
+//        let nav2 = ZLNavigationController(rootViewController: vc2)
+//        nav2.tabBarItem = UITabBarItem(title: "统计", image: UIImage(named: "icon_tongji_nor"), selectedImage: O2ThemeManager.image(for: "Icon.at_tongji")!)
+//        return [nav1,nav2]
+//    }()
+//
 
 
     public func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {

+ 22 - 8
o2ios/O2Platform/App/NewAttance-考勤打卡/m/OOAttandanceModels.swift

@@ -108,18 +108,30 @@ class OOAttandanceFeature: NSObject, DataModel {
     
 }
 
-// MARK: - istMyRecords 登录者当天的所有移动打卡信息记录 排版情况等
+// MARK: - 打卡班次对象 和 打卡结果拼接的结果
+class OOAttandanceMobileScheduleInfo: NSObject, DataModel {
+    @objc var signDate: String?
+    @objc var signTime: String?
+    @objc var checkinType: String?
+    var signSeq: Int?
+    @objc var checkinStatus: String? // 未打卡 已打卡
+    @objc var checkinTime: String? //打卡时间
+    @objc var recordId: String? //打卡结果的id 更新打卡用
+    
+    required override init() {
+        
+    }
+    
+}
+
+// MARK: - MyRecords 登录者当天的所有移动打卡信息记录 排版情况等
 class OOMyAttandanceRecords: NSObject, DataModel {
-    /**
-     {
-         "records": [],
-         "scheduleSetting": {},
-         "feature": {}
-     },
-     */
+   
     @objc var records:[OOAttandanceMobileDetail]?
     @objc var scheduleSetting:OOAttandanceScheduleSetting?
     @objc var feature: OOAttandanceFeature?
+    //2020-07-21 新添加的
+    @objc var scheduleInfos: [OOAttandanceFeature]?
     
     required override init() {
         
@@ -129,6 +141,8 @@ class OOMyAttandanceRecords: NSObject, DataModel {
 // MARK:- 提交打卡数据FormBean
 class OOAttandanceMobileCheckinForm:NSObject,DataModel {
     
+    @objc var id:String? //id 为空就是新增 有id就是更新
+    
     @objc var empNo:String? //员工号, 可以为空.
     
     @objc var empName:String? //员工姓名, 必须填写.

+ 41 - 0
o2ios/O2Platform/App/NewAttance-考勤打卡/v/OOAttendanceScheduleViewCell.swift

@@ -0,0 +1,41 @@
+//
+//  OOAttendanceScheduleViewCell.swift
+//  O2Platform
+//
+//  Created by FancyLou on 2020/7/21.
+//  Copyright © 2020 zoneland. All rights reserved.
+//
+
+import UIKit
+
+class OOAttendanceScheduleViewCell: UICollectionViewCell {
+    @IBOutlet weak var checkInTypeLabel: UILabel!
+    @IBOutlet weak var updateCheckInBtn: UIButton!
+    @IBOutlet weak var checkInStatusLabel: UILabel!
+    @IBOutlet weak var checkInTimeLabel: UILabel!
+    
+    
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        // Initialization code
+    }
+    
+    
+    func setData(info: OOAttandanceMobileScheduleInfo, isLastRecord: Bool) {
+        self.checkInTypeLabel.text = info.checkinType
+        self.checkInTimeLabel.text = info.signTime
+        self.checkInStatusLabel.text = info.checkinStatus
+        self.updateCheckInBtn.isHidden = true
+        if info.checkinStatus == "已打卡" {
+            if let time = info.checkinTime {
+                self.checkInStatusLabel.text = time.subString(from: 0, to: 5) + (info.checkinStatus ?? "")
+            }
+            if isLastRecord {
+                self.updateCheckInBtn.isHidden = false
+            }
+        }
+        
+    }
+
+}

+ 86 - 0
o2ios/O2Platform/App/NewAttance-考勤打卡/v/OOAttendanceScheduleViewCell.xib

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="OOAttendanceScheduleViewCell" id="gTV-IL-0wX" customClass="OOAttendanceScheduleViewCell" customModule="O2Platform" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="127" height="64"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="127" height="64"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KMo-pX-TmM">
+                        <rect key="frame" x="0.0" y="0.0" width="127" height="64"/>
+                        <subviews>
+                            <stackView opaque="NO" contentMode="scaleToFill" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="LgZ-1N-gXy">
+                                <rect key="frame" x="12" y="10" width="116" height="14.5"/>
+                                <subviews>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="上午上班打卡" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qug-eg-7N2">
+                                        <rect key="frame" x="0.0" y="0.0" width="74" height="14.5"/>
+                                        <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
+                                        <nil key="textColor"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="09:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OCm-CU-8sx">
+                                        <rect key="frame" x="82" y="0.0" width="34" height="14.5"/>
+                                        <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
+                                        <nil key="textColor"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                            </stackView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="09:00未打卡" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Cro-sW-eth">
+                                <rect key="frame" x="12" y="34.5" width="71" height="14.5"/>
+                                <fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
+                                <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dBx-af-tVn">
+                                <rect key="frame" x="72" y="31" width="50" height="27"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                <state key="normal" title="更新打卡"/>
+                            </button>
+                        </subviews>
+                        <color key="backgroundColor" red="0.95686274509803915" green="0.96470588235294119" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <constraints>
+                            <constraint firstItem="Cro-sW-eth" firstAttribute="top" secondItem="LgZ-1N-gXy" secondAttribute="bottom" constant="10" id="54c-S6-9LZ"/>
+                            <constraint firstItem="Cro-sW-eth" firstAttribute="leading" secondItem="KMo-pX-TmM" secondAttribute="leading" constant="12" id="6tz-hr-JUK"/>
+                            <constraint firstAttribute="trailing" secondItem="dBx-af-tVn" secondAttribute="trailing" constant="5" id="Fjp-Ob-VPw"/>
+                            <constraint firstItem="LgZ-1N-gXy" firstAttribute="top" secondItem="KMo-pX-TmM" secondAttribute="top" constant="10" id="LxA-yw-iLw"/>
+                            <constraint firstAttribute="bottom" secondItem="dBx-af-tVn" secondAttribute="bottom" constant="6" id="N0m-Tk-Q6G"/>
+                            <constraint firstItem="LgZ-1N-gXy" firstAttribute="leading" secondItem="KMo-pX-TmM" secondAttribute="leading" constant="12" id="qI9-Gb-Hyr"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="12"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+            </view>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="KMo-pX-TmM" secondAttribute="bottom" id="0be-yW-tuL"/>
+                <constraint firstItem="KMo-pX-TmM" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="8eg-ms-ZJe"/>
+                <constraint firstAttribute="trailing" secondItem="KMo-pX-TmM" secondAttribute="trailing" id="bEZ-fH-5Dh"/>
+                <constraint firstItem="KMo-pX-TmM" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="k5p-4g-vwg"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
+            <size key="customSize" width="127" height="64"/>
+            <connections>
+                <outlet property="checkInStatusLabel" destination="Cro-sW-eth" id="fad-PD-GVf"/>
+                <outlet property="checkInTimeLabel" destination="OCm-CU-8sx" id="Kmp-UM-pCP"/>
+                <outlet property="checkInTypeLabel" destination="Qug-eg-7N2" id="SiG-2z-01f"/>
+                <outlet property="updateCheckInBtn" destination="dBx-af-tVn" id="Qmf-cX-HLB"/>
+            </connections>
+            <point key="canvasLocation" x="-73.188405797101453" y="101.78571428571428"/>
+        </collectionViewCell>
+    </objects>
+</document>

+ 1 - 1
o2ios/O2Platform/App/NewAttance-考勤打卡/vm/OOAttandanceViewModel.swift

@@ -40,7 +40,7 @@ final class OOAttandanceViewModel: NSObject {
 
 extension OOAttandanceViewModel{
     
-    // MARK: -
+    // MARK: - 当天打卡记录和打卡班次情况
     func listMyRecords(_ completedBlock:@escaping CallbackBlockDefine) {
         ooAttanceAPI.request(.listMyRecord) { response in
             let myResult = OOResult<BaseModelClass<OOMyAttandanceRecords>>(response)

+ 30 - 0
o2ios/O2Platform/App/O2MainController.swift

@@ -35,6 +35,10 @@ class O2MainController: UITabBarController, UITabBarControllerDelegate {
     private lazy var imViewModel: IMViewModel = {
         return IMViewModel()
     }()
+    //考勤判断版本
+    private lazy var attendanceViewModel: OOAttandanceViewModel = {
+        return OOAttandanceViewModel()
+    }()
 
 
     override func viewDidLoad() {
@@ -57,6 +61,8 @@ class O2MainController: UITabBarController, UITabBarControllerDelegate {
         self._startWebsocket()
         //读取消息
         self.getConversationList()
+        //检查考勤版本
+        self.checkAttendanceVersion()
     }
 
     deinit {
@@ -141,6 +147,30 @@ class O2MainController: UITabBarController, UITabBarControllerDelegate {
             return nav
         }
     }
+    
+    // MARK: - 考勤判断版本
+    private func checkAttendanceVersion() {
+        self.attendanceViewModel.listMyRecords { (result) in
+            switch result {
+            case .ok(let data):
+                let model = data as? OOMyAttandanceRecords
+                if let s = model?.scheduleInfos, s.count > 0 {
+                    StandDefaultUtil.share.userDefaultCache(value: true as AnyObject, key: O2.O2_Attendance_version_key)
+                    DDLogDebug("考勤打卡新版。。。。。。。。。。。。。。。。。。")
+                }else {
+                    StandDefaultUtil.share.userDefaultCache(value: false as AnyObject, key: O2.O2_Attendance_version_key)
+                }
+                break
+            case .fail(let err):
+                DDLogError(err)
+                StandDefaultUtil.share.userDefaultCache(value: false as AnyObject, key: O2.O2_Attendance_version_key)
+                break
+            default:
+                StandDefaultUtil.share.userDefaultCache(value: false as AnyObject, key: O2.O2_Attendance_version_key)
+                break
+            }
+        }
+    }
 
     
     // MARK: - IM message

+ 3 - 0
o2ios/O2Platform/config/O2.swift

@@ -11,6 +11,9 @@ import CocoaLumberjack
 
 
 struct O2 {
+    //考勤打卡版本判断用的 userDefaults的key
+    public static let O2_Attendance_version_key = "attendance_version_key"
+    
     public static let O2_Word_draft_mode = "draft"
     public static let O2_First_ID = "(0)"
     /// EZSE: Returns app's name