diff --git a/OrderScheduling.xcodeproj/project.pbxproj b/OrderScheduling.xcodeproj/project.pbxproj index f8294b4..0487471 100644 --- a/OrderScheduling.xcodeproj/project.pbxproj +++ b/OrderScheduling.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ 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 */; }; + 79CE24AA2EF52EAF007FCF90 /* IdentityAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CE24A92EF52EAF007FCF90 /* IdentityAlertView.swift */; }; 79CECC122A89BD1A00B95D8B /* MessageCenterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC112A89BD1A00B95D8B /* MessageCenterController.swift */; }; 79CECC192A89EE6A00B95D8B /* ReviewFailedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC182A89EE6A00B95D8B /* ReviewFailedController.swift */; }; 79CECC1B2A89F83800B95D8B /* AdditionalPhotoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79CECC1A2A89F83800B95D8B /* AdditionalPhotoController.swift */; }; @@ -207,6 +208,7 @@ 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 = ""; }; + 79CE24A92EF52EAF007FCF90 /* IdentityAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityAlertView.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 = ""; }; 79CECC1A2A89F83800B95D8B /* AdditionalPhotoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalPhotoController.swift; sourceTree = ""; }; @@ -327,6 +329,7 @@ 792EE0942AA74E0A00A212AB /* PushNotiCommonView.swift */, 792EE0962AA74E5800A212AB /* PushNotiCommonTool.swift */, 79BF24402E9CEFB300FA5F1E /* OnlineVehiclesEntryView.swift */, + 79CE24A92EF52EAF007FCF90 /* IdentityAlertView.swift */, ); path = View; sourceTree = ""; @@ -1202,6 +1205,7 @@ 791887AE2A80F943007EA0C1 /* UserData.swift in Sources */, 79FB75EE2A9898EB00DB00A4 /* AcceptOrderView.swift in Sources */, 791887BA2A82495D007EA0C1 /* EnvironmentStrings.swift in Sources */, + 79CE24AA2EF52EAF007FCF90 /* IdentityAlertView.swift in Sources */, 79D964E02E77FE2100309946 /* AppealInputViewController.swift in Sources */, 791887A62A80D50C007EA0C1 /* ParametersList.swift in Sources */, ); diff --git a/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/Contents.json b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/Contents.json new file mode 100644 index 0000000..873dc6b --- /dev/null +++ b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "mine_info_manage.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "mine_info_manage@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "mine_info_manage@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage.png b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage.png new file mode 100644 index 0000000..6d5ce7f Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage.png differ diff --git a/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@2x.png b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@2x.png new file mode 100644 index 0000000..d62ae5c Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@2x.png differ diff --git a/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@3x.png b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@3x.png new file mode 100644 index 0000000..46e2d3a Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Mine/mine_info_manage.imageset/mine_info_manage@3x.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/Contents.json b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/Contents.json new file mode 100644 index 0000000..78829e3 --- /dev/null +++ b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "IdentityAlertNotice.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "IdentityAlertNotice@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "IdentityAlertNotice@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice.png b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice.png new file mode 100644 index 0000000..9171362 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@2x.png b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@2x.png new file mode 100644 index 0000000..0bfc104 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@2x.png differ diff --git a/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@3x.png b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@3x.png new file mode 100644 index 0000000..43cf801 Binary files /dev/null and b/OrderScheduling/Assets.xcassets/Rescue/IdentityAlertNotice.imageset/IdentityAlertNotice@3x.png differ diff --git a/OrderScheduling/Common/View/AppUpdateTool.swift b/OrderScheduling/Common/View/AppUpdateTool.swift index 8b7371a..af55fe4 100644 --- a/OrderScheduling/Common/View/AppUpdateTool.swift +++ b/OrderScheduling/Common/View/AppUpdateTool.swift @@ -61,7 +61,7 @@ open class AppUpdateTool : NSObject { UIApplication.shared.dd_keyWindow.rootViewController?.view.dd_showHUD() }) .flatMapLatest { (type,_) in - return Observable.zip(RQ.versionCheck(parameters: VersionCheckParameters(version: APPINFO.bundleVersionShort())).asObservable(), Observable.just(type)) + return Observable.zip(RQ.updateVersion(parameters: UpdateVersionParameters(appVersion: APPINFO.bundleVersionShort(), supplierId: UserData.default.supplierId)).asObservable(), Observable.just(type)) } .observe(on: MainScheduler.instance) .do(onNext: { (_,_) in @@ -70,18 +70,23 @@ open class AppUpdateTool : NSObject { .observe(on: MainScheduler.instance) .subscribe(onNext: {[weak self] (response,type) in if response?.success == true { - if self?.canUpdate(localVersion: APPINFO.bundleVersionShort(), onlineVersion: response?.data?.appVersion ?? "0") == true { + + if response?.data == nil { + return + } + + if self?.canUpdate(localVersion: APPINFO.bundleVersionShort(), onlineVersion: response?.data?.newAppVersion ?? "0") == true { if type == .auto { - if response?.data?.update.code == .YES || self?.shouldPresentEntry() == true { + if response?.data?.update == UpdateVersionDataModel.ForceUpdate.force.rawValue || self?.shouldPresentEntry() == true { if let appUpdateView = self?.appUpdateView { - appUpdateView.isForce(isForce: response?.data?.update.code == .YES ? true : false) + appUpdateView.isForce(isForce: (response?.data?.update == UpdateVersionDataModel.ForceUpdate.force.rawValue) ? true : false) appUpdateView.contentLabel.text = response?.data?.description ENTRY.showAppUpdateEntry(view: appUpdateView,name: appUpdateEntry) } } }else if type == .manual { if let appUpdateView = self?.appUpdateView { - appUpdateView.isForce(isForce: response?.data?.update.code == .YES ? true : false) + appUpdateView.isForce(isForce: (response?.data?.update == UpdateVersionDataModel.ForceUpdate.force.rawValue) ? true : false) appUpdateView.contentLabel.text = response?.data?.description ENTRY.showAppUpdateEntry(view: appUpdateView,name: appUpdateEntry) } diff --git a/OrderScheduling/Common/WebView/WebViewTool.swift b/OrderScheduling/Common/WebView/WebViewTool.swift index 819a9e6..8851b97 100644 --- a/OrderScheduling/Common/WebView/WebViewTool.swift +++ b/OrderScheduling/Common/WebView/WebViewTool.swift @@ -21,6 +21,8 @@ open class WebViewTool : NSObject { public var h5Models : DispatchAppH5UrlDataModel? public var bannerInMineDataSources : [ConfigByCodeDataModel.ConfigByCodeBannerModel]? + public var supplierAppIsUserNewReportRelay = ReplayRelay.create(bufferSize: 1) + public var supplierAppIsUserNewReport : Bool = false enum WebViewNameEnum : String { case todoList = "待办事项" @@ -45,6 +47,8 @@ open class WebViewTool : NSObject { case reportIndex = "报备" case vehicleAlarmDetail = "报警详情" case vehicleAlarmList = "车辆报警" + case kpiCaseNew = "服务商案件和车辆情况统计" + case managerPeople = "管理人员" } public override init() { @@ -158,6 +162,12 @@ open class WebViewTool : NSObject { case .vehicleAlarmDetail: vc = WebViewController(showNavBar:true, title: WebViewNameEnum.vehicleAlarmDetail.rawValue, url: "\((h5Models?.vehicleAlarmDetail)!)?token=\((USER.token)!)"+(appending ?? "")) break + case .kpiCaseNew: + vc = WebViewController(showNavBar:true, title: nil, url: "\((h5Models?.kpiCaseNew)!)?token=\((USER.token)!)"+(appending ?? "")) + break + case .managerPeople: + vc = WebViewController(showNavBar:false, title: nil, url: "\((h5Models?.managerPeople)!)?token=\((USER.token)!)"+(appending ?? "")) + break } if let vc { @@ -166,6 +176,14 @@ open class WebViewTool : NSObject { nav?.pushViewController(vc, animated: true) } } + + func openReportIndex(queryType: Int,userOrderId: Int,orderCode: String,type: Int,userOrderCode: String,supplierId: Int) { + if supplierAppIsUserNewReport == true { + open(name: .reportIndex,appending: "&userOrderId=\(userOrderId)&type=\(type)&userOrderCode=\(userOrderCode)&supplierId=\(supplierId)") + }else{ + open(name: .reporting,appending: "&queryType=\(queryType)&userOrderId=\(userOrderId)&orderCode=\(orderCode)") + } + } func open(name:WebViewNameEnum,appending:String?,completionHandler:(() -> Void)? = nil) { requestModelRelay.accept(name) diff --git a/OrderScheduling/Entry/Entry.swift b/OrderScheduling/Entry/Entry.swift index 1b9f3b7..e407f5c 100644 --- a/OrderScheduling/Entry/Entry.swift +++ b/OrderScheduling/Entry/Entry.swift @@ -14,6 +14,60 @@ public let ENTRY = Entry.default open class Entry { public static let `default` = Entry() + func showIdentityAlert(view: UIView, name: String? = nil) { + var attributes = EKAttributes.centerFloat + attributes.name = name + attributes.precedence = .override(priority: .min, dropEnqueuedEntries: false) + attributes.displayMode = .inferred + attributes.displayDuration = .infinity + + // ✅ 背景加半透明遮罩 + attributes.screenBackground = .color( + color: EKColor(UIColor.black.withAlphaComponent(0.45)) + ) + + // entry 自己画内容,所以这里透明 + attributes.entryBackground = .color(color: .clear) + + attributes.screenInteraction = .absorbTouches // 必须点按钮才能关闭 + attributes.entryInteraction = .absorbTouches + attributes.scroll = .disabled + + attributes.entranceAnimation = .init( + translate: .init( + duration: 0.25, + spring: .init(damping: 1, initialVelocity: 0) + ) + ) + attributes.exitAnimation = .init( + translate: .init(duration: 0.25) + ) + attributes.popBehavior = .animated( + animation: .init( + translate: .init(duration: 0.25) + ) + ) + attributes.shadow = .active( + with: .init( + color: .black, + opacity: 0.3, + radius: 6 + ) + ) + + // ✅ 让 entry 本身按内容高度来,而不是铺满全屏 + attributes.positionConstraints.size = .init( + width: .offset(value: 40), // 左右各留 20,自己可调 + height: .intrinsic // 高度跟 view 的布局走 + ) + attributes.positionConstraints.verticalOffset = 0 + attributes.positionConstraints.safeArea = .overridden + attributes.positionConstraints.rotation.isEnabled = false + attributes.statusBar = .light + + SwiftEntryKit.display(entry: view, using: attributes) + } + func showOnlineVehiclesEntry(view:UIView,name:String? = nil) { var attributes = EKAttributes() attributes = .centerFloat diff --git a/OrderScheduling/History/ViewController/HistoryController.swift b/OrderScheduling/History/ViewController/HistoryController.swift index 0d46a2e..a446be2 100644 --- a/OrderScheduling/History/ViewController/HistoryController.swift +++ b/OrderScheduling/History/ViewController/HistoryController.swift @@ -241,10 +241,9 @@ extension HistoryItemController : UITableViewDelegate, UITableViewDataSource { cell?.reportButton.rx.tap .observe(on: MainScheduler.instance) .subscribe(onNext: { _ in -// if let supplierId = USER.supplierId { -// WEBTOOL.open(name: .reportIndex,appending: "&userOrderId=\(model.userOrderId)&type=1&userOrderCode=\(model.taskCode)&supplierId=\(supplierId)") -// } - WEBTOOL.open(name: .reporting, appending: "&queryType=\(OrderTypeEnum.UNCLOSED_ORDER.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)") + if let supplierId = USER.supplierId { + WEBTOOL.openReportIndex(queryType: OrderTypeEnum.UNCLOSED_ORDER.rawValue, userOrderId: model.userOrderId, orderCode: model.orderCode, type: 1, userOrderCode: model.taskCode, supplierId: supplierId) + } }) .disposed(by: cell!.disposeBag) diff --git a/OrderScheduling/HttpRequestCenter/ApiList.swift b/OrderScheduling/HttpRequestCenter/ApiList.swift index 610978d..96d9b9f 100644 --- a/OrderScheduling/HttpRequestCenter/ApiList.swift +++ b/OrderScheduling/HttpRequestCenter/ApiList.swift @@ -48,9 +48,15 @@ open class ApiList { public let generalInfo = "/supplierAppV2/dispatchApp/user/generalInfo" + public let getNeedConfirmPersonInfo = "/supplierAppV2/dispatchApp/wechat/getNeedConfirmPersonInfo" + + public let giveUp = "/supplierAppV2/dispatchApp/wechat/giveUp" + + public let judgeIfNeedConfirm = "/supplierAppV2/dispatchApp/wechat/judgeIfNeedConfirm" + public let dispatchAppH5Urls = "/supplierAppV2/open/dispatchAppH5Urls" - public let versionCheck = "/supplierAppV2/dispatchApp/user/versionCheck" + public let updateVersion = "/supplierAppV2/dispatchApp/user/updateVersion" public let messageReminderList = "/supplierAppV2/dispatchApp/toDoMessage/messageReminderList" diff --git a/OrderScheduling/HttpRequestCenter/ParametersList.swift b/OrderScheduling/HttpRequestCenter/ParametersList.swift index c4edf2e..4f334d7 100644 --- a/OrderScheduling/HttpRequestCenter/ParametersList.swift +++ b/OrderScheduling/HttpRequestCenter/ParametersList.swift @@ -205,9 +205,10 @@ public struct SupplementOrderPhotoParameters : Encodable { var file : Data } -public struct VersionCheckParameters : Encodable { - var version : String - var platForm : Int = 2 +public struct UpdateVersionParameters : Encodable { + var appVersion : String + var supplierId : Int? + var sysType : String = "ios" } public struct MessageReminderListParameters : Encodable { @@ -278,3 +279,15 @@ public struct VehicleMonitorInfoParameters : Encodable { var lat : String? var code : String? } + +public struct NeedConfirmPersonInfoParameters : Encodable { + var supplierId : Int? +} + +public struct JudgeIfNeedConfirmParameters : Encodable { + var supplierId : Int? +} + +public struct GiveUpParameters : Encodable { + var supplierId : Int? +} diff --git a/OrderScheduling/HttpRequestCenter/RequestList.swift b/OrderScheduling/HttpRequestCenter/RequestList.swift index 0481243..57acbdb 100644 --- a/OrderScheduling/HttpRequestCenter/RequestList.swift +++ b/OrderScheduling/HttpRequestCenter/RequestList.swift @@ -99,12 +99,24 @@ open class RequestList { return DDAF.post(urlString: HOST+API.generalInfo,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) } + func getNeedConfirmPersonInfo(prameters:P) -> Single?> { + return DDAF.get(urlString: HOST+API.getNeedConfirmPersonInfo,parameters: prameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel<[NeedConfirmPersonInfoDataModel]>.self) + } + + func judgeIfNeedConfirm(prameters:P) -> Single?> { + return DDAF.get(urlString: HOST+API.judgeIfNeedConfirm,parameters: prameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) + } + + func giveUp(prameters:P) -> Single?> { + return DDAF.get(urlString: HOST+API.giveUp,parameters: prameters,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) + } + func dispatchAppH5Urls() -> Single?> { return DDAF.post(urlString: HOST+API.dispatchAppH5Urls,encoding: URLEncodedFormParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) } - func versionCheck(parameters:P) -> Single?> { - return DDAF.post(urlString: HOST+API.versionCheck,parameters: parameters,encoding: JSONParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) + func updateVersion(parameters:P) -> Single?> { + return DDAF.post(urlString: HOST+API.updateVersion,parameters: parameters,encoding: JSONParameterEncoder.default,headers: [tokenHeader()],responseType: ResponseModel.self) } func messageReminderList(parameters:P) -> Single?> { diff --git a/OrderScheduling/HttpResponseModel/ResponseModel.swift b/OrderScheduling/HttpResponseModel/ResponseModel.swift index 0e07be4..184c229 100644 --- a/OrderScheduling/HttpResponseModel/ResponseModel.swift +++ b/OrderScheduling/HttpResponseModel/ResponseModel.swift @@ -262,6 +262,15 @@ public class GeneralInfoDataModel : Decodable { var addressLon : Double? } +public class NeedConfirmPersonInfoDataModel : Decodable { +} + +public class JudgeIfNeedConfirmDataModel : Decodable { + var needConfirm : Bool? + var count : Int? + var isLast : Bool? +} + public class DispatchAppH5UrlDataModel : Decodable { var todoList : String? var workOrderReconciliation : String @@ -282,28 +291,17 @@ public class DispatchAppH5UrlDataModel : Decodable { var reportIndex : String var vehicleAlarmList : String var vehicleAlarmDetail : String + var kpiCaseNew : String + var managerPeople : String } -public class VersionCheckDataModel : Decodable { - var id : Int - var appVersion : String - var update : UpdateModel - var appType : TypeModel - class UpdateModel : Decodable { - var code : UpdateEnum - var label : String - } - class TypeModel : Decodable { - var code : Int - var label : String - } - enum UpdateEnum : Int,Decodable { - case NO = 0 - case YES = 1 - } - var updateTime : String? - var createTime : String? +public class UpdateVersionDataModel : Decodable { + var newAppVersion : String? + var update : Int? var description : String? + public enum ForceUpdate : Int { + case force = 1 + } } public class MessageReminderListDataModel : Decodable { @@ -372,6 +370,7 @@ public class AppPushRecordListDataModel : Decodable { public class ConfigByCodeDataModel : Decodable { var bannerConfig : [ConfigByCodeBannerModel]? + var supplierAppIsUserNewReport : String? public class ConfigByCodeBannerModel : Decodable { var linkUrl : String? var bannerIcon : String? diff --git a/OrderScheduling/Mine/ViewController/MineController.swift b/OrderScheduling/Mine/ViewController/MineController.swift index cd95479..ac93e77 100644 --- a/OrderScheduling/Mine/ViewController/MineController.swift +++ b/OrderScheduling/Mine/ViewController/MineController.swift @@ -49,14 +49,14 @@ extension MineController { return RQ.thisWeekNumber() }) .flatMapLatest { numberModel in - return Single.zip(RQ.generalInfo(),Single.just(numberModel)) + return Single.zip(RQ.generalInfo(),RQ.getNeedConfirmPersonInfo(prameters: NeedConfirmPersonInfoParameters(supplierId: UserData.default.supplierId)),Single.just(numberModel)) } .observe(on: MainScheduler.instance) - .subscribe(onNext: {[weak self] response,numberModel in + .subscribe(onNext: {[weak self] response,needConfirmPersonInfoModel,numberModel in + self?.mineView.scrollView.mj_header?.endRefreshing() if response?.success == true { - self?.mineView.scrollView.mj_header?.endRefreshing() self?.mineView.carInfoView.descLabel.text = String(response?.data?.vehicleCount ?? 0)+"台" - self?.mineView.driverInfoView.descLabel.text = String(response?.data?.driverCount ?? 0)+"台" + self?.mineView.driverInfoView.descLabel.text = String(response?.data?.driverCount ?? 0)+"人" if let icon = response?.data?.icon { self?.mineView.avatar.sd_setImage(with: URL(string: icon),placeholderImage: UIImage(named: "placeholder_gender_man")) } @@ -68,6 +68,12 @@ extension MineController { self?.view.dd_makeToast(response?.msg) } + if needConfirmPersonInfoModel?.success == true { + self?.mineView.manageView.descLabel.text = String(needConfirmPersonInfoModel?.data?.count ?? 0)+"人" + }else{ + self?.view.dd_makeToast(response?.msg) + } + if numberModel?.success == true { if let number = numberModel?.data, number > 0 { self?.mineView.ershouche.contentView.isHidden = false @@ -81,6 +87,15 @@ extension MineController { }) .disposed(by: disposeBag) + mineView.manageGes.rx.event + .observe(on: MainScheduler.instance) + .subscribe(onNext: { _ in + if let supplierId = UserData.default.supplierId { + WEBTOOL.open(name: .managerPeople, appending: "&supplierId=\(supplierId)") + } + }) + .disposed(by: disposeBag) + mineView.carInfoGes.rx.event .observe(on: MainScheduler.instance) .subscribe(onNext: { _ in @@ -97,6 +112,13 @@ extension MineController { }) .disposed(by: disposeBag) + mineView.fuwushanganjianGes.rx.event + .observe(on: MainScheduler.instance) + .subscribe(onNext: { _ in + WEBTOOL.open(name: .kpiCaseNew, appending: nil) + }) + .disposed(by: disposeBag) + mineView.shujutongjiGes.rx.event .observe(on: MainScheduler.instance) .subscribe(onNext: { _ in @@ -222,12 +244,15 @@ open class MineController : ZDViewController { make.bottom.equalTo(-view.safeAreaInsets.bottom - CGRectGetHeight(tabBarController?.tabBar.frame ?? .zero)) } + mineView.manageView.titleLabel.text = "管理人员" + mineView.manageView.imageView.image = UIImage(named: "mine_info_manage") mineView.carInfoView.titleLabel.text = "车辆管理" mineView.carInfoView.imageView.image = UIImage(named: "mine_info_car") mineView.driverInfoView.titleLabel.text = "司机管理" mineView.driverInfoView.imageView.image = UIImage(named: "mine_info_driver") - mineView.shujutongji.titleLabel.text = "KPI数据统计" + mineView.fuwushanganjian.titleLabel.text = "服务商案件和车辆情况统计" + mineView.shujutongji.titleLabel.text = "服务商KPI" mineView.gongdanduizhang.titleLabel.text = "工单对账" mineView.gongdanpici.titleLabel.text = "工单批次" mineView.kaipiaoxinxi.titleLabel.text = "开票信息" @@ -326,17 +351,22 @@ open class MineView : DDView { private let topBackgroundImageView : DDImageView public let avatar : DDImageView public let companyLabel : DDLabel + public let manageGes : UITapGestureRecognizer + public let manageView : MineInfoView public let carInfoGes : UITapGestureRecognizer public let carInfoView : MineInfoView public let driverInfoGes : UITapGestureRecognizer public let driverInfoView : MineInfoView public let infoRadiusView : DDView + private let infoStackView: UIStackView public let infoRadiusSeparate : DDImageView public let statisticsRadiusView : DDView public let orderRadiusView : DDView public let materialRadiusView : DDView public let usedCarRadiusView : DDView public let settingsRadiusView : DDView + public let fuwushanganjianGes : UITapGestureRecognizer + public let fuwushanganjian : MineCell public let shujutongjiGes : UITapGestureRecognizer public let shujutongji : MineCell public let gongdanduizhangGes : UITapGestureRecognizer @@ -369,17 +399,22 @@ open class MineView : DDView { topBackgroundImageView = DDImageView() avatar = DDImageView(image: UIImage(named: "placeholder_gender_man")) companyLabel = DDLabel.dd_init(withText: "", font: .mediumFont(auto(12)), textColor: .hex("FFFFFF").alpha(0.5)) + manageView = MineInfoView() + manageGes = UITapGestureRecognizer() carInfoView = MineInfoView() carInfoGes = UITapGestureRecognizer() driverInfoView = MineInfoView() driverInfoGes = UITapGestureRecognizer() infoRadiusView = DDView() + infoStackView = UIStackView() infoRadiusSeparate = DDImageView(image: UIImage(named: "mine_info_separate")) statisticsRadiusView = DDView() orderRadiusView = DDView() materialRadiusView = DDView() usedCarRadiusView = DDView() settingsRadiusView = DDView() + fuwushanganjianGes = UITapGestureRecognizer() + fuwushanganjian = MineCell() shujutongjiGes = UITapGestureRecognizer() shujutongji = MineCell() gongdanduizhangGes = UITapGestureRecognizer() @@ -421,10 +456,20 @@ open class MineView : DDView { infoRadiusView.backgroundColor = .hex("FFFFFF") infoRadiusView.layer.cornerRadius = auto(12) scrollContentView.addSubview(infoRadiusView) + + infoStackView.axis = .horizontal + infoStackView.alignment = .fill + infoStackView.distribution = .fillEqually + infoRadiusView.addSubview(infoStackView) + + manageView.addGestureRecognizer(manageGes) carInfoView.addGestureRecognizer(carInfoGes) - infoRadiusView.addSubview(carInfoView) driverInfoView.addGestureRecognizer(driverInfoGes) - infoRadiusView.addSubview(driverInfoView) + + infoStackView.addArrangedSubview(manageView) + infoStackView.addArrangedSubview(carInfoView) + infoStackView.addArrangedSubview(driverInfoView) + scrollContentView.addSubview(infoRadiusSeparate) statisticsRadiusView.backgroundColor = .hex("FFFFFF") statisticsRadiusView.layer.cornerRadius = auto(6) @@ -441,6 +486,8 @@ open class MineView : DDView { settingsRadiusView.backgroundColor = .hex("FFFFFF") settingsRadiusView.layer.cornerRadius = auto(6) scrollContentView.addSubview(settingsRadiusView) + fuwushanganjian.addGestureRecognizer(fuwushanganjianGes) + statisticsRadiusView.addSubview(fuwushanganjian) shujutongji.addGestureRecognizer(shujutongjiGes) shujutongji.line.isHidden = true statisticsRadiusView.addSubview(shujutongji) @@ -518,14 +565,8 @@ open class MineView : DDView { make.width.equalTo(auto(350)) } - carInfoView.snp.makeConstraints { make in - make.left.top.bottom.equalToSuperview() - make.width.equalToSuperview().multipliedBy(0.5) - } - - driverInfoView.snp.makeConstraints { make in - make.right.top.bottom.equalToSuperview() - make.width.equalToSuperview().multipliedBy(0.5) + infoStackView.snp.makeConstraints { make in + make.edges.equalToSuperview() } infoRadiusSeparate.snp.makeConstraints { make in @@ -537,7 +578,6 @@ open class MineView : DDView { make.top.equalTo(infoRadiusView.snp.bottom).offset(auto(10)) make.width.equalTo(infoRadiusView) make.centerX.equalToSuperview() - make.height.equalTo(auto(55)) } orderRadiusView.snp.makeConstraints { make in @@ -567,11 +607,18 @@ open class MineView : DDView { make.height.equalTo(auto(110)) } - shujutongji.snp.makeConstraints { make in + fuwushanganjian.snp.makeConstraints { make in make.left.right.top.equalToSuperview() make.height.equalTo(auto(55)) } + shujutongji.snp.makeConstraints { make in + make.top.equalTo(fuwushanganjian.snp.bottom) + make.left.right.equalToSuperview() + make.height.equalTo(auto(55)) + make.bottom.equalToSuperview() + } + gongdanduizhang.snp.makeConstraints { make in make.left.right.top.equalToSuperview() make.height.equalTo(auto(55)) @@ -729,23 +776,30 @@ public class MineInfoView : DDView { addSubview(descLabel) addSubview(arrow) + imageView.contentMode = .scaleAspectFit imageView.snp.makeConstraints { make in - make.left.top.equalTo(auto(20)) + make.right.equalTo(titleLabel.snp.left).offset(-auto(5)) + make.width.height.equalTo(auto(24)) + make.centerY.equalTo(titleLabel) } - + titleLabel.snp.makeConstraints { make in - make.left.equalTo(imageView.snp.right).offset(auto(10)) - make.top.equalTo(imageView.snp.top).offset(auto(5)) + make.top.equalToSuperview().offset(auto(10)) + make.bottom.equalTo(snp.centerY).offset(-auto(2.5)) + make.centerX.equalToSuperview().offset(auto(8)) } - + descLabel.snp.makeConstraints { make in make.left.equalTo(titleLabel) - make.top.equalTo(titleLabel.snp.bottom).offset(auto(5)) + make.top.equalTo(snp.centerY).offset(auto(2.5)) + make.bottom.equalToSuperview().offset(-auto(10)) } - + + arrow.contentMode = .scaleAspectFit arrow.snp.makeConstraints { make in - make.right.equalTo(-auto(20)) + make.left.equalTo(titleLabel.snp.right).offset(auto(5)) make.centerY.equalTo(titleLabel) + make.width.height.equalTo(auto(8)) } } diff --git a/OrderScheduling/Rescue/View/IdentityAlertView.swift b/OrderScheduling/Rescue/View/IdentityAlertView.swift new file mode 100644 index 0000000..e7e455f --- /dev/null +++ b/OrderScheduling/Rescue/View/IdentityAlertView.swift @@ -0,0 +1,186 @@ +// +// IdentityAlertView.swift +// OrderScheduling +// +// Created by 中道 on 2025/12/19. +// + +import UIKit +import SnapKit + +final class IdentityAlertView: UIView { + + // MARK: - Public Callbacks + var onConfirm: (() -> Void)? + var onLater: (() -> Void)? + + // MARK: - UI + private let containerView = UIView() + private let iconContainer = UIView() + private let iconImageView = UIImageView() + private let gradientLayer = CAGradientLayer() + private let titleLabel = UILabel() + private let messageLabel = UILabel() + private let confirmButton = UIButton(type: .system) + private let laterButton = UIButton(type: .system) + + // MARK: - Init + + /// times: 第几次提醒;totalTimes: 总次数,比如 3 + init(times: Int = 1, totalTimes: Int = 3, isLast: Bool) { + super.init(frame: .zero) + setupUI(times: times, totalTimes: totalTimes, isLast:isLast) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func layoutSubviews() { + super.layoutSubviews() + gradientLayer.frame = containerView.bounds + } +} + +// MARK: - UI + +private extension IdentityAlertView { + func setupUI(times: Int, totalTimes: Int, isLast: Bool) { + backgroundColor = .clear + + // 容器(白色卡片,顶部有渐变) + addSubview(containerView) + addSubview(iconContainer) + + containerView.layer.cornerRadius = 18 + containerView.layer.masksToBounds = true + + // 渐变背景:上浅橙,下白色,模拟设计稿上半段渐变 + gradientLayer.colors = [ + UIColor(red: 0xFF/255.0, green: 0xE4/255.0, blue: 0xD7/255.0, alpha: 1).cgColor, + UIColor.white.cgColor + ] + gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) + gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.25) + containerView.layer.insertSublayer(gradientLayer, at: 0) + + // 先约束图标容器:居中,顶在 entry 顶部;宽高 52 + iconContainer.layer.cornerRadius = 26 + iconContainer.layer.masksToBounds = true + iconContainer.backgroundColor = .clear + + iconContainer.snp.makeConstraints { make in + make.top.equalToSuperview() // 让图标顶部贴住 entry 顶部 + make.centerX.equalToSuperview() + make.width.height.equalTo(52) + } + + // 再约束白色卡片:顶部经过图标中心,实现“图标一半悬在卡片外”的效果 + containerView.snp.makeConstraints { make in + make.top.equalTo(iconContainer.snp.centerY) + make.left.right.bottom.equalToSuperview() + } + + // 感叹号图标(切好的 52x52 图片,内含背景样式) + iconImageView.image = UIImage(named: "IdentityAlertNotice") + iconImageView.contentMode = .scaleAspectFit + iconContainer.addSubview(iconImageView) + iconImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + // 标题 + titleLabel.text = "重要提示" + titleLabel.font = .boldSystemFont(ofSize: 18) + titleLabel.textColor = UIColor(red: 51/255, green: 51/255, blue: 51/255, alpha: 1) + titleLabel.textAlignment = .center + containerView.addSubview(titleLabel) + + titleLabel.snp.makeConstraints { make in + make.top.equalTo(iconContainer.snp.bottom).offset(16) + make.left.right.equalToSuperview().inset(20) + } + + // 文案 + let reminderText = isLast ? "本次为最后一次提醒" : "此为第\(times)次提醒" + let message = """ + 中道救援将通过您确认的身份及联系方式,向您发送通知。请务必仔细核对您的身份及联系方式等关键信息,以免因无法接收通知而受到损失。\n + \(reminderText),请及时确认。若\(totalTimes)次提醒仍未确认,您将无法承接案件。 + """ + + let attr = NSMutableAttributedString(string: message) + let fullRange = NSRange(location: 0, length: attr.length) + let paragraph = NSMutableParagraphStyle() + paragraph.lineSpacing = 4 + paragraph.alignment = .center + + attr.addAttributes([ + .font: UIFont.systemFont(ofSize: 14), + .foregroundColor: UIColor(red: 0x66/255, green: 0x66/255, blue: 0x66/255, alpha: 1), + .paragraphStyle: paragraph + ], range: fullRange) + + // 高亮 “将无法承接案件。” + if let highlightRange = (message as NSString).range(of: "请务必仔细核对您的身份及联系方式等关键信息").optionalNonEmpty { + attr.addAttribute(.foregroundColor, + value: UIColor(red: 0xF5/255, green: 0x52/255, blue: 0x3C/255, alpha: 1), + range: highlightRange) + } + + messageLabel.attributedText = attr + messageLabel.numberOfLines = 0 + containerView.addSubview(messageLabel) + + messageLabel.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(12) + make.left.right.equalToSuperview().inset(24) + } + + // 立即确认按钮 + confirmButton.setTitle(isLast ? "放弃" : "立即确认", for: .normal) + confirmButton.setTitleColor(.white, for: .normal) + confirmButton.titleLabel?.font = .boldSystemFont(ofSize: 16) + confirmButton.backgroundColor = UIColor(red: 0xFF/255, green: 0x6B/255, blue: 0x50/255, alpha: 1) + confirmButton.layer.cornerRadius = 20 + confirmButton.layer.masksToBounds = true + confirmButton.addTarget(self, action: #selector(handleConfirm), for: .touchUpInside) + containerView.addSubview(confirmButton) + + confirmButton.snp.makeConstraints { make in + make.top.equalTo(messageLabel.snp.bottom).offset(20) + make.left.right.equalToSuperview().inset(40) + make.height.equalTo(40) + } + + // 稍后提醒按钮 + laterButton.setTitle("稍后提醒", for: .normal) + laterButton.setTitleColor(UIColor(red: 0x99/255, green: 0x99/255, blue: 0x99/255, alpha: 1), for: .normal) + laterButton.titleLabel?.font = .systemFont(ofSize: 14) + laterButton.addTarget(self, action: #selector(handleLater), for: .touchUpInside) + containerView.addSubview(laterButton) + + laterButton.snp.makeConstraints { make in + make.top.equalTo(confirmButton.snp.bottom).offset(12) + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(-20) + } + } +} + +// MARK: - Actions + +private extension IdentityAlertView { + @objc func handleConfirm() { + onConfirm?() + } + + @objc func handleLater() { + onLater?() + } +} + +private extension NSRange { + var optionalNonEmpty: NSRange? { + return location != NSNotFound && length > 0 ? self : nil + } +} diff --git a/OrderScheduling/Rescue/ViewController/RescueController.swift b/OrderScheduling/Rescue/ViewController/RescueController.swift index a1aa698..5b36e74 100644 --- a/OrderScheduling/Rescue/ViewController/RescueController.swift +++ b/OrderScheduling/Rescue/ViewController/RescueController.swift @@ -136,6 +136,20 @@ extension RescueController { }) .disposed(by: disposeBag) + WEBTOOL.supplierAppIsUserNewReportRelay + .flatMapLatest { _ in + return RQ.getConfigByCode(parameters: ConfigByCodeParameters(code: "AppIsUseNewReport")) + } + .observe(on: MainScheduler.instance) + .subscribe(onNext: {[weak self] response in + if response?.success == true { + WEBTOOL.supplierAppIsUserNewReport = (response?.data?.supplierAppIsUserNewReport == "true") + }else{ + self?.view.dd_makeToast(response?.msg) + } + }) + .disposed(by: disposeBag) + onlineReminderRelay .flatMapLatest { _ in return RQ.onlineReminder(parameters: OnlineReminderParameters(supplierId: UserData.default.supplierId)) @@ -170,6 +184,43 @@ extension RescueController { }) .disposed(by: disposeBag) + judgeIfNeedConfirmEntryRelay + .flatMapLatest { _ in + return RQ.judgeIfNeedConfirm(prameters: JudgeIfNeedConfirmParameters(supplierId: UserData.default.supplierId)) + } + .observe(on: MainScheduler.instance) + .subscribe(onNext: {[weak self] response in + guard let self = self else { return } + if response?.success == true { + if response?.data?.needConfirm == true { + let isLast = (response?.data?.isLast == true) + let entryName = "IdentityAlert" + let entryView = IdentityAlertView(times: response?.data?.count ?? 0,totalTimes: 3, isLast: isLast) + entryView.onLater = { + Entry.default.dismiss(name: entryName) + } + entryView.onConfirm = { + Entry.default.dismiss(name: entryName,completion: { + if isLast { + RQ.giveUp(prameters: GiveUpParameters(supplierId: UserData.default.supplierId)) + .subscribe(onSuccess: { _ in + }) + .disposed(by: self.disposeBag) + }else{ + if let supplierId = UserData.default.supplierId { + WEBTOOL.open(name: .managerPeople, appending: "&supplierId=\(supplierId)") + } + } + }) + } + Entry.default.showIdentityAlert(view: entryView, name: entryName) + } + }else{ + self.view.dd_makeToast(response?.msg) + } + }) + .disposed(by: disposeBag) + // 点击tabBar 需要刷下下列 preRefreshRelay .observe(on: MainScheduler.instance) @@ -183,9 +234,11 @@ extension RescueController { func excuseRelay() { NewTraining.default.newTrainingRelay.accept(nil) + WEBTOOL.supplierAppIsUserNewReportRelay.accept(nil) appBannerRelay.accept(nil) appPushRecordRelay.accept(nil) onlineReminderRelay.accept(nil) + judgeIfNeedConfirmEntryRelay.accept(nil) } } @@ -937,10 +990,9 @@ extension RescuePendingDispatchController : UITableViewDelegate,UITableViewDataS cell?.reportButton.rx.tap .observe(on: MainScheduler.instance) .subscribe(onNext: { _ in -// if let supplierId = USER.supplierId { -// WEBTOOL.open(name: .reportIndex,appending: "&userOrderId=\(model.userOrderId)&type=1&userOrderCode=\(model.taskCode)&supplierId=\(supplierId)") -// } - WEBTOOL.open(name: .reporting,appending: "&queryType=\(OrderTypeEnum.TO_DISPATCH_VEHICLE.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)") + if let supplierId = USER.supplierId { + WEBTOOL.openReportIndex(queryType: OrderTypeEnum.TO_DISPATCH_VEHICLE.rawValue, userOrderId: model.userOrderId, orderCode: model.orderCode, type: 1, userOrderCode: model.taskCode, supplierId: supplierId) + } }) .disposed(by: cell!.disposeBag) cell?.contactButton.rx.tap @@ -1099,10 +1151,9 @@ extension RescueIsIngController : UITableViewDelegate,UITableViewDataSource { cell?.reportButton.rx.tap .observe(on: MainScheduler.instance) .subscribe(onNext: { _ in -// if let supplierId = USER.supplierId { -// WEBTOOL.open(name: .reportIndex,appending: "&userOrderId=\(model.userOrderId)&type=1&userOrderCode=\(model.taskCode)&supplierId=\(supplierId)") -// } - WEBTOOL.open(name: .reporting,appending: "&queryType=\(OrderTypeEnum.TO_DISPATCH_VEHICLE.rawValue)&userOrderId=\(model.userOrderId)&orderCode=\(model.orderCode)") + if let supplierId = USER.supplierId { + WEBTOOL.openReportIndex(queryType: OrderTypeEnum.TO_DISPATCH_VEHICLE.rawValue, userOrderId: model.userOrderId, orderCode: model.orderCode, type: 1, userOrderCode: model.taskCode, supplierId: supplierId) + } }) .disposed(by: cell!.disposeBag) @@ -1221,7 +1272,9 @@ class RescueController : ZDViewController { private var bannerDataSources : [ConfigByCodeDataModel.ConfigByCodeBannerModel] = [] private var onlineReminderRelay = ReplayRelay.create(bufferSize: 1) - + + private var judgeIfNeedConfirmEntryRelay = ReplayRelay.create(bufferSize: 1) + override func viewDidLoad() { super.viewDidLoad() dd_navigationBarBackgroundColor = .hex("354683")