Files
OrderScheduling/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift
ddisfriend ec55113ccb 优化
2025-11-12 15:23:51 +08:00

1836 lines
83 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// VehicleMonitoringController.swift
// OrderScheduling
//
// Created by on 2023/8/14.
//
import Foundation
import DDControlsKit_Private
import DDMAMapKit_Private
import DDAutoUIKit_Private
import RxSwift
import RxCocoa
import RxRelay
import JXCategoryView
import SnapKit
import DDUIGestureRecognizer
import DDUtilsSwiftKit_Private
fileprivate let vehicleMonitoringPannelViewHeight = auto(300)
fileprivate let vehicleMonitoringPannelCategoryViewHeight = auto(40)
fileprivate let vehicleMonitoringListDetailViewHeight = auto(270)
fileprivate let vehicleMonitoringPointAnnotationW = auto(120)
fileprivate let vehicleMonitoringPointAnnotationNameLeftInset = auto(35)
fileprivate let vehicleMonitoringPointAnnotationNameRightInset = auto(35)
fileprivate let vehicleMonitoringPointAnnotationNameAtLeastH = auto(30)
extension VehicleMonitoringController {
func addAction() {
MCOUNT.messageCountRelay
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] count in
if count > 0 {
self?.messageView.countLabel.isHidden = false
self?.messageView.countLabel.text = String(count)
self?.messageView.countLabel.snp.updateConstraints({ make in
make.width.equalTo(20)
})
}else{
self?.messageView.countLabel.isHidden = true
self?.messageView.countLabel.snp.updateConstraints({ make in
make.width.equalTo(0)
})
}
})
.disposed(by: disposeBag)
reloadRelay
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
self?.view.dd_showHUD()
})
.flatMapLatest {[weak self] _ in
guard let self = self else {
return Single.just((
nil as ResponseModel<VehicleMonitorListDataModel>?,
nil as ResponseModel<GeneralInfoDataModel>?,
[] as [AlarmListDataModel]
))
}
return Single.zip(RQ.vehicleMonitorList(),RQ.generalInfo(),self.getAllAlarmList(pageNum: 1, alarmList: []))
}
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _,_,_ in
self?.view.dd_hideHUD()
})
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response,generalInfo,alarmList in
if generalInfo?.success == true {
/// list0
if let lat = generalInfo?.data?.addressLat,let lon = generalInfo?.data?.addressLon {
self?.defaultCoordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
}else{
self?.defaultCoordinate = nil
}
}else{
self?.defaultCoordinate = nil
self?.view.dd_makeToast(response?.msg)
}
if response?.success == true {
self?.dataModel = response?.data
let rosterTitle = "排班"
let rosterCount = NSNumber(value: response?.data?.vehicleMonitorCount.rosterCount ?? 0)
let onLineTitle = "上线"
let onLineCount = NSNumber(value: response?.data?.vehicleMonitorCount.onLineCount ?? 0)
let lostConnectionTitle = "掉线"
let lostConnectionCount = NSNumber(value: response?.data?.vehicleMonitorCount.lostConnectionCount ?? 0)
let leisureTitle = "空闲"
let leisureCount = NSNumber(value: response?.data?.vehicleMonitorCount.leisureCount ?? 0)
let busyTitle = "忙碌"
let busyCount = NSNumber(value: response?.data?.vehicleMonitorCount.busyCount ?? 0)
// let alarmCount = String(response?.data?.vehicleMonitorCount.alarmCount ?? 0)+"\n"+""
if USER.supplierType == 1 {
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [rosterTitle,onLineTitle,lostConnectionTitle,leisureTitle,busyTitle]
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.counts = [rosterCount,onLineCount,lostConnectionCount,leisureCount,busyCount]
}else{
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = [onLineTitle,lostConnectionTitle,leisureTitle,busyTitle]
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.counts = [onLineCount,lostConnectionCount,leisureCount,busyCount]
}
///
self?.resetSelectedOfData()
///
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.reloadDataWithoutListContainer()
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.listContainer.reloadData()
self?.categoryView(self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView, didSelectedItemAt: self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.selectedIndex ?? 0)
}else{
self?.view.dd_makeToast(response?.msg)
self?.dataModel = nil
self?.mapModel = nil
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles = []
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.counts = []
self?.vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.reloadData()
}
if alarmList.count > 0 {
self?.alarmList = alarmList
var items : [String] = []
for i in 0..<alarmList.count {
let item = alarmList[i]
items.append((item.alarmTypeString ?? "")+":"+(item.vehicleName ?? ""))
}
self?.vehicleMonitoringView.offlineView.offLineLabel.items = items
self?.vehicleMonitoringView.alarmView.count.text = String(items.count)
self?.vehicleMonitoringView.offlineView.isHidden = false
self?.vehicleMonitoringView.alarmView.isHidden = false
}else{
self?.vehicleMonitoringView.offlineView.isHidden = true
self?.vehicleMonitoringView.alarmView.isHidden = true
}
///
self?.vehicleMonitoringListDetailView.backButton.sendActions(for: .touchUpInside)
///
self?.modifyMapAnchor()
})
.disposed(by: disposeBag)
messageTapGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
MESSAGETOOL.openMessageCenter(by: self?.navigationController)
})
.disposed(by: disposeBag)
refreshButton.rx.tap
.subscribe(onNext: {[weak self] _ in
self?.preRefreshRelay.accept(nil)
})
.disposed(by: disposeBag)
vehicleLogoutView.cancelButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
ENTRY.dismiss(name: vehicleLogoutEntry)
})
.disposed(by: disposeBag)
vehicleLogoutView.sureButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
ENTRY.dismiss(name: vehicleLogoutEntry) {[weak self] in
self?.vehicleLogoutRelay.accept(self?.vehicleLogoutModel)
}
})
.disposed(by: disposeBag)
showVehicleEntryRelay
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] model in
if let vehicleName = model?.vehicleName,let driverName = model?.driverName {
self?.vehicleLogoutView.titleLabel.text = vehicleName+"/"+driverName
self?.vehicleLogoutView.contentLabel.text = "该车辆确定要退出登录吗?"
self?.vehicleLogoutModel = model
}
if let view = self?.vehicleLogoutView {
ENTRY.showVehicleLogoutEntry(view: view,name: vehicleLogoutEntry)
}
})
.disposed(by: disposeBag)
vehicleLogoutRelay
.filter({ model in
return model?.vehicleId != nil
})
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
self?.view.dd_showHUD()
})
.flatMapLatest { model in
return RQ.vehicleLogout(parameters: VehicleLogoutParameters(vehicleId: model!.vehicleId!))
}
.observe(on: MainScheduler.instance)
.do(onNext: {[weak self] _ in
self?.view.dd_hideHUD()
})
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] response in
if response?.success == true {
self?.reloadRelay.accept(nil)
}else{
self?.view.dd_makeToast(response?.msg)
}
})
.disposed(by: disposeBag)
vehicleMonitoringListDetailView.callButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
if let model = self?.selectedModel {
URLLINKS.openUrl(type: .phone, appending: model.driverPhone)
}
})
.disposed(by: disposeBag)
vehicleMonitoringListDetailView.backButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
self?.hideListDetail()
self?.hideIncidentLocation()
})
.disposed(by: disposeBag)
vehicleMonitoringListDetailView.settingButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
if let view = self?.vehicleConfigView {
view.showMonitoring(false)
ENTRY.showVehicleMonitoringConfigEntry(view: view, name: vehicleMonitoringConfigEntry)
}
})
.disposed(by: disposeBag)
vehicleMonitoringListDetailView.showIncidentLocationHandler = {[weak self] incidentCoordi,destCoordi in
///
self?.hideIncidentLocation()
let incidentCoordiAnnotation = MAPointAnnotation()
incidentCoordiAnnotation.dd_image = UIImage(named: "vehichleMonitoring_start_32")
incidentCoordiAnnotation.coordinate = incidentCoordi
incidentCoordiAnnotation.annotationClass = VehicleMonitoringIncidentLocationAnnotationView.self
incidentCoordiAnnotation.tag = -1
self?.vehicleMonitoringView.maMapView.maMapView.addAnnotation(incidentCoordiAnnotation)
if let destCoordi {
let destCoordiAnnotation = MAPointAnnotation()
destCoordiAnnotation.dd_image = UIImage(named: "vehichleMonitoring_terminal_32")
destCoordiAnnotation.coordinate = destCoordi
destCoordiAnnotation.annotationClass = VehicleMonitoringIncidentLocationAnnotationView.self
destCoordiAnnotation.tag = -2
self?.vehicleMonitoringView.maMapView.maMapView.addAnnotation(destCoordiAnnotation)
}
}
vehicleMonitoringListDetailView.showOrderDetailHandler = { taskModel in
WEBTOOL.open(name: .workOrderDetail, appending: "&queryType=\(OrderTypeEnum.TO_RESCUE.rawValue)&userOrderId=\(taskModel.userOrderId)&orderCode=\(taskModel.orderCode)&taskOrderId=\(taskModel.taskOrderId)")
}
vehicleConfigView.cancelGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: { _ in
ENTRY.dismiss(name: vehicleMonitoringConfigEntry)
})
.disposed(by: disposeBag)
vehicleMonitoringListDetailView.videoButton.rx.tap
.observe(on: ConcurrentMainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
self?.navigationController?.pushViewController(VehicleMonitorVideoController(vehicleId: self?.selectedModel?.vehicleId,simNumber: self?.selectedModel?.number), animated: true)
})
.disposed(by: disposeBag)
vehicleMonitoringView.alarmView.dd_addTapGesture {
WEBTOOL.open(name: .vehicleAlarmList, appending: nil)
}
vehicleMonitoringView.offlineView.offLineLabel.onTap = {[weak self] index in
let model = self?.alarmList[index]
if let code = model?.code {
WEBTOOL.open(name: .vehicleAlarmDetail, appending: "&code=\(code)")
}
}
vehicleConfigView.logoutGes.rx.event
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
ENTRY.dismiss(name: vehicleMonitoringConfigEntry) {[weak self] in
self?.showVehicleEntryRelay.accept(self?.selectedModel)
}
})
.disposed(by: disposeBag)
// tabBar
preRefreshRelay
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
NewTraining.default.newTrainingRelay.accept(nil)
MCOUNT.newestMessage()
self?.reloadRelay.accept(nil)
})
.disposed(by: disposeBag)
}
func getAllAlarmList(pageNum: Int,alarmList: [AlarmListDataModel]) -> Single<[AlarmListDataModel]> {
func recursive(pageNum: Int,alarmList: [AlarmListDataModel]) -> Single<[AlarmListDataModel]> {
return RQ.alarmList(parameters: AlarmListParameters(pageNum: pageNum, supplierId: USER.supplierId,handStatus: AlarmListParameters.HandStatusEnum.pending.rawValue))
.flatMap { response in
if (response?.data?.count ?? 0) == 0 {
return Single.create { single in
single(.success(alarmList))
return Disposables.create()
}
}
let addAlarmList = alarmList + (response?.data ?? [])
return recursive(pageNum: pageNum + 1, alarmList: addAlarmList)
}
}
return recursive(pageNum: 1, alarmList: [])
}
}
extension VehicleMonitoringController : DDMAMapViewDelegate {
public func dd_mapView(_ mapView: MAMapView, viewFor annotation: MAAnnotation) -> MAAnnotationView {
if annotation.isMember(of: MAPointAnnotation.self) {
let pointAnnotation = annotation as! MAPointAnnotation
if pointAnnotation.annotationClass == VehicleMonitoringPointAnnotation.self{
let DriverPointReuseIndentifier = "DispatchMapStatePointAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: DriverPointReuseIndentifier) as? VehicleMonitoringPointAnnotation
if annotationView == nil {
annotationView = VehicleMonitoringPointAnnotation.init(annotation: pointAnnotation, reuseIdentifier: DriverPointReuseIndentifier)
}
let model = mapModel?[pointAnnotation.tag]
/// idannotation
pointAnnotation.vehicleId = model?.vehicleId
annotationView!.annotation = pointAnnotation
annotationView?.zIndex = model?.zIndex ?? 0
if let annotationView, let model, let shouldShowSmallAnnotation {
annotationViewStateConfig(annotationView: annotationView, vehicleModel: model, shouldShowSmallAnnotation: shouldShowSmallAnnotation)
}
let labelSize = annotationView?.titleLabel.sizeThatFits(CGSize(width: auto(100), height: .infinity)) ?? .zero
let annotationViewW = labelSize.width
let annotationViewH = auto(50) + labelSize.height
annotationView?.frame = CGRect(origin: (annotationView?.frame.origin)!, size: CGSize(width: annotationViewW, height: annotationViewH))
return annotationView!
}
if pointAnnotation.annotationClass == DispatchMapSericeAddressPointAnnotation.self{
let DriverPointReuseIndentifier = "DispatchMapSericeAddressPointAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: DriverPointReuseIndentifier) as? DispatchMapSericeAddressPointAnnotation
if annotationView == nil {
annotationView = DispatchMapSericeAddressPointAnnotation.init(annotation: pointAnnotation, reuseIdentifier: DriverPointReuseIndentifier)
}
annotationView!.annotation = pointAnnotation
return annotationView!
}
if pointAnnotation.annotationClass == VehicleMonitoringIncidentLocationAnnotationView.self {
let incidentPointReuseIndentifier = "VehicleMonitoringIncidentLocationAnnotationView"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: incidentPointReuseIndentifier) as? VehicleMonitoringIncidentLocationAnnotationView
if annotationView == nil {
annotationView = VehicleMonitoringIncidentLocationAnnotationView.init(annotation: pointAnnotation, reuseIdentifier: incidentPointReuseIndentifier)
}
annotationView!.annotation = pointAnnotation
annotationView!.image = pointAnnotation.dd_image
annotationView!.zIndex = Int.max
return annotationView!
}
}
return MAAnnotationView.init(annotation: annotation, reuseIdentifier: "cell")
}
public func dd_mapView(_ mapView: MAMapView, didAnnotationViewTapped view: MAAnnotationView) {
if view.isKind(of: VehicleMonitoringPointAnnotation.self) != true {
return
}
zIndex += 1
view.zIndex = zIndex
if let tapPointAnnotation = view.annotation as? MAPointAnnotation, let mapModel = self.mapModel {
let model = mapModel[tapPointAnnotation.tag]
selectVehicle(selectState: true,vehicleModel: model, currentTableViewVehicleModels: mapModel, selectIndex: tapPointAnnotation.tag, mapView: mapView)
if model.vehicleId == selectedModel?.vehicleId {
if isListDetailShowed == false {
showListDetail(vehicleModel: model)
}else{
hideListDetail()
}
}else{
showListDetail(vehicleModel: model)
}
}
}
public func dd_mapView(_ mapView: MAMapView, mapDidZoomByUser wasUserAction: Bool) {
// ////
// if mapView.zoomLevel <= 14 {
// shouldShowSmallAnnotation = true
//
// if isShowSmallAnnotation == false {
// let annotations = mapView.annotations
// mapView.removeAnnotations(annotations)
// mapView.addAnnotations(annotations)
//
// isShowSmallAnnotation = true
// }
// }else{
shouldShowSmallAnnotation = false
if isShowSmallAnnotation == true {
let annotations = mapView.annotations
mapView.removeAnnotations(annotations)
mapView.addAnnotations(annotations)
isShowSmallAnnotation = false
}
// }
}
}
// MARK: JXCategoryListContainerViewDelegate
extension VehicleMonitoringController : JXCategoryListContainerViewDelegate {
public func number(ofListsInlistContainerView listContainerView: JXCategoryListContainerView!) -> Int {
return vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles.count
}
public func listContainerView(_ listContainerView: JXCategoryListContainerView!, initListFor index: Int) -> JXCategoryListContentViewDelegate! {
var vc : VehicleMonitoringListController?
if USER.supplierType == 1 {
if index == 0 {
vc = VehicleMonitoringListController(models: dataModel?.rosterList,isPaiban: true)
}else if index == 1 {
vc = VehicleMonitoringListController(models: dataModel?.onLineList)
}else if index == 2 {
vc = VehicleMonitoringListController(models: dataModel?.lostConnectionList)
}else if index == 3 {
vc = VehicleMonitoringListController(models: dataModel?.leisureList)
}else if index == 4 {
vc = VehicleMonitoringListController(models: dataModel?.busyList)
}else if index == 5 {
vc = VehicleMonitoringListController(models: dataModel?.alarmList,isAlarm: true)
}
}else{
if index == 0 {
vc = VehicleMonitoringListController(models: dataModel?.onLineList)
}else if index == 1 {
vc = VehicleMonitoringListController(models: dataModel?.lostConnectionList)
}else if index == 2 {
vc = VehicleMonitoringListController(models: dataModel?.leisureList)
}else if index == 3 {
vc = VehicleMonitoringListController(models: dataModel?.busyList)
}else if index == 4 {
vc = VehicleMonitoringListController(models: dataModel?.alarmList,isAlarm: true)
}
}
vc?.selectCellBlock = {[weak self] (model,item) in
if let models = vc?.models,let mapView = self?.vehicleMonitoringView.maMapView.maMapView {
self?.selectVehicle(selectState: true,vehicleModel: model, currentTableViewVehicleModels: models, selectIndex: item, mapView: mapView)
self?.showMapCenter(with: model)
}
}
vc?.showDetailBlock = {[weak self] (model,item) in
if let models = vc?.models,let mapView = self?.vehicleMonitoringView.maMapView.maMapView {
self?.selectVehicle(selectState: true,vehicleModel: model, currentTableViewVehicleModels: models, selectIndex: item, mapView: mapView)
self?.showListDetail(vehicleModel: model)
self?.showMapCenter(with: model)
}
}
vc?.showMaxBlock = {[weak self] in
if self?.pannelPanGes.panGesValue.expandLevel != .max {
self?.pannelPanGes.expand(.max)
}
}
return vc
}
}
extension VehicleMonitoringController : JXCategoryViewDelegate {
public func categoryView(_ categoryView: JXCategoryBaseView!, didSelectedItemAt index: Int) {
DispatchQueue.main.async {[weak self] in
self?.reloadData(index: index)
if let containerView = categoryView.listContainer as? JXCategoryListContainerView {
let key = NSNumber(value: index)
let vc = containerView.validListDict[key]
self?.currentTableView = (vc as? VehicleMonitoringListController)?.vehicleMonitoringListView.tableView
}
}
}
func reloadData(index:Int) {
/// annottaion
if let annotations = vehicleMonitoringView.maMapView.maMapView.annotations {
vehicleMonitoringView.maMapView.maMapView.removeAnnotations(annotations)
}
/// mapModel
if USER.supplierType == 1 {
if index == 0 {
mapModel = dataModel?.rosterList
}else if index == 1 {
mapModel = dataModel?.onLineList
}else if index == 2 {
mapModel = dataModel?.lostConnectionList
}else if index == 3 {
mapModel = dataModel?.leisureList
}else if index == 4 {
mapModel = dataModel?.busyList
}else if index == 5 {
mapModel = dataModel?.alarmList
}
}else{
if index == 0 {
mapModel = dataModel?.onLineList
}else if index == 1 {
mapModel = dataModel?.lostConnectionList
}else if index == 2 {
mapModel = dataModel?.leisureList
}else if index == 3 {
mapModel = dataModel?.busyList
}else if index == 4 {
mapModel = dataModel?.alarmList
}
}
for index in 0..<(mapModel?.count ?? 0) {
let model = mapModel?[index]
if model?.lat != nil && model?.lon != nil {
let coordinate = CLLocationCoordinate2D(latitude: Double(model?.lat ?? "") ?? 0, longitude: Double(model?.lon ?? "") ?? 0)
let pointAnnotation = MAPointAnnotation.init()
pointAnnotation.annotationClass = VehicleMonitoringPointAnnotation.self
pointAnnotation.coordinate = coordinate
pointAnnotation.tag = index
vehicleMonitoringView.maMapView.maMapView.addAnnotation(pointAnnotation)
}
}
if let annotations = vehicleMonitoringView.maMapView.maMapView.annotations, annotations.isEmpty == false {
vehicleMonitoringView.maMapView.maMapView.showAnnotations(annotations, animated: true)
modifyMapAnchor()
}else{
let coordinate = defaultCoordinate ?? vehicleMonitoringView.maMapView.maMapView.userLocation.coordinate
vehicleMonitoringView.maMapView.maMapView.setCenter(coordinate, animated: true)
vehicleMonitoringView.maMapView.maMapView.zoomLevel = 18
}
}
}
extension VehicleMonitoringController {
func selectVehicle(selectState: Bool,vehicleModel: VehicleMonitorListDataModel.ItemModel, currentTableViewVehicleModels: [VehicleMonitorListDataModel.ItemModel],selectIndex: Int, mapView: MAMapView) {
resetSelectedOfDataModel()
/// mapModelvehicleId
if let selectedModel = currentTableViewVehicleModels.first(where: {[weak self] model in
return model.vehicleId == self?.selectedVehicleId
}), let selectedTableView = self.selectedTableView,let currentTableView = self.currentTableView, selectedTableView == currentTableView {
if let tag = currentTableViewVehicleModels.firstIndex(where: { model in
return selectedModel.vehicleId == model.vehicleId
}) {
if let annotation = mapView.annotations.first(where: { annotation in
let pointAnnotation = annotation as? MAPointAnnotation
return pointAnnotation?.vehicleId == selectedModel.vehicleId
}) {
mapView.removeAnnotation(annotation as? MAAnnotation)
selectedModel.isSelected = false
let coordinate = CLLocationCoordinate2D(latitude: Double(selectedModel.lat ?? "0") ?? 0, longitude: Double(selectedModel.lon ?? "0") ?? 0)
let pointAnnotation = MAPointAnnotation.init()
pointAnnotation.annotationClass = VehicleMonitoringPointAnnotation.self
pointAnnotation.coordinate = coordinate
pointAnnotation.tag = tag
mapView.addAnnotation(pointAnnotation)
}
}
}
///
/// annotation
if let oldAnnotation = mapView.annotations.first(where: { annotation in
let pointAnnotation = annotation as? MAPointAnnotation
return pointAnnotation?.tag == selectIndex
}) {
mapView.removeAnnotation(oldAnnotation as? MAAnnotation)
}
/// true
vehicleModel.isSelected = selectState
zIndex+=1
vehicleModel.zIndex = zIndex
/// annotation
let coordinate = CLLocationCoordinate2D(latitude: Double(vehicleModel.lat ?? "0") ?? 0, longitude: Double(vehicleModel.lon ?? "0") ?? 0)
let pointAnnotation = MAPointAnnotation.init()
pointAnnotation.annotationClass = VehicleMonitoringPointAnnotation.self
pointAnnotation.coordinate = coordinate
pointAnnotation.tag = selectIndex
mapView.addAnnotation(pointAnnotation)
/// id
selectedVehicleId = vehicleModel.vehicleId
/// tableviewtableview
selectedTableView?.reloadData()
currentTableView?.reloadData()
selectedTableView = currentTableView
}
func resetSelectedOfDataModel() {
// tableview
for index in 0..<(dataModel?.rosterList.count ?? 0) {
let _model = dataModel?.rosterList[index]
_model?.isSelected = false
}
for index in 0..<(dataModel?.onLineList.count ?? 0) {
let _model = dataModel?.onLineList[index]
_model?.isSelected = false
}
for index in 0..<(dataModel?.lostConnectionList.count ?? 0) {
let _model = dataModel?.lostConnectionList[index]
_model?.isSelected = false
}
for index in 0..<(dataModel?.leisureList.count ?? 0) {
let _model = dataModel?.leisureList[index]
_model?.isSelected = false
}
for index in 0..<(dataModel?.busyList.count ?? 0) {
let _model = dataModel?.busyList[index]
_model?.isSelected = false
}
for index in 0..<(dataModel?.alarmList.count ?? 0) {
let _model = dataModel?.alarmList[index]
_model?.isSelected = false
}
}
func annotationViewStateConfig(annotationView: VehicleMonitoringPointAnnotation,vehicleModel: VehicleMonitorListDataModel.ItemModel, shouldShowSmallAnnotation: Bool) {
var backgroundColor : UIColor?
var bigImage : UIImage?
var middleImage : UIImage?
if let _ = vehicleModel.alarmType {
}else{
switch vehicleModel.vehicleStatus?.code {
case VehicleStatusCodeEnum.offLine.rawValue,VehicleStatusCodeEnum.lostConnection.rawValue:
backgroundColor = .hex("858585")
bigImage = UIImage(named: "vehicleMonitoring_offline_big")
middleImage = UIImage(named: "vehicleMonitor_offline_cell_flag_bg")
break
case VehicleStatusCodeEnum.onLine.rawValue,VehicleStatusCodeEnum.leisure.rawValue:
backgroundColor = .hex("067BB9")
bigImage = UIImage(named: "vehicleMonitoring_empty_big")
middleImage = UIImage(named: "vehicleMonitor_empty_cell_flag_bg")
break
case VehicleStatusCodeEnum.busy.rawValue:
backgroundColor = .hex("F05412")
bigImage = UIImage(named: "vehicleMonitoring_busy_big")
middleImage = UIImage(named: "vehicleMonitor_busy_cell_onlne_bg")
break
case VehicleStatusCodeEnum.BuyBusy.rawValue:
backgroundColor = .hex("F05412")
bigImage = UIImage(named: "vehicleMonitoring_busy_big")
middleImage = UIImage(named: "vehicleMonitor_busy_cell_onlne_bg")
break
default:
backgroundColor = .hex("858585")
bigImage = UIImage(named: "vehicleMonitoring_offline_big")
middleImage = UIImage(named: "vehicleMonitor_offline_cell_flag_bg")
break
}
switch vehicleModel.onlineStatus?.code {
case OnlineStatusModel.OnlineStatusCodeEnum.onLine.rawValue:
annotationView.bigStateLabel.textColor = .white
annotationView.middleStateLabel.textColor = .white
break
default:
annotationView.bigStateLabel.textColor = .hex("CCCCCC")
annotationView.middleStateLabel.textColor = .hex("CCCCCC")
break
}
}
if vehicleModel.isSelected == true {
annotationView.bigImageView.isHidden = false
annotationView.bigStateLabel.isHidden = false
annotationView.smallImageView.isHidden = true
annotationView.middleImageView.isHidden = true
annotationView.bigImageView.image = bigImage
annotationView.bigStateLabel.text = vehicleModel.vehicleTypeStr
annotationView.bigWorkingCountlabel.isHidden = !vehicleModel.shouldShowWorkingCount
if let workingCount = vehicleModel.workingCount {
annotationView.bigWorkingCountlabel.text = String(workingCount)
}
annotationView.titleLabel.backgroundColor = .hex("FFFFFF")
}else{
annotationView.bigImageView.isHidden = true
annotationView.bigStateLabel.isHidden = true
if shouldShowSmallAnnotation == true {
annotationView.smallImageView.isHidden = false
annotationView.middleImageView.isHidden = true
annotationView.middleStateLabel.isHidden = true
annotationView.titleLabel.isHidden = true
annotationView.smallImageView.backgroundColor = backgroundColor
}else{
annotationView.smallImageView.isHidden = true
annotationView.middleImageView.isHidden = false
annotationView.middleStateLabel.isHidden = false
annotationView.titleLabel.isHidden = false
annotationView.middleImageView.image = middleImage
annotationView.middleStateLabel.text = vehicleModel.vehicleTypeStr
annotationView.middleWorkingCountlabel.isHidden = !vehicleModel.shouldShowWorkingCount
if let workingCount = vehicleModel.workingCount {
annotationView.middleWorkingCountlabel.text = String(workingCount)
}
}
annotationView.titleLabel.backgroundColor = .clear
}
annotationView.titleLabel.text = vehicleModel.vehicleName
}
func showListDetail(vehicleModel: VehicleMonitorListDataModel.ItemModel) {
selectedModel = vehicleModel
vehicleMonitoringListDetailView.stateLabel.text = vehicleModel.vehicleTypeStr
vehicleMonitoringListDetailView.nameLabel.text = vehicleModel.driverName
vehicleMonitoringListDetailView.vehicleLabel.text = vehicleModel.vehicleName
switch vehicleModel.vehicleStatus?.code {
case VehicleStatusCodeEnum.offLine.rawValue,VehicleStatusCodeEnum.lostConnection.rawValue:
vehicleMonitoringListDetailView.icon.image = UIImage(named: "vehicleMonitor_offline_cell_flag_bg")
break
case VehicleStatusCodeEnum.onLine.rawValue,VehicleStatusCodeEnum.leisure.rawValue:
vehicleMonitoringListDetailView.icon.image = UIImage(named: "vehicleMonitor_empty_cell_flag_bg")
break
case VehicleStatusCodeEnum.busy.rawValue:
vehicleMonitoringListDetailView.icon.image = UIImage(named: "vehicleMonitor_busy_cell_onlne_bg")
break
case VehicleStatusCodeEnum.BuyBusy.rawValue:
vehicleMonitoringListDetailView.icon.image = UIImage(named: "vehicleMonitor_busy_cell_onlne_bg")
break
default:
vehicleMonitoringListDetailView.icon.image = UIImage(named: "vehicleMonitor_offline_cell_flag_bg")
break
}
vehicleMonitoringListDetailView.updateData(taskModels: vehicleModel.taskList ?? [])
///
if let number = vehicleModel.number, number.isEmpty == false {
vehicleMonitoringListDetailView.videoButton.isHidden = false
vehicleMonitoringListDetailView.videoButton.snp.updateConstraints { make in
make.left.equalTo(vehicleMonitoringListDetailView.settingButton.snp.right).offset(auto(10))
make.width.equalTo(auto(23))
}
}else{
vehicleMonitoringListDetailView.videoButton.isHidden = true
vehicleMonitoringListDetailView.videoButton.snp.updateConstraints { make in
make.left.equalTo(vehicleMonitoringListDetailView.settingButton.snp.right).offset(0)
make.width.equalTo(0)
}
}
if let terminalType = vehicleModel.terminalType {
vehicleMonitoringListDetailView.locationLabel.text = "定位:\(terminalType)"
}
var workScheduleString = ""
if let startTime = vehicleModel.startTime, let endTime = vehicleModel.endTime {
workScheduleString = "\(startTime)-\(endTime)"
}
if workScheduleString.count > 0 {
if let rosterType = vehicleModel.rosterType {
workScheduleString = workScheduleString.appending("/\(rosterType)")
}
}else{
workScheduleString = vehicleModel.rosterType ?? ""
}
if workScheduleString.count == 0 {
vehicleMonitoringListDetailView.workScheduleTitle.text = nil
vehicleMonitoringListDetailView.workScheduleContent.text = nil
}else{
vehicleMonitoringListDetailView.workScheduleTitle.text = "排班:"
vehicleMonitoringListDetailView.workScheduleContent.text = workScheduleString
}
/// maxpannelView
if pannelPanGes.panGesValue.expandLevel == .max {
previousStateOfPannelView = .max
pannelPanGes.expand(.default)
}
///
vehicleMonitoringListDetailView.snp.updateConstraints({ make in
make.left.equalTo(vehicleMonitoringView.snp.right).offset(-vehicleMonitoringView.width)
})
UIView.animate(withDuration: 0.25) {[weak self] in
self?.view.layoutIfNeeded()
}
isListDetailShowed = true
}
func hideListDetail() {
vehicleMonitoringListDetailView.snp.updateConstraints({ make in
make.left.equalTo(vehicleMonitoringView.snp.right).offset(0)
})
UIView.animate(withDuration: 0.25) {[weak self] in
self?.view.layoutIfNeeded()
}
if previousStateOfPannelView == .max {
pannelPanGes.expand(.max)
previousStateOfPannelView = .min
}
isListDetailShowed = false
}
func hideIncidentLocation() {
let annotations = vehicleMonitoringView.maMapView.maMapView.annotations.filter { item in
let annotation = item as? MAPointAnnotation
return annotation?.annotationClass == VehicleMonitoringIncidentLocationAnnotationView.self
}
vehicleMonitoringView.maMapView.maMapView.removeAnnotations(annotations)
}
func showMapCenter(with vehicleModel: VehicleMonitorListDataModel.ItemModel) {
/// item,
if let lat = vehicleModel.lat,let lon = vehicleModel.lon {
modifyMapAnchor()
vehicleMonitoringView.maMapView.maMapView.setCenter(CLLocationCoordinate2D(latitude: Double(lat) ?? 0, longitude: Double(lon) ?? 0), animated: true)
}
}
func modifyMapAnchor() {
let mapHeight = vehicleMonitoringView.maMapView.height
var deltaH = 0.0
if pannelPanGes.panGesValue.expandLevel == .max {
deltaH = mapHeight - pannelPanGes.panGesValue.maxDisplayHeight
}else if pannelPanGes.panGesValue.expandLevel == .default {
deltaH = mapHeight - pannelPanGes.panGesValue.defaultDisplayHeight
}else{
deltaH = mapHeight - pannelPanGes.panGesValue.minDisplayHeight
}
let scale = (deltaH/2) / (mapHeight/2)
vehicleMonitoringView.maMapView.maMapView.screenAnchor = CGPoint(x: 0.5, y: 0.5 * scale)
}
func resetSelectedOfData() {
currentTableView = nil
selectedTableView = nil
selectedVehicleId = nil
selectedModel = nil
}
}
open class VehicleMonitoringController : ZDViewController {
/// tabBar
struct SafeAreaInsets {
static var safeAreaInsetsTop = 0.0
static var safeAreaInsetsBottom = 0.0
}
private let vehicleMonitoringView = VehicleMonitoringView(titles:[])
private let vehicleMonitoringListDetailView = VehicleMonitoringListDetailView(taskModels: [])
public lazy var categoryContainerView = JXCategoryListContainerView(type: .scrollView, delegate: self)
private let pannelPanGes = DDUIPanGestureRecognizer.init() /// pannel
private let reloadRelay = ReplayRelay<Any?>.create(bufferSize: 1) ///
private var dataModel : VehicleMonitorListDataModel? ///
private var mapModel : [VehicleMonitorListDataModel.ItemModel]? /// category
public var zIndex = 0 /// annotation
private var currentTableView : DDTableView? ///
private var selectedVehicleId : Int? ///
private var selectedTableView : DDTableView? ///
private var selectedModel : VehicleMonitorListDataModel.ItemModel? ///
private var previousStateOfPannelView : DDUIPanGestureRecognizer.ExpandLevel = .min /// pannelviewmax
private var isListDetailShowed : Bool = false ///
private var shouldShowSmallAnnotation : Bool? = false /// annotation
private var isShowSmallAnnotation : Bool? = false /// annotation
private var defaultCoordinate : CLLocationCoordinate2D? /// list0
private let messageTapGes = UITapGestureRecognizer() ///
private let messageView = MessageView() ///
public let refreshButton = DDButton.dd_initCustom() ///
private var preRefreshRelay = ReplayRelay<Any?>.create(bufferSize: 1) ///
private let vehicleLogoutView = VehicleLogoutView() /// 退
private let vehicleConfigView = VehicleMonitoringConfigView()
private var showVehicleEntryRelay = ReplayRelay<VehicleMonitorListDataModel.ItemModel?>.create(bufferSize: 1) /// 退
private var vehicleLogoutModel : VehicleMonitorListDataModel.ItemModel?
private var vehicleLogoutRelay = ReplayRelay<VehicleMonitorListDataModel.ItemModel?>.create(bufferSize: 1)
private var alarmList : [AlarmListDataModel] = []
private let disposeBag = DisposeBag()
open override func viewDidLoad() {
super.viewDidLoad()
dd_navigationItemTitle = "车辆监控"
dd_navigationBarTitleTextAttributes = [.foregroundColor : UIColor.white(alpha: 0.7),.font:UIFont.mediumFont(17)]
dd_navigationBarBarButtonItemAttributes = [.foregroundColor : UIColor.white]
navigationItem.leftBarButtonItems = nil
addSubviews()
addAction()
}
func addSubviews() {
view.addSubview(vehicleMonitoringView)
view.addSubview(vehicleMonitoringListDetailView)
vehicleMonitoringListDetailView.snp.makeConstraints { make in
make.left.equalTo(vehicleMonitoringView.snp.right)
make.bottom.equalTo(vehicleMonitoringView)
make.width.equalTo(vehicleMonitoringView)
make.height.equalTo(vehicleMonitoringListDetailViewHeight)
}
CustomMapStyle.customMap(vehicleMonitoringView.maMapView.maMapView)
vehicleMonitoringView.maMapView.delegate = self
vehicleMonitoringView.maMapView.maMapView.showsUserLocation = true
vehicleMonitoringView.maMapView.maMapView.userTrackingMode = .follow
vehicleMonitoringView.maMapView.maMapView.customizeUserLocationAccuracyCircleRepresentation = true
vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.delegate = self
vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.listContainer = categoryContainerView
pannelPanGes.panGesValue.from = .bottom
pannelPanGes.expandLevelChangedHandler = {[weak self] old, new in
self?.modifyMapAnchor()
}
vehicleMonitoringView.vehicleMonitoringPannelView.addGestureRecognizer(pannelPanGes)
messageView.titleLabel.text = "消息"
messageView.addGestureRecognizer(messageTapGes)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: messageView)
messageView.snp.makeConstraints { make in
make.height.equalTo(40)
make.width.greaterThanOrEqualTo(40)
}
refreshButton.setTitle("刷新", for: .normal)
refreshButton.setTitleColor(.hex("FFFFFF").alpha(0.7), for: .normal)
refreshButton.titleLabel?.font = .mediumFont(auto(14))
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: refreshButton)
if let categoryContainerView {
vehicleMonitoringView.vehicleMonitoringPannelView.radiusView.addSubview(categoryContainerView)
}
}
open override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
SafeAreaInsets.safeAreaInsetsTop = view.safeAreaInsets.top
if view.safeAreaInsets.bottom > 0 {
SafeAreaInsets.safeAreaInsetsBottom = view.safeAreaInsets.bottom
}
vehicleMonitoringView.snp.remakeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(SafeAreaInsets.safeAreaInsetsTop)
make.bottom.equalToSuperview().offset(-SafeAreaInsets.safeAreaInsetsBottom)
}
let vehicleMonitoringPannelViewCornerRadius = auto(16)
vehicleMonitoringView.vehicleMonitoringPannelView.layer.cornerRadius = vehicleMonitoringPannelViewCornerRadius
vehicleMonitoringView.vehicleMonitoringPannelView.layer.masksToBounds = true
vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.snp.remakeConstraints { make in
make.top.equalToSuperview().priority(.high)
make.left.right.equalToSuperview()
make.height.equalTo(vehicleMonitoringPannelCategoryViewHeight)
}
vehicleMonitoringListDetailView.layer.cornerRadius = vehicleMonitoringPannelViewCornerRadius
vehicleMonitoringListDetailView.layer.masksToBounds = true
categoryContainerView?.snp.remakeConstraints({ make in
make.top.equalTo(vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.snp.bottom)
make.left.right.equalToSuperview()
make.bottom.equalToSuperview()
})
let minDisplayHeight = vehicleMonitoringPannelCategoryViewHeight
let maxDisplayHeight = view.height - SafeAreaInsets.safeAreaInsetsTop - SafeAreaInsets.safeAreaInsetsBottom - auto(150)
let defaultDisplayHeight = vehicleMonitoringListDetailViewHeight
vehicleMonitoringView.maMapView.snp.remakeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview()
make.bottom.equalToSuperview().offset(-vehicleMonitoringPannelCategoryViewHeight + vehicleMonitoringPannelViewCornerRadius)
}
if pannelPanGes.panGesValue.expandLevel == .max {
vehicleMonitoringView.vehicleMonitoringPannelView.snp.remakeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(maxDisplayHeight)
make.bottom.equalToSuperview()
}
}else if pannelPanGes.panGesValue.expandLevel == .min {
vehicleMonitoringView.vehicleMonitoringPannelView.snp.remakeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(maxDisplayHeight)
make.bottom.equalToSuperview().offset(maxDisplayHeight - minDisplayHeight)
}
}else if pannelPanGes.panGesValue.expandLevel == .default {
vehicleMonitoringView.vehicleMonitoringPannelView.snp.remakeConstraints { make in
make.left.right.equalToSuperview()
make.height.equalTo(maxDisplayHeight)
make.bottom.equalToSuperview().offset(maxDisplayHeight - defaultDisplayHeight)
}
}
pannelPanGes.panGesValue.minDisplayHeight = minDisplayHeight
pannelPanGes.panGesValue.maxDisplayHeight = maxDisplayHeight
pannelPanGes.panGesValue.defaultDisplayHeight = defaultDisplayHeight
/// categoryView
dd_navigationBarBackgroundColor = .hex("354683")
}
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
vehicleMonitoringView.maMapView.maMapView.logoCenter = CGPoint(x: vehicleMonitoringView.maMapView.maMapView.logoCenter.x, y: CGRectGetMaxY(vehicleMonitoringView.maMapView.maMapView.frame) - 30)
}
open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
hideListDetail()
resetSelectedOfData()
resetSelectedOfDataModel()
vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.reloadDataWithoutListContainer()
vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.listContainer.reloadData()
if vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.titles.count > 0 {
categoryView(vehicleMonitoringView.vehicleMonitoringPannelView.categoryView, didSelectedItemAt: vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.selectedIndex)
}
}
open override func reloadData() {
super.reloadData()
preRefreshRelay.accept(nil)
}
}
// MARK: UI
open class VehicleMonitoringView : DDView {
public let vehicleMonitoringPannelView : VehicleMonitoringPannelView
public let maMapView : DDMAMapView
public let coverView : DDView
public let tapGes : UITapGestureRecognizer
public let panGes : UIPanGestureRecognizer
public let offlineView : VehicleDeviceOffLineView
public let alarmView : VehicleAlarmView
public init(titles: [String]) {
vehicleMonitoringPannelView = VehicleMonitoringPannelView(titles:titles)
maMapView = DDMAMapView()
coverView = DDView()
tapGes = UITapGestureRecognizer()
panGes = UIPanGestureRecognizer()
offlineView = VehicleDeviceOffLineView()
alarmView = VehicleAlarmView()
super.init(frame: .zero)
maMapView.maMapView.isRotateCameraEnabled = false
addSubview(maMapView)
offlineView.offlineIconImageView.image = UIImage(named: "vehicleMonitoring_offline_icon")
offlineView.backgroundColor = .dd_hex(light: "FB8958", dark: "FB8958")
offlineView.layer.cornerRadius = 6
offlineView.isHidden = true
addSubview(offlineView)
alarmView.imageView.image = UIImage(named: "vehicleMonitoring_alarm")
alarmView.isHidden = true
addSubview(alarmView)
coverView.addGestureRecognizer(tapGes)
coverView.addGestureRecognizer(panGes)
coverView.isHidden = true
addSubview(coverView)
addSubview(vehicleMonitoringPannelView)
coverView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
alarmView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(10)
make.right.equalToSuperview().offset(-10)
}
offlineView.snp.makeConstraints { make in
make.centerY.equalTo(alarmView)
make.centerX.equalToSuperview()
make.height.equalTo(35)
make.width.equalTo(200)
}
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
open class VehicleDeviceOffLineView : DDView {
let offlineIconImageView : DDImageView
let offLineLabel : VerticalLoopScrollLabel
public override init(frame: CGRect) {
offlineIconImageView = DDImageView()
offLineLabel = VerticalLoopScrollLabel()
super.init(frame: frame)
addSubview(offlineIconImageView)
addSubview(offLineLabel)
offlineIconImageView.snp.makeConstraints { make in
make.left.equalTo(15)
make.centerY.equalToSuperview()
}
offLineLabel.snp.makeConstraints { make in
make.left.equalTo(offlineIconImageView.snp.right).offset(10)
make.right.equalToSuperview().offset(-10)
make.top.bottom.equalToSuperview().inset(8)
}
}
@MainActor required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
open class VehicleAlarmView : DDView {
public let imageView : DDImageView
public let count : DDLabel
public override init(frame: CGRect) {
self.imageView = DDImageView()
self.count = DDLabel()
super.init(frame: frame)
addSubview(imageView)
count.layer.cornerRadius = 1
count.layer.borderColor = UIColor.dd_hex(light: "FFFFFF", dark: "FFFFFF").cgColor
count.layer.borderWidth = 0.8
count.layer.masksToBounds = true
count.backgroundColor = .dd_hex(light: "F93D3D", dark: "F93D3D")
count.textColor = .dd_hex(light: "FFFFFF", dark: "FFFFFF")
count.font = .dd_systemFont(ofSize: 12, weight: .semibold)
addSubview(count)
imageView.snp.makeConstraints { make in
make.left.top.bottom.equalToSuperview()
make.width.height.equalTo(50)
}
count.snp.makeConstraints { make in
make.left.equalTo(imageView.snp.right).offset(-15)
make.right.lessThanOrEqualToSuperview()
make.top.equalTo(imageView.snp.top)
}
}
@MainActor required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
open class VehicleMonitoringPannelView : DDView {
public let radiusView : DDView
public let categoryView : JXCategoryNumberView
public init(titles:[String]) {
radiusView = DDView()
categoryView = JXCategoryNumberView.init()
categoryView.titles = titles
super.init(frame: .zero)
backgroundColor = .hex("FBFBFB")
radiusView.backgroundColor = .clear
addSubview(radiusView)
categoryView.titleNumberOfLines = 1
categoryView.titleColor = .hex("737373").alpha(0.55)
categoryView.titleSelectedColor = .hex("3678FF")
categoryView.titleFont = .mediumFont(auto(14))
categoryView.backgroundColor = .hex("FBFBFB")
let indicator = JXCategoryIndicatorLineView()
indicator.indicatorColor = .hex("3678FF")
indicator.verticalMargin = 0
categoryView.indicators = [indicator]
categoryView.numberBackgroundColor = .red
categoryView.numberLabelOffset = CGPoint(x: 5, y: 0)
radiusView.addSubview(categoryView)
radiusView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.bottom.equalToSuperview()
}
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
open class VehicleMonitoringIncidentLocationAnnotationView : MAAnnotationView {
}
open class VehicleMonitoringPointAnnotation : MAAnnotationView {
public let clearView : DDView
public var disposeBag : DisposeBag
public var smallImageView : DDImageView
public var middleImageView : DDImageView
public var bigImageView : DDImageView
public var titleLabel : DDLabel
public var middleStateLabel : DDLabel
public var bigStateLabel : DDLabel
public var middleWorkingCountlabel : DDLabel
public var bigWorkingCountlabel : DDLabel
override init!(annotation: MAAnnotation!, reuseIdentifier: String!) {
clearView = DDView.init()
disposeBag = DisposeBag()
smallImageView = DDImageView()
middleImageView = DDImageView()
bigImageView = DDImageView()
titleLabel = DDLabel.dd_init(withText: "", font: .mediumFont(11), textColor: .hex("03030F"))
middleStateLabel = DDLabel.dd_init(withText: "", font: .mediumFont(10), textColor: .white)
bigStateLabel = DDLabel.dd_init(withText: "", font: .mediumFont(18), textColor: .white)
middleWorkingCountlabel = DDLabel.dd_init(withText: "", font: .mediumFont(7), textColor: .white)
bigWorkingCountlabel = DDLabel.dd_init(withText: "", font: .mediumFont(9), textColor: .white)
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
setUpSubviews()
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
func setUpSubviews(){
clearView.isUserInteractionEnabled = false
addSubview(clearView)
smallImageView.layer.cornerRadius = auto(5)
smallImageView.layer.borderColor = UIColor.white.cgColor
smallImageView.layer.borderWidth = 1
smallImageView.backgroundColor = .hex("858585")
clearView.addSubview(smallImageView)
titleLabel.textAlignment = .center
clearView.addSubview(titleLabel)
middleImageView.layer.cornerRadius = auto(11)
middleImageView.layer.borderColor = UIColor.white.cgColor
middleImageView.layer.borderWidth = 1
middleImageView.backgroundColor = .hex("858585")
clearView.addSubview(middleImageView)
middleImageView.addSubview(middleStateLabel)
middleWorkingCountlabel.backgroundColor = .hex("F93D3D")
middleWorkingCountlabel.textAlignment = .center
middleWorkingCountlabel.layer.borderColor = UIColor.white.cgColor
middleWorkingCountlabel.layer.borderWidth = 1
middleImageView.addSubview(middleWorkingCountlabel)
clearView.addSubview(bigImageView)
bigImageView.addSubview(bigStateLabel)
bigWorkingCountlabel.backgroundColor = .hex("F93D3D")
bigWorkingCountlabel.textAlignment = .center
bigWorkingCountlabel.layer.borderColor = UIColor.white.cgColor
bigWorkingCountlabel.layer.borderWidth = 1
bigImageView.addSubview(bigWorkingCountlabel)
clearView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
smallImageView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.height.equalTo(auto(10))
}
titleLabel.snp.makeConstraints { make in
make.bottom.left.right.equalToSuperview()
}
middleImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().priority(.high)
make.width.height.equalTo(auto(22))
make.bottom.equalTo(titleLabel.snp.top)
}
middleStateLabel.snp.makeConstraints { make in
make.centerX.centerY.equalTo(middleImageView)
}
middleWorkingCountlabel.layer.cornerRadius = auto(5)
middleWorkingCountlabel.layer.masksToBounds = true
middleWorkingCountlabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(-auto(5))
make.right.equalToSuperview().offset(auto(5))
make.width.height.equalTo(10)
}
bigImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalToSuperview().priority(.high)
make.width.equalTo(auto(42))
make.height.equalTo(auto(50))
make.bottom.equalTo(titleLabel.snp.top)
}
bigStateLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset(-auto(4))
}
bigWorkingCountlabel.layer.cornerRadius = auto(7.5)
bigWorkingCountlabel.layer.masksToBounds = true
bigWorkingCountlabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(-auto(2.5))
make.right.equalToSuperview().offset(auto(2.5))
make.width.height.equalTo(15)
}
}
}
class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDelegate, JXCategoryViewDelegate {
func number(ofListsInlistContainerView listContainerView: JXCategoryListContainerView!) -> Int {
return taskModels.count
}
func listContainerView(_ listContainerView: JXCategoryListContainerView!, initListFor index: Int) -> JXCategoryListContentViewDelegate! {
let view = VMLDContainerView()
view.updateData(taskModel: taskModels[index])
view.orderNumButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] _ in
if let taskModel = self?.taskModels[index] {
self?.showOrderDetailHandler?(taskModel)
}
})
.disposed(by: disposeBag)
return view
}
func categoryView(_ categoryView: JXCategoryBaseView!, didSelectedItemAt index: Int) {
pageNumLabel.text = "\(index + 1)/\(taskModels.count)"
let taskModel = taskModels[index]
if let vehiclePointLatitude = taskModel.vehiclePointLatitude, let vehiclePointLongitude = taskModel.vehiclePointLongitude {
showIncidentLocationHandler?(CLLocationCoordinate2D(latitude: vehiclePointLatitude, longitude: vehiclePointLongitude),(taskModel.destinationLatitude != nil && taskModel.destinationLongitude != nil) ? CLLocationCoordinate2D(latitude: taskModel.destinationLatitude!, longitude: taskModel.destinationLongitude!) : nil)
}
}
public var taskModels : [VehicleMonitorListDataModel.TaskModel]
public let backButton : DDButton
public let icon : DDImageView
public let stateLabel : DDLabel
public let vehicleLabel : DDLabel
public let settingButton : DDButton
public let videoButton : DDButton
public let locationLabel : DDLabel
public let workScheduleTitle : DDLabel
public let workScheduleContent : DDLabel
public let nameLabel : DDLabel
public let callButton : DDButton
public let containerView : DDView
public var categoryView : JXCategoryTitleView
public lazy var categoryContainerView = JXCategoryListContainerView(type: .scrollView, delegate: self)
public let pageNumImageView : DDImageView
public let pageNumLabel : DDLabel
public let previousButton : DDButton
public let nextButton : DDButton
public var emptyLabel : DDLabel
public let disposeBag = DisposeBag()
public var showIncidentLocationHandler : ((CLLocationCoordinate2D,CLLocationCoordinate2D?) -> Void)?
public var showOrderDetailHandler : ((VehicleMonitorListDataModel.TaskModel) -> Void)?
public init(taskModels: [VehicleMonitorListDataModel.TaskModel]) {
self.taskModels = taskModels
backButton = DDButton.dd_initCustom()
backButton.setImage(UIImage(named: "vehicleMonitoring_back"), for: .normal)
icon = DDImageView()
stateLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(10)), textColor: .white)
vehicleLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(14)), textColor: .hex("11142F"))
settingButton = DDButton.dd_initCustom()
settingButton.setBackgroundImage(UIImage(named: "vehicleMonitoring_setting"), for: .normal)
videoButton = DDButton.dd_initCustom()
videoButton.setBackgroundImage(UIImage(named: "vehicleMonitoring_video_icon"), for: .normal)
locationLabel = DDLabel.dd_init(withText: "", font: .regularFont(12), textColor: .hex("11142F"))
workScheduleTitle = DDLabel.dd_init(withText: "", font: .regularFont(12), textColor: .hex("11142F"))
workScheduleContent = DDLabel.dd_init(withText: "", font: .regularFont(12), textColor: .hex("11142F"))
nameLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(12)), textColor: .hex("11142F"))
callButton = DDButton.dd_initCustom()
callButton.setBackgroundImage(UIImage(named: "vehicleMonitor_call_cell"), for: .normal)
containerView = DDView()
categoryView = JXCategoryTitleView.init()
pageNumImageView = DDImageView(image: UIImage(named: "vehicleMonitor_pageNum_bg"))
pageNumLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(8)), textColor: .white)
previousButton = DDButton.dd_initCustom()
previousButton.setImage(UIImage(named: "vehicleMonitoring_previous_gray"), for: .normal)
nextButton = DDButton.dd_initCustom()
nextButton.setImage(UIImage(named: "vehicleMonitoring_next_gray"), for: .normal)
emptyLabel = DDLabel.dd_init(withText: "暂无执行中订单", font: .mediumFont(auto(18)), textColor: .hex("11142F").alpha(0.6))
super.init(frame: .zero)
backgroundColor = .white
layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
backgroundColor = .hex("F2F7FA")
addSubview(backButton)
addSubview(icon)
stateLabel.textAlignment = .center
icon.addSubview(stateLabel)
addSubview(vehicleLabel)
addSubview(settingButton)
addSubview(videoButton)
addSubview(locationLabel)
addSubview(nameLabel)
addSubview(callButton)
addSubview(workScheduleTitle)
addSubview(workScheduleContent)
containerView.backgroundColor = .hex("FAFAFA")
containerView.layer.cornerRadius = auto(5)
containerView.layer.masksToBounds = true
addSubview(containerView)
categoryView.delegate = self
if let categoryContainerView = self.categoryContainerView {
containerView.addSubview(categoryContainerView)
categoryView.listContainer = categoryContainerView
}
categoryContainerView?.addSubview(pageNumImageView)
pageNumLabel.textAlignment = .center
pageNumImageView.addSubview(pageNumLabel)
categoryContainerView?.addSubview(previousButton)
categoryContainerView?.addSubview(nextButton)
containerView.addSubview(emptyLabel)
containerView.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(auto(7))
make.top.equalTo(workScheduleContent.snp.bottom).offset(auto(5))
make.bottom.equalToSuperview().offset(-auto(10))
}
categoryContainerView?.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
emptyLabel.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
}
pageNumImageView.snp.makeConstraints { make in
make.left.top.equalToSuperview()
make.width.equalTo(auto(20))
make.height.equalTo(auto(14))
}
pageNumLabel.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
previousButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(-auto(10))
make.centerY.equalToSuperview()
make.width.equalTo(auto(30))
make.height.equalTo(auto(40))
}
nextButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(auto(10))
make.centerY.equalToSuperview()
make.width.equalTo(auto(30))
make.height.equalTo(auto(40))
}
backButton.snp.makeConstraints { make in
make.left.equalTo(0)
make.top.equalTo(0)
make.width.height.equalTo(auto(40))
}
icon.snp.makeConstraints { make in
make.left.equalTo(backButton.snp.right).offset(0)
make.centerY.equalTo(backButton)
make.width.height.equalTo(auto(20))
}
stateLabel.snp.makeConstraints { make in
make.edges.equalTo(icon)
}
vehicleLabel.snp.makeConstraints { make in
make.left.equalTo(icon.snp.right).offset(auto(3))
make.centerY.equalTo(icon)
}
settingButton.snp.makeConstraints { make in
make.left.equalTo(vehicleLabel.snp.right).offset(auto(5))
make.centerY.equalTo(icon)
make.width.equalTo(auto(16))
make.height.equalTo(auto(14))
}
videoButton.snp.makeConstraints { make in
make.left.equalTo(settingButton.snp.right).offset(auto(10))
make.centerY.equalTo(icon)
make.width.equalTo(auto(23))
make.height.equalTo(auto(13))
}
locationLabel.snp.makeConstraints { make in
make.left.equalTo(videoButton.snp.right).offset(auto(10))
make.centerY.equalTo(icon)
}
callButton.snp.makeConstraints { make in
make.right.equalTo(-auto(20))
make.centerY.equalTo(backButton)
make.width.height.equalTo(auto(25))
}
nameLabel.snp.makeConstraints { make in
make.right.equalTo(callButton.snp.left).offset(-auto(8))
make.centerY.equalTo(callButton)
}
workScheduleTitle.snp.makeConstraints { make in
make.top.equalTo(backButton.snp.bottom)
make.left.equalTo(icon)
}
workScheduleContent.snp.makeConstraints { make in
make.left.equalTo(workScheduleTitle.snp.right).offset(auto(10))
make.right.lessThanOrEqualToSuperview().offset(-auto(20))
make.top.equalTo(workScheduleTitle)
}
previousButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] in
if let index = self?.categoryView.selectedIndex {
if index > 0 {
let newIndex = index - 1
self?.categoryView.selectItem(at: newIndex)
}
}
})
.disposed(by: disposeBag)
nextButton.rx.tap
.observe(on: MainScheduler.instance)
.subscribe(onNext: {[weak self] in
if let index = self?.categoryView.selectedIndex, let allCount = self?.taskModels.count {
let validCount = allCount - 1
if index < validCount {
let newIndex = index + 1
self?.categoryView.selectItem(at: newIndex)
}
}
})
.disposed(by: disposeBag)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func updateData(taskModels: [VehicleMonitorListDataModel.TaskModel]) {
self.taskModels = taskModels
let allCount = taskModels.count
if allCount > 0 {
var titles : [String] = []
for index in 0..<allCount {
titles.append("\(index)")
}
categoryView.titles = titles
emptyLabel.isHidden = true
categoryContainerView?.isHidden = false
}else{
categoryView.titles = nil
emptyLabel.isHidden = false
categoryContainerView?.isHidden = true
}
categoryView.reloadData()
if allCount > 0 {
categoryView.selectItem(at: 0)
}
}
}
class VMLDContainerView : DDView , JXCategoryListContentViewDelegate {
var orderNumButton : UIButton
var titleLabel : DDLabel
var stateLabel : DDLabel
var line : DDView
var incidentIcon : UIImageView
var incidentLabel : DDLabel
var destIcon : UIImageView
var destLabel : DDLabel
var contractImageView : DDImageView
var contractTitle : DDLabel
var contractContent : DDLabel
var distanceFromPointLabel : DDLabel
var remainTimeLabel : DDLabel
var distanceLabel : DDLabel
var disposeBag : DisposeBag
override init(frame: CGRect) {
orderNumButton = UIButton()
orderNumButton.setTitleColor(.hex("0E76F4"), for: .normal)
orderNumButton.titleLabel?.font = .regularFont(auto(12))
titleLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(12)), textColor: .hex("000000").alpha(0.7))
stateLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(12)), textColor: .hex("09B820"))
line = DDView()
incidentIcon = UIImageView(image: UIImage(named: "vehichleMonitoring_start_16"))
incidentLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(12)), textColor: .hex("000000").alpha(0.7))
destIcon = UIImageView(image: UIImage(named: "vehichleMonitoring_terminal_16"))
destLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(12)), textColor: .hex("000000").alpha(0.7))
contractImageView = DDImageView()
contractTitle = DDLabel.dd_init(withText: "", font: .regularFont(12), textColor: .hex("11142F"))
contractContent = DDLabel.dd_init(withText: "", font: .regularFont(12), textColor: .hex("11142F"))
distanceFromPointLabel = DDLabel()
remainTimeLabel = DDLabel()
distanceLabel = DDLabel()
disposeBag = DisposeBag()
super.init(frame: frame)
addSubview(orderNumButton)
addSubview(titleLabel)
stateLabel.numberOfLines = 0
addSubview(stateLabel)
line.backgroundColor = .hex("F1F2F5")
addSubview(line)
addSubview(incidentIcon)
incidentLabel.numberOfLines = 0
incidentLabel.textAlignment = .left
addSubview(incidentLabel)
addSubview(destIcon)
destLabel.numberOfLines = 0
destLabel.textAlignment = .left
addSubview(destLabel)
addSubview(contractImageView)
addSubview(contractTitle)
contractContent.textAlignment = .right
contractContent.numberOfLines = 2
addSubview(contractContent)
addSubview(distanceFromPointLabel)
addSubview(remainTimeLabel)
addSubview(distanceLabel)
orderNumButton.snp.makeConstraints { make in
make.left.equalTo(auto(20))
make.top.equalTo(auto(15))
make.height.equalTo(auto(18))
}
titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
titleLabel.snp.makeConstraints { make in
make.left.equalTo(orderNumButton.snp.right).offset(auto(5))
make.centerY.equalTo(orderNumButton)
}
stateLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
stateLabel.snp.makeConstraints { make in
make.right.equalTo(-auto(20))
make.centerY.equalTo(orderNumButton)
make.left.greaterThanOrEqualTo(titleLabel.snp.right).offset(auto(5))
}
line.snp.makeConstraints { make in
make.top.equalTo(orderNumButton.snp.bottom).offset(auto(15))
make.height.equalTo(1)
make.left.right.equalToSuperview().inset(auto(20))
}
contractImageView.snp.makeConstraints { make in
make.left.equalTo(orderNumButton)
make.top.equalTo(line.snp.bottom).offset(auto(5))
make.width.height.equalTo(auto(15))
}
contractTitle.snp.makeConstraints { make in
make.left.equalTo(contractImageView.snp.right).offset(auto(10))
make.centerY.equalTo(contractImageView.snp.centerY)
}
contractContent.snp.makeConstraints { make in
make.left.equalTo(contractTitle.snp.right).offset(auto(10))
make.right.equalToSuperview().offset(-auto(20))
make.centerY.equalTo(contractImageView)
}
incidentIcon.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
incidentIcon.snp.makeConstraints { make in
make.left.equalTo(orderNumButton)
make.top.equalTo(contractImageView.snp.bottom).offset(auto(15))
}
incidentLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
incidentLabel.snp.makeConstraints { make in
make.left.equalTo(incidentIcon.snp.right).offset(auto(20))
make.top.equalTo(incidentIcon)
make.right.equalTo(-auto(20))
make.bottom.greaterThanOrEqualTo(incidentIcon)
}
destIcon.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
destIcon.snp.makeConstraints { make in
make.left.equalTo(orderNumButton)
make.top.equalTo(incidentLabel.snp.bottom).offset(auto(15))
}
destLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
destLabel.snp.makeConstraints { make in
make.left.equalTo(destIcon.snp.right).offset(auto(20))
make.top.equalTo(destIcon)
make.right.equalTo(-auto(20))
make.bottom.greaterThanOrEqualTo(destIcon)
}
remainTimeLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.height.equalTo(auto(20))
make.top.equalTo(destLabel.snp.bottom).offset(auto(10))
}
distanceFromPointLabel.snp.makeConstraints { make in
make.left.equalTo(orderNumButton)
make.centerY.equalTo(remainTimeLabel)
}
distanceLabel.snp.makeConstraints { make in
make.right.equalTo(-auto(20))
make.centerY.equalTo(remainTimeLabel)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateData(taskModel: VehicleMonitorListDataModel.TaskModel) {
orderNumButton.setTitle(taskModel.orderCode, for: .normal)
titleLabel.text = taskModel.serviceName
stateLabel.text = taskModel.taskStatusString
incidentLabel.text = taskModel.vehiclePointAddress
destLabel.text = taskModel.destinationAddress
RQ.vehicleMonitorInfo(parameters: VehicleMonitorInfoParameters(vehicleId: taskModel.taskVehicleId,lon: taskModel.lon,lat: taskModel.lat,code: taskModel.orderCode))
.observe(on: MainScheduler.instance)
.subscribe(onSuccess: {[weak self] response in
guard let self = self else { return }
if let contractName = response?.data?.contractName {
var contractContent = contractName
if let organizeName = response?.data?.organizeName {
contractContent = contractContent + "/" + organizeName
}
self.contractContent.text = contractContent
self.contractTitle.text = "合同:"
self.contractImageView.image = UIImage(named: "vehichleMonitoring_contract_16")
}else{
self.contractContent.text = nil
self.contractTitle.text = nil
self.contractImageView.image = nil
}
var point : String? = nil
var leftTime : Int? = nil
if let leftTimeB = response?.data?.leftTimeB,leftTimeB > 0 {
point = "B"
leftTime = Int(leftTimeB)
}else if let leftTimeC = response?.data?.leftTimeC,leftTimeC > 0 {
point = "C"
leftTime = Int(leftTimeC)
}
if let point, let distance = response?.data?.distance {
let distanceFromPointAttributeString = NSMutableAttributedString(string: "距离\(point)点: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)])
distanceFromPointAttributeString.append(NSMutableAttributedString(string: "\(distance)", attributes: [.foregroundColor : UIColor.hex("F93D3D"),.font : UIFont.regularFont(12)]))
distanceFromPointAttributeString.append(NSMutableAttributedString(string: "km", attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]))
self.distanceFromPointLabel.attributedText = distanceFromPointAttributeString
}
let leftTimeAttributeString = NSMutableAttributedString(string: "剩余时间: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)])
if let _ = point, let leftTime {
leftTimeAttributeString.append(NSMutableAttributedString(string: "\(leftTime)", attributes: [.foregroundColor : UIColor.hex("F93D3D"),.font : UIFont.regularFont(12)]))
leftTimeAttributeString.append(NSMutableAttributedString(string: "", attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]))
self.remainTimeLabel.attributedText = leftTimeAttributeString
}
let bcAttributeString = NSMutableAttributedString(string: "BC: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)])
if let mileageBc = response?.data?.mileageBc {
bcAttributeString.append(NSMutableAttributedString(string: "\(mileageBc)", attributes: [.foregroundColor : UIColor.hex("F93D3D"),.font : UIFont.regularFont(12)]))
bcAttributeString.append(NSMutableAttributedString(string: "km", attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]))
self.distanceLabel.attributedText = bcAttributeString
}
})
.disposed(by: disposeBag)
}
func listView() -> UIView! {
return self
}
}