diff --git a/OrderScheduling.xcodeproj/project.pbxproj b/OrderScheduling.xcodeproj/project.pbxproj index dd7916e..a40b794 100644 --- a/OrderScheduling.xcodeproj/project.pbxproj +++ b/OrderScheduling.xcodeproj/project.pbxproj @@ -67,6 +67,7 @@ 795B949B2BECDB56008F3205 /* NewTraining.swift in Sources */ = {isa = PBXBuildFile; fileRef = 795B949A2BECDB56008F3205 /* NewTraining.swift */; }; 797484782DA67515003EEB47 /* NewTraningViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 797484772DA67515003EEB47 /* NewTraningViewModel.swift */; }; 79B966382AB0651C00308A8D /* VehicleLogoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B966372AB0651C00308A8D /* VehicleLogoutView.swift */; }; + 79BF24412E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79BF24402E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift */; }; 79CB07CC2AA8465A00154B61 /* UserPermission.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CB07CB2AA8465A00154B61 /* UserPermission.swift */; }; 79CECC122A89BD1A00B95D8B /* MessageCenterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC112A89BD1A00B95D8B /* MessageCenterController.swift */; }; 79CECC192A89EE6A00B95D8B /* ReviewFailedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC182A89EE6A00B95D8B /* ReviewFailedController.swift */; }; @@ -204,6 +205,7 @@ 795B949A2BECDB56008F3205 /* NewTraining.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTraining.swift; sourceTree = ""; }; 797484772DA67515003EEB47 /* NewTraningViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTraningViewModel.swift; sourceTree = ""; }; 79B966372AB0651C00308A8D /* VehicleLogoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleLogoutView.swift; sourceTree = ""; }; + 79BF24402E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnlineVehiclesEntryView.swift; sourceTree = ""; }; 79CB07CB2AA8465A00154B61 /* UserPermission.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPermission.swift; sourceTree = ""; }; 79CECC112A89BD1A00B95D8B /* MessageCenterController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageCenterController.swift; sourceTree = ""; }; 79CECC182A89EE6A00B95D8B /* ReviewFailedController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewFailedController.swift; sourceTree = ""; }; @@ -324,6 +326,7 @@ 79FB75EF2A98A26C00DB00A4 /* AcceptOrderTool.swift */, 792EE0942AA74E0A00A212AB /* PushNotiCommonView.swift */, 792EE0962AA74E5800A212AB /* PushNotiCommonTool.swift */, + 79BF24402E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift */, ); path = View; sourceTree = ""; @@ -1160,6 +1163,7 @@ 79FB76152A9DEE7400DB00A4 /* RefuseOrderConfirmView.swift in Sources */, 79FB76262A9F0A0000DB00A4 /* BackgroundTask.swift in Sources */, 79DD0DB12A94B3DB00768FE7 /* EmptyView.swift in Sources */, + 79BF24412E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift in Sources */, 79DD0DAA2A9481BC00768FE7 /* NotificationAuthTool.swift in Sources */, 794FBB1C2A8F4DE900D57BB8 /* MessageView.swift in Sources */, 794FBB142A8F045F00D57BB8 /* MineController.swift in Sources */, diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/Contents.json b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/Contents.json new file mode 100644 index 0000000..b88d812 --- /dev/null +++ b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "online_entry_pin.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "online_entry_pin@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "online_entry_pin@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin.png new file mode 100644 index 0000000..107be39 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@2x.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@2x.png new file mode 100644 index 0000000..c88d6fc Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@2x.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@3x.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@3x.png new file mode 100644 index 0000000..dabf011 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_background.imageset/online_entry_pin@3x.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/Contents.json b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/Contents.json new file mode 100644 index 0000000..55e15eb --- /dev/null +++ b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "online_entry_background.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "online_entry_background@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "online_entry_background@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background.png new file mode 100644 index 0000000..f9b64c2 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@2x.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@2x.png new file mode 100644 index 0000000..d38fab2 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@2x.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@3x.png b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@3x.png new file mode 100644 index 0000000..ea83756 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/online_entry_pin.imageset/online_entry_background@3x.png differ diff --git a/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/Contents.json b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/Contents.json new file mode 100644 index 0000000..821aa1e --- /dev/null +++ b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "vehichleMonitoring_contract_16.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "vehichleMonitoring_contract_16@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "vehichleMonitoring_contract_16@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16.png b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16.png new file mode 100644 index 0000000..88b95b8 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16.png differ diff --git a/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@2x.png b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@2x.png new file mode 100644 index 0000000..48a2f3d Binary files /dev/null and b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@2x.png differ diff --git a/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@3x.png b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@3x.png new file mode 100644 index 0000000..1c34049 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/VehicleMonitoring/vehichleMonitoring_contract_16.imageset/vehichleMonitoring_contract_16@3x.png differ diff --git a/OrderScheduling/Entry/Entry.swift b/OrderScheduling/Entry/Entry.swift index 2a766a3..1b9f3b7 100644 --- a/OrderScheduling/Entry/Entry.swift +++ b/OrderScheduling/Entry/Entry.swift @@ -14,7 +14,7 @@ public let ENTRY = Entry.default open class Entry { public static let `default` = Entry() - func showLoginNoticeEntry(view:UIView,name:String? = nil) { + func showOnlineVehiclesEntry(view:UIView,name:String? = nil) { var attributes = EKAttributes() attributes = .centerFloat attributes.name = name @@ -22,7 +22,7 @@ open class Entry { attributes.displayMode = .inferred attributes.displayDuration = .infinity attributes.screenBackground = .color(color: .clear) - attributes.entryBackground = .color(color: .white) + attributes.entryBackground = .color(color: .clear) attributes.screenInteraction = .absorbTouches attributes.entryInteraction = .absorbTouches attributes.scroll = .disabled @@ -48,8 +48,8 @@ open class Entry { ) ) attributes.positionConstraints.size = .init( - width: .constant(value: auto(280)), - height: .constant(value: auto(130)) + width: .fill, + height: .fill ) attributes.positionConstraints.verticalOffset = 0 attributes.positionConstraints.safeArea = .overridden diff --git a/OrderScheduling/Global/Tool/Tool.swift b/OrderScheduling/Global/Tool/Tool.swift index cbfce02..207fbfb 100644 --- a/OrderScheduling/Global/Tool/Tool.swift +++ b/OrderScheduling/Global/Tool/Tool.swift @@ -132,6 +132,10 @@ open class Tool { } } + func playVoiceWith(broadcast: String) { + DDSS.play(text: broadcast, name: "broadcast") + } + func stopVoice() { DDAS.stopSound(name: "sound") DDSS.stop(name: "broadcast") diff --git a/OrderScheduling/HttpRequestCenter/ApiList.swift b/OrderScheduling/HttpRequestCenter/ApiList.swift index 33718d0..33c0bf9 100644 --- a/OrderScheduling/HttpRequestCenter/ApiList.swift +++ b/OrderScheduling/HttpRequestCenter/ApiList.swift @@ -81,4 +81,8 @@ open class ApiList { public let getAppeal = "/supplierAppV2/dispatchApp/order/getAppeal" public let saveAppeal = "/driverApp/task/saveAppeal" + + public let onlineReminder = "/supplierAppV2/dispatchApp/alarm/onlineReminder" + + public let onlineReminderRead = "/supplierAppV2/dispatchApp/alarm/onlineReminderRead" } diff --git a/OrderScheduling/HttpRequestCenter/ParametersList.swift b/OrderScheduling/HttpRequestCenter/ParametersList.swift index 5777a3c..b02a631 100644 --- a/OrderScheduling/HttpRequestCenter/ParametersList.swift +++ b/OrderScheduling/HttpRequestCenter/ParametersList.swift @@ -267,3 +267,11 @@ public struct SaveAppealParameters : Encodable { var vehicleId : Int? var msg : String? } + +public struct OnlineReminderParameters : Encodable { + var supplierId : Int? +} + +public struct OnlineReminderReadParameters : Encodable { + var id : Int? +} diff --git a/OrderScheduling/HttpRequestCenter/RequestList.swift b/OrderScheduling/HttpRequestCenter/RequestList.swift index 629de67..671a51b 100644 --- a/OrderScheduling/HttpRequestCenter/RequestList.swift +++ b/OrderScheduling/HttpRequestCenter/RequestList.swift @@ -168,4 +168,12 @@ open class RequestList { func saveAppeal(parameters:P) -> Single?> { return DDAF.get(urlString: HOST+API.saveAppeal,parameters: parameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) } + + func onlineReminder(parameters:P) -> Single?> { + return DDAF.get(urlString: HOST+API.onlineReminder,parameters: parameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) + } + + func onlineReminderRead(parameters:P) -> Single?> { + return DDAF.get(urlString: HOST+API.onlineReminderRead,parameters: parameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) + } } diff --git a/OrderScheduling/HttpResponseModel/ResponseModel.swift b/OrderScheduling/HttpResponseModel/ResponseModel.swift index a437e4c..377aff3 100644 --- a/OrderScheduling/HttpResponseModel/ResponseModel.swift +++ b/OrderScheduling/HttpResponseModel/ResponseModel.swift @@ -185,6 +185,9 @@ public class VehicleMonitorListDataModel : Decodable { var alarmType : AlarmType? var rosterStartTime : String? var rosterEndTime : String? + var rosterType : String? + var endTime : String? + var startTime : String? var lat : String? var lon : String? var orderCode : String? @@ -229,7 +232,11 @@ public class VehicleMonitorListDataModel : Decodable { var destinationLongitude : Double? var destinationLatitude : Double? var destinationAddress : String? - } + var leftTimeB : Double? + var leftTimeC : Double? + var distance : Double? + var mileageBc : Double? + var contractName : String? } } public class OrderPhotoListDataModel : Decodable { diff --git a/OrderScheduling/Rescue/View/AcceptOrderTool.swift b/OrderScheduling/Rescue/View/AcceptOrderTool.swift index c95284f..4a41440 100644 --- a/OrderScheduling/Rescue/View/AcceptOrderTool.swift +++ b/OrderScheduling/Rescue/View/AcceptOrderTool.swift @@ -20,6 +20,7 @@ open class AcceptOrderTool : NSObject { acceptOrderView.titleLabel.text = "新订单" acceptOrderView.contentLabel.text = TOOL.getOrderString(userInfo: userInfo) acceptOrderView.readButton.setTitle("查看", for: .normal) + acceptOrderView.cancelButton.setTitle("稍后查看", for: .normal) acceptOrderView.readButton.rx.tap .observe(on: MainScheduler.instance) .subscribe(onNext: { diff --git a/OrderScheduling/Rescue/View/AcceptOrderView.swift b/OrderScheduling/Rescue/View/AcceptOrderView.swift index 22eae91..2a1e40f 100644 --- a/OrderScheduling/Rescue/View/AcceptOrderView.swift +++ b/OrderScheduling/Rescue/View/AcceptOrderView.swift @@ -18,9 +18,8 @@ open class AcceptOrderView : DDView { public let contentLabel : DDLabel public let horizontalLine : DDView public let verticalLine : DDView - public let refuseButton : DDButton - public let acceptButton : DDButton public let readButton : DDButton + public let cancelButton : DDButton public override init(frame: CGRect) { radiusView = DDView.init() scrollView = DDScrollView() @@ -29,9 +28,8 @@ open class AcceptOrderView : DDView { contentLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(14)), textColor: .hex("203053")) horizontalLine = DDView() verticalLine = DDView() - refuseButton = DDButton.dd_initCustom() - acceptButton = DDButton.dd_initCustom() readButton = DDButton.dd_initCustom() + cancelButton = DDButton.dd_initCustom() super.init(frame: frame) radiusView.layer.cornerRadius = auto(10) radiusView.layer.masksToBounds = true @@ -47,20 +45,14 @@ open class AcceptOrderView : DDView { verticalLine.backgroundColor = .hex("979797").alpha(0.35) verticalLine.isHidden = true radiusView.addSubview(verticalLine) - refuseButton.isHidden = true - refuseButton.titleLabel?.font = .mediumFont(auto(14)) - refuseButton.backgroundColor = .white - refuseButton.setTitleColor(.black.alpha(0.3), for: .normal) - radiusView.addSubview(refuseButton) - acceptButton.titleLabel?.font = .mediumFont(auto(14)) - acceptButton.backgroundColor = .white - acceptButton.setTitleColor(.black.alpha(0.3), for: .normal) - acceptButton.isHidden = true - radiusView.addSubview(acceptButton) readButton.titleLabel?.font = .mediumFont(auto(14)) readButton.backgroundColor = .white readButton.setTitleColor(.hex("1D64D2"), for: .normal) radiusView.addSubview(readButton) + cancelButton.titleLabel?.font = .mediumFont(auto(14)) + cancelButton.backgroundColor = .white + cancelButton.setTitleColor(.hex("1D64D2"), for: .normal) + cancelButton.addSubview(cancelButton) radiusView.snp.makeConstraints { make in make.edges.equalToSuperview() @@ -103,23 +95,18 @@ open class AcceptOrderView : DDView { make.width.equalTo(1) } - refuseButton.snp.makeConstraints { make in - make.bottom.equalToSuperview() - make.left.equalToSuperview() - make.top.equalTo(horizontalLine.snp.bottom) - make.right.equalTo(verticalLine.snp.left) - } - - acceptButton.snp.makeConstraints { make in + readButton.snp.makeConstraints { make in make.bottom.equalToSuperview() make.right.equalToSuperview() make.top.equalTo(horizontalLine.snp.bottom) make.left.equalTo(verticalLine.snp.right) } - readButton.snp.makeConstraints { make in + cancelButton.snp.makeConstraints { make in + make.bottom.equalToSuperview() + make.left.equalToSuperview() make.top.equalTo(horizontalLine.snp.bottom) - make.left.right.bottom.equalToSuperview() + make.right.equalTo(verticalLine.snp.left) } } diff --git a/OrderScheduling/Rescue/View/OnlineVehiclesEntryView.swift b/OrderScheduling/Rescue/View/OnlineVehiclesEntryView.swift new file mode 100644 index 0000000..46a6172 --- /dev/null +++ b/OrderScheduling/Rescue/View/OnlineVehiclesEntryView.swift @@ -0,0 +1,129 @@ +// +// OnlineVehiclesEntryView.swift +// OrderScheduling +// +// Created by 中道 on 2025/10/13. +// + +import UIKit +import SnapKit + +/// 弹窗:实时车辆在线情况 +final class OnlineVehiclesEntryView: UIView { + + // MARK: - Public + /// 点击“已知晓”回调 + var onConfirm: (() -> Void)? + + // MARK: - UI + private let pinImageView: UIImageView = { + let iv = UIImageView(image: UIImage(named: "online_entry_pin")) + iv.contentMode = .scaleAspectFit + return iv + }() + + private let backgroundImageView: UIImageView = { + let iv = UIImageView(image: UIImage(named: "online_entry_background")) + iv.contentMode = .scaleAspectFit + return iv + }() + + private let cardView: UIView = { + let v = UIView() + v.backgroundColor = .white + v.layer.cornerRadius = 16 + v.layer.shadowColor = UIColor.black.cgColor + v.layer.shadowOpacity = 0.12 + v.layer.shadowRadius = 10 + v.layer.shadowOffset = CGSize(width: 0, height: 6) + return v + }() + + private let titleLabel: UILabel = { + let l = UILabel() + l.text = "实时车辆在线情况" + l.textAlignment = .center + l.font = .boldSystemFont(ofSize: 16) + l.textColor = UIColor(hex: "#040404") + return l + }() + + /// 富文本正文 + private let contentLabel: UILabel = { + let l = UILabel() + l.numberOfLines = 0 + l.textAlignment = .left + l.textColor = UIColor(hex: "#4C5361") + l.font = .dd_systemFont(ofSize: 14, weight: .medium) + return l + }() + + private let confirmButton: UIButton = { + let b = UIButton(type: .system) + b.setTitle("已知晓", for: .normal) + b.setTitleColor(.white, for: .normal) + b.titleLabel?.font = .boldSystemFont(ofSize: 16) + b.backgroundColor = UIColor(hex: "#3174CE") + b.layer.cornerRadius = 24 + b.layer.masksToBounds = true + return b + }() + + // MARK: - Init + override init(frame: CGRect) { + super.init(frame: frame) + buildUI() + } + required init?(coder: NSCoder) { + super.init(coder: coder) + buildUI() + } + + convenience init(content: String?) { + self.init(frame: .zero) + contentLabel.text = content + } + + func buildUI() { + backgroundColor = .clear + + addSubview(cardView) + cardView.addSubview(backgroundImageView) + cardView.addSubview(pinImageView) + cardView.addSubview(titleLabel) + cardView.addSubview(contentLabel) + cardView.addSubview(confirmButton) + + cardView.snp.makeConstraints { make in + make.centerY.centerX.equalToSuperview() + make.left.right.equalToSuperview().inset(30) + } + + backgroundImageView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + } + + pinImageView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.centerY.equalTo(cardView.snp.top) + make.size.equalTo(CGSize(width: 88, height: 88)) + } + + titleLabel.snp.makeConstraints { make in + make.top.equalTo(pinImageView.snp.bottom).offset(20) + make.left.right.equalTo(cardView).inset(20) + } + + contentLabel.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(12) + make.left.right.equalTo(titleLabel) + } + + confirmButton.snp.makeConstraints { make in + make.top.equalTo(contentLabel.snp.bottom).offset(18) + make.left.right.equalTo(titleLabel) + make.height.equalTo(48) + make.bottom.equalTo(cardView.snp.bottom).inset(20) + } + } +} diff --git a/OrderScheduling/Rescue/ViewController/RescueController.swift b/OrderScheduling/Rescue/ViewController/RescueController.swift index bfe17f2..744d83c 100644 --- a/OrderScheduling/Rescue/ViewController/RescueController.swift +++ b/OrderScheduling/Rescue/ViewController/RescueController.swift @@ -86,9 +86,7 @@ extension RescueController { USER.refreshTokenSub .subscribe(onNext: {[weak self] _ in - NewTraining.default.newTrainingRelay.accept(nil) - self?.appBannerRelay.accept(nil) - self?.appPushRecordRelay.accept(nil) + self?.excuseRelay() }) .disposed(by: disposeBag) @@ -138,19 +136,55 @@ extension RescueController { }) .disposed(by: disposeBag) + onlineReminderRelay + .flatMapLatest { _ in + return RQ.onlineReminder(parameters: OnlineReminderParameters(supplierId: UserData.default.supplierId)) + } + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] response in + guard let self = self else { return } + + if response?.success == true, let data = response?.data, let content = data.content { + let entryView = OnlineVehiclesEntryView(content: content) + entryView.onConfirm = { [weak self] in + guard let self = self else { return } + RQ.onlineReminderRead(parameters: OnlineReminderReadParameters(id: response?.data?.id)) + .observe(on: MainScheduler.instance) + .subscribe(onSuccess: {[weak self] readResponse in + guard let self = self else { return } + if readResponse?.success == true { + Entry.default.dismiss(name: "onlineVehiclesEntryView") + } else { + self.view.dd_makeToast(readResponse?.msg) + } + }) + .disposed(by: self.disposeBag) + } + Entry.default.showOnlineVehiclesEntry(view: entryView, name: "onlineVehiclesEntryView") + Tool.default.playVoiceWith(broadcast: content) + } else { + self.view.dd_makeToast(response?.msg) + } + }) + .disposed(by: disposeBag) + // 点击tabBar 需要刷下下列 preRefreshRelay .observe(on: MainScheduler.instance) .subscribe(onNext: {[weak self] _ in - NewTraining.default.newTrainingRelay.accept(nil) - self?.appBannerRelay.accept(nil) - self?.appPushRecordRelay.accept(nil) + self?.excuseRelay() MCOUNT.newestMessage() self?.categoryView.reloadData() }) .disposed(by: disposeBag) } + func excuseRelay() { + NewTraining.default.newTrainingRelay.accept(nil) + appBannerRelay.accept(nil) + appPushRecordRelay.accept(nil) + onlineReminderRelay.accept(nil) + } } extension RescueController : TYCyclePagerViewDataSource, TYCyclePagerViewDelegate { @@ -604,7 +638,7 @@ extension RescuePendingOrderController : UITableViewDelegate,UITableViewDataSour cell?.acceptButton.setTitle("接单", for: .normal) cell?.refuseButton.setTitle("拒单", for: .normal) } -// +// let model = resultArr[indexPath.row] cell?.typeLabel.text = model.taskServiceName cell?.orderNumLabel.text = model.orderCode @@ -1182,6 +1216,8 @@ class RescueController : ZDViewController { private var appBannerRelay = ReplayRelay.create(bufferSize: 1) private var bannerDataSources : [ConfigByCodeDataModel.ConfigByCodeBannerModel] = [] + private var onlineReminderRelay = ReplayRelay.create(bufferSize: 1) + override func viewDidLoad() { super.viewDidLoad() dd_navigationBarBackgroundColor = .hex("354683") diff --git a/OrderScheduling/ReviewFailed/ViewController/AdditionalPhotoController.swift b/OrderScheduling/ReviewFailed/ViewController/AdditionalPhotoController.swift index 3409ec3..3116c9f 100644 --- a/OrderScheduling/ReviewFailed/ViewController/AdditionalPhotoController.swift +++ b/OrderScheduling/ReviewFailed/ViewController/AdditionalPhotoController.swift @@ -12,6 +12,8 @@ import RxSwift import ZLPhotoBrowser import RxCocoa import RxRelay +import SnapKit +import DDUtilsSwiftKit_Private extension AdditionalPhotoController{ func addActions() { @@ -79,6 +81,55 @@ extension AdditionalPhotoController{ } }) .disposed(by: disposeBag) + + // 保存至相册(带 HUD,批量保存,统一结果反馈) + additionalPhotoView.actionView.save.rx.tap + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] in + guard let self = self else { return } + let images = self.collectSelectedImages() + guard !images.isEmpty else { self.view.dd_makeToast("请先选择照片"); return } + + // 显示 HUD + let hud = ZLProgressHUD.show() + + let group = DispatchGroup() + var successCount = 0 + + images.forEach { img in + group.enter() + ZLPhotoManager.saveImageToAlbum(image: img) { isSuccess, _ in + if isSuccess { successCount += 1 } + group.leave() + } + } + + group.notify(queue: .main) { + hud.hide() + if successCount == images.count { + self.view.dd_makeToast("已保存到相册") + } else if successCount == 0 { + // 全部失败:统一弹窗(沿用库内风格的 alert 方法) + self.presentSaveErrorAlert() + } else { + self.view.dd_makeToast("已保存 \(successCount)/\(images.count) 张") + } + } + }) + .disposed(by: disposeBag) + + // 分享 + additionalPhotoView.actionView.share.rx.tap + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] in + guard let self = self else { return } + let images = self.collectSelectedImages() + guard !images.isEmpty else { self.view.dd_makeToast("请先选择照片"); return } + let activity = UIActivityViewController(activityItems: images, applicationActivities: nil) + activity.modalPresentationStyle = .formSheet + self.present(activity, animated: true) + }) + .disposed(by: disposeBag) } } @@ -127,6 +178,33 @@ extension AdditionalPhotoController : UICollectionViewDelegate, UICollectionView }) .disposed(by: cell!.disposeBag) cell?.takePhotoButton.isHidden = !canModify + + // 选择模式 UI(无图片时不显示选择按钮) + let hasImage = (itemModel.photoUrl != nil) || ((cell?.uploadImageView.image) != nil) + cell?.selectButton.isHidden = !isSelecting || !hasImage + let isChecked = selectedIndexPaths.contains(indexPath) + cell?.selectButton.isSelected = isChecked + cell?.selectButton.setTitleColor(isChecked ? .white : UIColor.hex("#206FFF"), for: .normal) + + cell?.selectButton.rx.tap + .observe(on: MainScheduler.instance) + .subscribe(onNext: { [weak self] in + guard let self = self else { return } + // 若当前无图片,忽略点击 + guard let c = collectionView.cellForItem(at: indexPath) as? AdditionalPhotoCell, c.uploadImageView.isHidden == false else { return } + if self.selectedIndexPaths.contains(indexPath) { + self.selectedIndexPaths.remove(indexPath) + } else { + self.selectedIndexPaths.insert(indexPath) + } + if let c = collectionView.cellForItem(at: indexPath) as? AdditionalPhotoCell { + let checked = self.selectedIndexPaths.contains(indexPath) + c.selectButton.isSelected = checked + c.selectButton.setTitleColor(checked ? .white : UIColor.hex("#206FFF"), for: .normal) + } + self.updateActionViewVisibility(animated: true) + }) + .disposed(by: cell!.disposeBag) return cell! } @@ -138,6 +216,26 @@ extension AdditionalPhotoController : UICollectionViewDelegate, UICollectionView } public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if isSelecting { + // 无图片的条目不允许选中 + if let c = collectionView.cellForItem(at: indexPath) as? AdditionalPhotoCell, c.uploadImageView.isHidden { + return + } + if selectedIndexPaths.contains(indexPath) { + selectedIndexPaths.remove(indexPath) + } else { + selectedIndexPaths.insert(indexPath) + } + if let c = collectionView.cellForItem(at: indexPath) as? AdditionalPhotoCell { + let checked = selectedIndexPaths.contains(indexPath) + c.selectButton.isSelected = checked + c.selectButton.setTitleColor(checked ? .white : UIColor.hex("#206FFF"), for: .normal) + } + updateActionViewVisibility(animated: true) + return + } + + // 非选择模式:沿用原预览逻辑 let cell = self.collectionView(collectionView, cellForItemAt: indexPath) as? AdditionalPhotoCell if let image = cell?.uploadImageView.image { let vc = ZLImagePreviewController.init(datas: [image as Any],showSelectBtn: false,showBottomView: false) @@ -158,6 +256,9 @@ open class AdditionalPhotoController : ZDViewController { private let taskOrderId : Int private let canModify : Bool private var resultArr : [OrderPhotoListDataModel] = [] + private var isSelecting = false + private var selectedIndexPaths = Set() + private var selectButton: UIButton? public init(userOrderId: Int, orderCode: String, taskOrderId: Int, canModify:Bool){ self.userOrderId = userOrderId self.orderCode = orderCode @@ -179,6 +280,14 @@ open class AdditionalPhotoController : ZDViewController { addSubviews() addActions() + let selectButton = UIButton(type: .system) + selectButton.setTitle("选择", for: .normal) + selectButton.setTitleColor(.white.alpha(0.7), for: .normal) + selectButton.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium) + selectButton.addTarget(self, action: #selector(toggleSelectMode), for: .touchUpInside) + let barButton = UIBarButtonItem(customView: selectButton) + navigationItem.rightBarButtonItem = barButton + self.selectButton = selectButton } func addSubviews() { @@ -194,11 +303,80 @@ open class AdditionalPhotoController : ZDViewController { additionalPhotoView.collectionView.delegate = self additionalPhotoView.collectionView.dataSource = self } + + @objc private func toggleSelectMode() { + if isSelecting { cancelSelectMode() } else { enterSelectMode() } + } + private func enterSelectMode() { + isSelecting = true + selectedIndexPaths.removeAll() + selectButton?.setTitle("取消", for: .normal) + updateActionViewVisibility(animated: true) + additionalPhotoView.collectionView.reloadData() + } + private func cancelSelectMode() { + isSelecting = false + selectedIndexPaths.removeAll() + selectButton?.setTitle("选择", for: .normal) + updateActionViewVisibility(animated: true) + additionalPhotoView.collectionView.reloadData() + } + private func updateActionViewVisibility(animated: Bool) { + let shouldShow = isSelecting && !selectedIndexPaths.isEmpty + let targetHeight: CGFloat = shouldShow ? 50 : 0 + additionalPhotoView.actionView.isHidden = (targetHeight == 0) + additionalPhotoView.actionHeightConstraint?.update(offset: targetHeight) + if isSelecting { + if !selectedIndexPaths.isEmpty { + selectButton?.setTitle("取消", for: .normal) + } else { + selectButton?.setTitle("取消", for: .normal) + } + } else { + selectButton?.setTitle("选择", for: .normal) + } + if animated { + UIView.animate(withDuration: 0.25) { self.view.layoutIfNeeded() } + } else { + self.view.layoutIfNeeded() + } + } + private func collectSelectedImages() -> [UIImage] { + var images: [UIImage] = [] + for indexPath in selectedIndexPaths { + let sectionModel = resultArr[indexPath.section] + let itemModel = sectionModel.photoList[indexPath.item] + if let cell = additionalPhotoView.collectionView.cellForItem(at: indexPath) as? AdditionalPhotoCell, + let img = cell.uploadImageView.image { + images.append(img) + } else if let urlString = itemModel.photoUrl, + let url = URL(string: urlString), + let data = try? Data(contentsOf: url), + let img = UIImage(data: data) { + images.append(img) + } + } + return images + } + + private func presentSaveErrorAlert() { + let alert = UIAlertController(title: nil, message: "图片保存失败,请检查相册权限", preferredStyle: .alert) + let cancel = UIAlertAction(title: "取消", style: .cancel, handler: nil) + let confirm = UIAlertAction(title: "确定", style: .default, handler: { _ in + UrlLinks.default.openSetting() + }) + alert.addAction(cancel) + alert.addAction(confirm) + self.present(alert, animated: true) + } } open class AdditionalPhotoView : DDView { public var collectionView : DDCollectionView + public var actionView : AdditionalPhotoActionView + public var actionHeightConstraint : Constraint? + public override init(frame: CGRect) { let flowLayout = UICollectionViewFlowLayout.init() flowLayout.itemSize = CGSize(width: auto(165), height: auto(100)) @@ -207,13 +385,20 @@ open class AdditionalPhotoView : DDView { flowLayout.minimumLineSpacing = auto(10) flowLayout.sectionInset = UIEdgeInsets(top: auto(10), left: auto(15), bottom: auto(10), right: auto(15)) collectionView = DDCollectionView(frame: .zero, collectionViewLayout: flowLayout) + actionView = AdditionalPhotoActionView() super.init(frame: frame) collectionView.backgroundColor = .white addSubview(collectionView) - collectionView.snp.makeConstraints { make in - make.top.left.right.bottom.equalToSuperview() + make.top.left.right.equalToSuperview() + } + actionView.isHidden = true + addSubview(actionView) + actionView.snp.makeConstraints { make in + make.top.equalTo(collectionView.snp.bottom) + make.left.right.bottom.equalToSuperview() + self.actionHeightConstraint = make.height.equalTo(0).constraint } } @@ -230,6 +415,7 @@ open class AdditionalPhotoCell : DDCollectionViewCell { public let stateLabel : DDLabel public let takePhotoButton : DDButton public let uploadImageView : DDImageView + public let selectButton : DDButton public var disposeBag = DisposeBag() public override init(frame: CGRect) { @@ -240,8 +426,10 @@ open class AdditionalPhotoCell : DDCollectionViewCell { stateLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(12)), textColor: .white) takePhotoButton = DDButton.dd_initCustom() uploadImageView = DDImageView.init() + selectButton = DDButton.dd_initCustom() super.init(frame: .zero) + titleLabel.numberOfLines = 2 addSubview(titleLabel) backgroundImageView.layer.borderColor = UIColor.hex("000000").alpha(0.1).cgColor backgroundImageView.layer.borderWidth = 0.5 @@ -263,8 +451,14 @@ open class AdditionalPhotoCell : DDCollectionViewCell { takePhotoButton.setImage(UIImage(named: "additionalPhotot_takePhoto"), for: .normal) backgroundImageView.addSubview(takePhotoButton) + backgroundImageView.addSubview(selectButton) + selectButton.setImage(UIImage(named: "refuseOrder_reason_unselected"), for: .normal) + selectButton.setImage(UIImage(named: "refuseOrder_reason_selected"), for: .selected) + selectButton.isHidden = true + titleLabel.snp.makeConstraints { make in make.left.equalTo(auto(5)) + make.right.equalTo(-auto(5)) make.top.equalTo(0) } @@ -298,6 +492,10 @@ open class AdditionalPhotoCell : DDCollectionViewCell { make.edges.equalToSuperview() } + selectButton.snp.makeConstraints { make in + make.top.right.equalToSuperview().inset(0) + make.width.height.equalTo(auto(30)) + } } public required init?(coder: NSCoder) { @@ -306,6 +504,8 @@ open class AdditionalPhotoCell : DDCollectionViewCell { open override func prepareForReuse() { super.prepareForReuse() + selectButton.isSelected = false + selectButton.isHidden = true disposeBag = DisposeBag() } } @@ -328,3 +528,56 @@ open class AdditionalPhotoHeaderView : DDCollectionViewCell { fatalError("init(coder:) has not been implemented") } } + +open class AdditionalPhotoActionView : UIView { + public let save : UIButton = UIButton(type: .custom) + public let share : UIButton = UIButton(type: .custom) + private let topSeparator = UIView() + private let middleSeparator = UIView() + override init(frame: CGRect) { + super.init(frame: frame) + buildUI() + } + + required public init?(coder: NSCoder) { + super.init(coder: coder) + buildUI() + } + + func buildUI() { + // Top horizontal separator + topSeparator.backgroundColor = UIColor.hex("E5E6EB") + addSubview(topSeparator) + topSeparator.snp.makeConstraints { make in + make.top.left.right.equalToSuperview() + make.height.equalTo(1.0 / UIScreen.main.scale) + } + + save.setTitle("保存至相册", for: .normal) + save.setTitleColor(.black, for: .normal) + save.titleLabel?.font = .dd_systemFont(ofSize: 16, weight: .medium) + addSubview(save) + share.setTitle("分享", for: .normal) + share.setTitleColor(.black, for: .normal) + share.titleLabel?.font = .dd_systemFont(ofSize: 16, weight: .medium) + addSubview(share) + save.snp.makeConstraints { make in + make.centerX.equalToSuperview().multipliedBy(0.5) + make.centerY.equalToSuperview() + } + share.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.centerX.equalToSuperview().multipliedBy(1.5) + } + + // Middle vertical separator + middleSeparator.backgroundColor = UIColor.hex("E5E6EB") + addSubview(middleSeparator) + middleSeparator.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.centerY.equalToSuperview() + make.width.equalTo(1.0 / UIScreen.main.scale) + make.height.equalTo(24) + } + } +} diff --git a/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift b/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift index 3c605a5..6333ce4 100644 --- a/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift +++ b/OrderScheduling/VehicleMonitoring/ViewController/VehicleMonitoringController.swift @@ -18,8 +18,8 @@ import DDUIGestureRecognizer import DDUtilsSwiftKit_Private fileprivate let vehicleMonitoringPannelViewHeight = auto(300) -fileprivate let vehicleMonitoringPannelCategoryView = auto(40) -fileprivate let vehicleMonitoringListDetailViewHeight = auto(190) +fileprivate let vehicleMonitoringPannelCategoryViewHeight = auto(40) +fileprivate let vehicleMonitoringListDetailViewHeight = auto(270) fileprivate let vehicleMonitoringPointAnnotationW = auto(120) fileprivate let vehicleMonitoringPointAnnotationNameLeftInset = auto(35) @@ -768,8 +768,39 @@ extension VehicleMonitoringController { /// 视频按钮显示规则 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 } /// 当为max时收回pannelView @@ -959,7 +990,7 @@ open class VehicleMonitoringController : ZDViewController { vehicleMonitoringView.vehicleMonitoringPannelView.categoryView.snp.remakeConstraints { make in make.top.equalToSuperview().priority(.high) make.left.right.equalToSuperview() - make.height.equalTo(vehicleMonitoringPannelCategoryView) + make.height.equalTo(vehicleMonitoringPannelCategoryViewHeight) } vehicleMonitoringListDetailView.layer.cornerRadius = vehicleMonitoringPannelViewCornerRadius @@ -971,13 +1002,13 @@ open class VehicleMonitoringController : ZDViewController { make.bottom.equalToSuperview() }) - let minDisplayHeight = vehicleMonitoringPannelCategoryView + 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(-vehicleMonitoringPannelCategoryView + vehicleMonitoringPannelViewCornerRadius) + make.bottom.equalToSuperview().offset(-vehicleMonitoringPannelCategoryViewHeight + vehicleMonitoringPannelViewCornerRadius) } if pannelPanGes.panGesValue.expandLevel == .max { @@ -1355,6 +1386,9 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg 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 @@ -1380,7 +1414,10 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg settingButton.setBackgroundImage(UIImage(named: "vehicleMonitoring_setting"), for: .normal) videoButton = DDButton.dd_initCustom() videoButton.setBackgroundImage(UIImage(named: "vehicleMonitoring_video_icon"), for: .normal) - nameLabel = DDLabel.dd_init(withText: "", font: .regularFont(auto(14)), textColor: .hex("11142F")) + 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() @@ -1404,9 +1441,11 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg 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 @@ -1427,7 +1466,7 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg containerView.snp.makeConstraints { make in make.left.right.equalToSuperview().inset(auto(7)) - make.top.equalTo(backButton.snp.bottom).offset(0) + make.top.equalTo(workScheduleContent.snp.bottom).offset(auto(5)) make.bottom.equalToSuperview().offset(-auto(10)) } @@ -1498,6 +1537,11 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg 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) @@ -1509,6 +1553,17 @@ class VehicleMonitoringListDetailView : DDView, JXCategoryListContainerViewDeleg 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 @@ -1572,6 +1627,12 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { 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 override init(frame: CGRect) { orderNumButton = UIButton() orderNumButton.setTitleColor(.hex("0E76F4"), for: .normal) @@ -1583,6 +1644,12 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { 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(image: UIImage(named: "vehichleMonitoring_contract_16")) + 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() super.init(frame: frame) addSubview(orderNumButton) @@ -1599,6 +1666,14 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { 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)) @@ -1625,10 +1700,27 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { 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(line.snp.bottom).offset(auto(15)) + make.top.equalTo(contractImageView.snp.bottom).offset(auto(15)) } incidentLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) @@ -1652,6 +1744,22 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { 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) { @@ -1663,7 +1771,38 @@ class VMLDContainerView : DDView , JXCategoryListContentViewDelegate { titleLabel.text = taskModel.serviceName stateLabel.text = taskModel.taskStatusString incidentLabel.text = taskModel.vehiclePointAddress - destLabel.text = taskModel.destinationAddress + destLabel.text = (taskModel.destinationAddress ?? "") + (taskModel.destinationAddress ?? "") + contractContent.text = taskModel.contractName + var point = "" + var leftTime : Int? = nil + if let leftTimeB = taskModel.leftTimeB { + point = "B" + leftTime = Int(leftTimeB) + }else if let leftTimeC = taskModel.leftTimeC { + point = "C" + leftTime = Int(leftTimeC) + } + let distanceFromPointAttributeString = NSMutableAttributedString(string: "距离\(point)点: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]) + if let distance = taskModel.distance { + 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)])) + distanceFromPointLabel.attributedText = distanceFromPointAttributeString + } + + let leftTimeAttributeString = NSMutableAttributedString(string: "剩余时间: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]) + if 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)])) + remainTimeLabel.attributedText = leftTimeAttributeString + } + + let bcAttributeString = NSMutableAttributedString(string: "BC: ",attributes: [.foregroundColor : UIColor.hex("11142F"),.font : UIFont.regularFont(12)]) + if let mileageBc = taskModel.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)])) + distanceLabel.attributedText = bcAttributeString + } + } func listView() -> UIView! {