From eb7a4585fa25566023a2a49caa7c83e03a29bd32 Mon Sep 17 00:00:00 2001 From: songzhiling <17630035658@163.com> Date: Thu, 17 Apr 2025 15:08:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(servicing):=20=E6=96=B0=E5=A2=9E=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=A4=84=E7=90=86?= =?UTF-8?q?-=20=E6=96=B0=E5=A2=9E=20FastLoginRequest=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=B1=BB=E7=94=A8=E4=BA=8E=E5=BF=AB=E9=80=9F=E7=99=BB=E5=BD=95?= =?UTF-8?q?=20-=20=E6=B7=BB=E5=8A=A0=20iaiCompareFace=20API=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=94=A8=E4=BA=8E=E4=BA=BA=E8=84=B8=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E6=AF=94=E8=BE=83=20-=20=E6=9B=B4=E6=96=B0=20DriverInfo=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=B1=BB=EF=BC=8C=E5=A2=9E=E5=8A=A0=20loginL?= =?UTF-8?q?ogId=20=E5=AD=97=E6=AE=B5-=20=E9=87=8D=E6=9E=84=20GlobalData=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E5=AD=98?= =?UTF-8?q?=E5=82=A8=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BD=BF=E7=94=A8=20MMKV?= =?UTF-8?q?=E6=9B=BF=E4=BB=A3=E6=95=B0=E6=8D=AE=E5=BA=93=20-=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20InServicingBottomView=20=E4=B8=AD=E7=9A=84=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E6=94=BE=E5=BC=83=E5=92=8C=E6=8B=A8=E6=89=93=E7=94=B5?= =?UTF-8?q?=E8=AF=9D=E5=8A=9F=E8=83=BD=20-=20=E6=9B=B4=E6=96=B0=20JpushBea?= =?UTF-8?q?n=EF=BC=8C=E5=A2=9E=E5=8A=A0=20userOrderId=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=20-=20=E4=BF=AE=E6=94=B9=20AndroidManifest.xml=20=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=9D=83=E9=99=90=E5=A3=B0=E6=98=8E=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=8A=A8=E6=80=81=E5=BA=94=E7=94=A8ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 11 +- .../main/java/com/za/sdk/demo/MainActivity.kt | 2 +- gradle/libs.versions.toml | 3 +- servicing/src/main/AndroidManifest.xml | 10 +- .../src/main/java/com/za/bean/DriverInfo.kt | 3 +- .../src/main/java/com/za/bean/JpushBean.kt | 2 +- .../src/main/java/com/za/bean/PreviewBean.kt | 15 + .../src/main/java/com/za/bean/request/Auth.kt | 10 +- .../java/com/za/bean/request/LoginRequest.kt | 2 + .../src/main/java/com/za/common/GlobalData.kt | 49 +- .../src/main/java/com/za/net/ApiService.kt | 10 +- .../src/main/java/com/za/net/BaseObserver.kt | 16 - .../src/main/java/com/za/net/CommonMethod.kt | 59 +- .../src/main/java/com/za/room/RoomHelper.kt | 2 +- .../main/java/com/za/room/db/GlobalRoom.kt | 6 +- .../com/za/room/db/user/DriverInfoBean.kt | 64 +- .../java/com/za/room/db/user/DriverInfoDao.kt | 40 - .../com/za/ui/camera/ZdCameraXActivity.kt | 847 +++++++++--------- .../com/za/ui/main/ServiceLauncherActivity.kt | 2 + .../com/za/ui/main/ServicingMainActivity.kt | 245 ++++- .../java/com/za/ui/main/ServicingMainVm.kt | 3 + .../com/za/ui/new_order/NewOrderActivity.kt | 1 - .../order_give_up/OrderGiveUpActivity.kt | 190 ++-- .../servicing/view/InServicingBottomView.kt | 427 +++++---- .../wait_to_start/WaitToStartActivity.kt | 721 +++++++-------- .../servicing/wait_to_start/WaitToStartVm.kt | 57 +- servicing/src/main/res/drawable/sv_copy.xml | 22 +- servicing/src/main/res/values/strings.xml | 1 + servicing/src/main/res/values/themes.xml | 2 + zd_sdk_demo.jks | Bin 0 -> 2516 bytes 30 files changed, 1626 insertions(+), 1196 deletions(-) create mode 100644 servicing/src/main/java/com/za/bean/PreviewBean.kt delete mode 100644 servicing/src/main/java/com/za/room/db/user/DriverInfoDao.kt create mode 100644 zd_sdk_demo.jks diff --git a/app/build.gradle b/app/build.gradle index 04a7049..b708864 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,13 +33,22 @@ android { ] } - buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + signingConfigs { + release { + storeFile file('E:\\workspace\\study\\zd_sdk_demo\\zd_sdk_demo.jks') + storePassword '123456' + keyAlias 'key0' + keyPassword '123456' + } + } + compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 diff --git a/app/src/main/java/com/za/sdk/demo/MainActivity.kt b/app/src/main/java/com/za/sdk/demo/MainActivity.kt index d64de81..75d014c 100644 --- a/app/src/main/java/com/za/sdk/demo/MainActivity.kt +++ b/app/src/main/java/com/za/sdk/demo/MainActivity.kt @@ -27,7 +27,7 @@ class MainActivity : ComponentActivity() { .fillMaxSize() .clickable { val uri = - "zd.assist://app?taskCode=ZD250407100237&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri() + "zd.assist://app?taskCode=ZD250416100398&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri() val intent = Intent(Intent.ACTION_VIEW, uri) startActivity(intent) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 70bbe5a..ff555f7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,8 @@ jcore = "3.3.2" jpush = "4.8.1" location = "5.6.1" loggingInterceptor = "4.11.0" -mmkv = "2.1.0" +#这是一个长期维护的版本,不建议升级 +mmkv = "1.3.11" orgEclipsePahoAndroidService = "1.1.1" orgEclipsePahoClientMqttv3 = "1.2.5" permissionx = "1.8.0" diff --git a/servicing/src/main/AndroidManifest.xml b/servicing/src/main/AndroidManifest.xml index 7343874..5c6c812 100644 --- a/servicing/src/main/AndroidManifest.xml +++ b/servicing/src/main/AndroidManifest.xml @@ -3,8 +3,9 @@ xmlns:tools="http://schemas.android.com/tools"> + @@ -78,9 +79,7 @@ - - + android:theme="@style/Theme.Dealer" /> - @@ -243,6 +242,7 @@ + { + override val values : Sequence + get() = sequenceOf(OrderInfo(taskCode = "123456789", + address = "上海市浦东新区", + distAddress = "上海市浦东新区", + addressProperty = "服务中", + serviceTypeName = "救援", + plateNumber = "沪A12345", + importantTip = "请保持电话畅通,服务人员将尽快联系您。")) +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/bean/request/Auth.kt b/servicing/src/main/java/com/za/bean/request/Auth.kt index d894138..5c75db3 100644 --- a/servicing/src/main/java/com/za/bean/request/Auth.kt +++ b/servicing/src/main/java/com/za/bean/request/Auth.kt @@ -1,5 +1,11 @@ package com.za.bean.request -data class DriverFaceCompareRequest(val vehicleId: Int? = null, val driverId: Int? = null, val photoUrl: String? = null) +data class DriverFaceCompareRequest(val vehicleId : Int? = null, + val driverId : Int? = null, + val photoUrl : String? = null) -data class DriverFaceCompareBean(val flowId: Int? = null, val shortLink: String? = null, val url: String? = null) \ No newline at end of file +data class DriverFaceCompareBean(val flowId : Int? = null, + val shortLink : String? = null, + val url : String? = null) + +data class IaiCompareFaceBean(val score : Float? = null, val compareResult : Boolean? = null) \ No newline at end of file diff --git a/servicing/src/main/java/com/za/bean/request/LoginRequest.kt b/servicing/src/main/java/com/za/bean/request/LoginRequest.kt index 09563d8..2258174 100644 --- a/servicing/src/main/java/com/za/bean/request/LoginRequest.kt +++ b/servicing/src/main/java/com/za/bean/request/LoginRequest.kt @@ -15,6 +15,8 @@ data class LoginRequest( var dashboardPath: String? = null //里程表照片路径 ) +data class FastLoginRequest(var deviceId: String? = null) + data class PhoneBean( var versionRelease: String? = null,//系统版本 var model: String? = null,//手机型号 diff --git a/servicing/src/main/java/com/za/common/GlobalData.kt b/servicing/src/main/java/com/za/common/GlobalData.kt index 2d0975e..223fecd 100644 --- a/servicing/src/main/java/com/za/common/GlobalData.kt +++ b/servicing/src/main/java/com/za/common/GlobalData.kt @@ -5,60 +5,82 @@ import com.amap.api.location.AMapLocation import com.blankj.utilcode.util.AppUtils import com.tencent.mmkv.MMKV import com.za.bean.db.order.OrderInfo +import com.za.common.log.LogUtil import com.za.room.RoomHelper import com.za.room.db.user.DriverInfoBean object GlobalData { lateinit var application : Application + private val mmkv : MMKV by lazy { MMKV.defaultMMKV() } var activityCount : Int = 0 var isMaster = AppUtils.getAppPackageName() == "com.za.rescue.dealer" var token : String? = null get() { - return MMKV.defaultMMKV().decodeString("ZD_TOKEN", null) + return mmkv.decodeString("ZD_TOKEN", null) } set(value) { - MMKV.defaultMMKV().encode("ZD_TOKEN", value) + mmkv.encode("ZD_TOKEN", value) field = value } var regid : String? = null get() { - return MMKV.defaultMMKV().decodeString("regid", null) + return mmkv.decodeString("regid", null) } set(value) { - MMKV.defaultMMKV().encode("regid", value) + mmkv.encode("regid", value) field = value } var aesKey : String? = null get() { - return MMKV.defaultMMKV().decodeString("AES_KEY", null) + return mmkv.decodeString("AES_KEY", null) } set(value) { - MMKV.defaultMMKV().encode("AES_KEY", value) + mmkv.encode("AES_KEY", value) field = value } //新订单是否已经被处理 var isHandlerNewOrder : Boolean? = false - var driverInfoBean : DriverInfoBean? = null + private val lock = Any() + var driverInfoBean : DriverInfoBean? get() { - val driverInfoBean = RoomHelper.db?.driverInfoDao()?.getDriverInfoFromUserId() + synchronized(lock) { + val driverInfoBean = + mmkv.decodeParcelable("driverInfoBean", DriverInfoBean::class.java) + LogUtil.print("driverInfo get", "driverInfoBean = $driverInfoBean") + return driverInfoBean + } + } + set(value) { + synchronized(lock) { + mmkv.encode("driverInfoBean", value) + if (value != null) { + lastLoginBean = value + } + LogUtil.print("driverInfo set", "driverInfoBean = $value") + } + } + + var lastLoginBean : DriverInfoBean? = null + get() { + val driverInfoBean = mmkv.decodeParcelable("lastLoginBean", DriverInfoBean::class.java) field = driverInfoBean return driverInfoBean } set(value) { - RoomHelper.db?.driverInfoDao()?.updateDriverInfo(value) + mmkv.encode("lastLoginBean", value) } var currentOrder : OrderInfo? = null get() { - return MMKV.defaultMMKV().decodeParcelable("currentOrder", OrderInfo::class.java) + return mmkv.decodeParcelable("currentOrder", OrderInfo::class.java) } set(value) { - MMKV.defaultMMKV().encode("currentOrder", value) + mmkv.encode("currentOrder", value) if (RoomHelper.db?.orderDao()?.getCurrentOrder() == null && value != null) { RoomHelper.db?.orderDao()?.insertOrder(value) } else if (value != null) { @@ -78,10 +100,10 @@ object GlobalData { var loginTime : Long? = null get() { - return MMKV.defaultMMKV().decodeLong("loginTime", System.currentTimeMillis()) + return mmkv.decodeLong("loginTime", System.currentTimeMillis()) } set(value) { - MMKV.defaultMMKV().encode("loginTime", value ?: System.currentTimeMillis()) + mmkv.encode("loginTime", value ?: System.currentTimeMillis()) field = value } @@ -89,6 +111,7 @@ object GlobalData { token = null aesKey = null currentLocation = null + driverInfoBean = null loginTime = null } diff --git a/servicing/src/main/java/com/za/net/ApiService.kt b/servicing/src/main/java/com/za/net/ApiService.kt index a957800..2bf521c 100644 --- a/servicing/src/main/java/com/za/net/ApiService.kt +++ b/servicing/src/main/java/com/za/net/ApiService.kt @@ -37,12 +37,14 @@ import com.za.bean.request.CustomerPaymentCreateRequest import com.za.bean.request.DriverFaceCompareBean import com.za.bean.request.DriverFaceCompareRequest import com.za.bean.request.ElectronOrderResponse +import com.za.bean.request.FastLoginRequest import com.za.bean.request.FetchVehicleMaintenanceSubmitHistoryRequestBean import com.za.bean.request.GeneralInfoRequest import com.za.bean.request.GiveUpTaskRequest import com.za.bean.request.HistoryDetailRequest import com.za.bean.request.HistoryPhotoTemplateRequest import com.za.bean.request.HistoryTasksRequest +import com.za.bean.request.IaiCompareFaceBean import com.za.bean.request.LoginRequest import com.za.bean.request.OrderListRequest import com.za.bean.request.OrderPhotoOcrRecognizeRequest @@ -116,6 +118,9 @@ interface ApiService { @POST("/driverApp/task/login") fun login(@Body info : LoginRequest) : Observable> + @POST("/driverApp/supplier/fastLogin") + fun fastLogin(@Body info : FastLoginRequest) : Observable> + //获取该手机号下面服务商列表 @POST("/driverApp/supplier/getDriverListInfo") fun getDriverListInfo(@Body info : VerifyCodeRequest) : Observable>> @@ -271,4 +276,7 @@ interface ApiService { @POST("driverApp/base/getVoiceUrl") fun getVoiceUrl(@Body info : AppNewOrderVoiceRequest) : Observable> -} \ No newline at end of file + + @POST("driverApp/supplier/iaiCompareFace") + fun iaiCompareFace(@Body info : DriverFaceCompareRequest) : Observable> +} diff --git a/servicing/src/main/java/com/za/net/BaseObserver.kt b/servicing/src/main/java/com/za/net/BaseObserver.kt index f0d8e8d..2acb45e 100644 --- a/servicing/src/main/java/com/za/net/BaseObserver.kt +++ b/servicing/src/main/java/com/za/net/BaseObserver.kt @@ -2,7 +2,6 @@ package com.za.net import android.net.ParseException import com.blankj.utilcode.util.ActivityUtils -import com.blankj.utilcode.util.NetworkUtils import com.blankj.utilcode.util.ToastUtils import com.google.gson.JsonParseException import com.za.base.Const @@ -105,21 +104,6 @@ abstract class BaseObserver : Observer> { GlobalData.clearUserCache() ZdLocationManager.stopContinuousLocation() ActivityUtils.finishAllActivities() -// val oldLoginInfo: LoginInfo = DbManager.getInstance(context).queryLoginInfo() -// val loginInfo: LoginInfo = LoginInfo() -// loginInfo.setSupplierId(oldLoginInfo.getSupplierId()) -// loginInfo.setSupplierCode(oldLoginInfo.getSupplierCode()) -// loginInfo.setJobNumber(oldLoginInfo.getJobNumber()) -// loginInfo.setPassword(oldLoginInfo.getPassword()) -// DbManager.getInstance(context).deleteLoginInfo() -// DbManager.getInstance(context).saveLoginInfo(loginInfo) -// SPKit.saveString(context, "userId", "-1") -// SPKit.saveString(context, "vehicleId", "-1") -// -// LBSManager.getInstance().cancel() -// DaemonService.stopService() -// //跳转 -// RsaRouter.navigateNoFlag(context, "/page/login") } catch (e: Exception) { LogUtil.print("handlerTokenExpired", e) } diff --git a/servicing/src/main/java/com/za/net/CommonMethod.kt b/servicing/src/main/java/com/za/net/CommonMethod.kt index db375c7..17cf644 100644 --- a/servicing/src/main/java/com/za/net/CommonMethod.kt +++ b/servicing/src/main/java/com/za/net/CommonMethod.kt @@ -27,6 +27,7 @@ import com.za.common.util.DeviceUtil import com.za.ext.toJson import com.za.offline.OfflineManager import com.za.room.RoomHelper +import com.za.room.db.user.DriverInfoBean import com.za.ui.new_order.NewOrderActivity import com.za.ui.order_report.ReportFloatingManager import com.za.water_marker.WaterMarkerTemplateManager @@ -113,6 +114,8 @@ object CommonMethod { }) } + + private var lastFetchGenerateInfoTime : Long = 0L fun getGenerateInfo(vehicleId : Int? = null, userId : Int? = null, success : (GeneralInfo) -> Unit = {}, @@ -130,22 +133,46 @@ object CommonMethod { LogUtil.print("getGenerateInfo", "获取车辆信息失败") return } - val driverInfoBean = GlobalData.driverInfoBean - GlobalData.driverInfoBean = driverInfoBean?.copy(vehicleId = it.vehicleId, - vehicleName = it.vehicleName, - userName = it.userName, - userPhone = it.userPhone, - plateNumber = it.plateNumber, - vehicleState = it.vehicleState, - supplierType = it.supplierType, - userPortrait = it.userPortrait, - userId = it.userId, - supplierId = it.supplierId, - deviceId = it.deviceId, - supplierName = it.supplierName, - authStatus = it.authStatus, - serviceList = it.serviceList?.toString()) - + if (GlobalData.driverInfoBean != null && (System.currentTimeMillis() - lastFetchGenerateInfoTime < 1000 * 10)) { + LogUtil.print("getGenerateInfo", "获取车辆信息成功,但是时间间隔小于10秒,不更新车辆信息") + success(it) + return + } + if (GlobalData.driverInfoBean == null) { + GlobalData.driverInfoBean = DriverInfoBean(vehicleId = it.vehicleId, + vehicleName = it.vehicleName, + userName = it.userName, + loginLogId = it.loginLogId, + userPhone = it.userPhone, + plateNumber = it.plateNumber, + vehicleState = it.vehicleState, + supplierType = it.supplierType, + userPortrait = it.userPortrait, + userId = it.userId, + supplierId = it.supplierId, + deviceId = it.deviceId, + supplierName = it.supplierName, + authStatus = it.authStatus, + serviceList = it.serviceList?.toString()) + } else { + GlobalData.driverInfoBean = + GlobalData.driverInfoBean?.copy(vehicleId = it.vehicleId, + vehicleName = it.vehicleName, + userName = it.userName, + userPhone = it.userPhone, + plateNumber = it.plateNumber, + vehicleState = it.vehicleState, + supplierType = it.supplierType, + userPortrait = it.userPortrait, + userId = it.userId, + loginLogId = it.loginLogId, + supplierId = it.supplierId, + deviceId = it.deviceId, + supplierName = it.supplierName, + authStatus = it.authStatus, + serviceList = it.serviceList?.toString()) + } + lastFetchGenerateInfoTime = System.currentTimeMillis() LogUtil.print("GlobalData.driverInfoBean", "${GlobalData.driverInfoBean?.toJson()}}") diff --git a/servicing/src/main/java/com/za/room/RoomHelper.kt b/servicing/src/main/java/com/za/room/RoomHelper.kt index 02ae83d..02105d5 100644 --- a/servicing/src/main/java/com/za/room/RoomHelper.kt +++ b/servicing/src/main/java/com/za/room/RoomHelper.kt @@ -11,7 +11,7 @@ import com.za.room.db.GlobalRoom @SuppressLint("StaticFieldLeak") object RoomHelper { - const val VERSION: Int = 37 + const val VERSION: Int = 38 private lateinit var mContext: Context var db: GlobalRoom? = null diff --git a/servicing/src/main/java/com/za/room/db/GlobalRoom.kt b/servicing/src/main/java/com/za/room/db/GlobalRoom.kt index ade2c22..15fac80 100644 --- a/servicing/src/main/java/com/za/room/db/GlobalRoom.kt +++ b/servicing/src/main/java/com/za/room/db/GlobalRoom.kt @@ -18,14 +18,12 @@ import com.za.room.db.ele_work.EleWorkOrderDao import com.za.room.db.order.ChangeBatteryDao import com.za.room.db.order.OrderDao import com.za.room.db.order.PhotoTemplateDao -import com.za.room.db.user.DriverInfoBean -import com.za.room.db.user.DriverInfoDao import com.za.room.db.user.LocalResourceBean import com.za.room.db.user.LocalResourceDao import com.za.room.db.water_marker.WaterMarkerDao -@Database(entities = [EleWorkOrderBean::class, EleCarDamagePhotoBean::class, LocalResourceBean::class, WaterMarkerTemplateBean::class, WaterMarkerItemBean::class, ChangeBatteryPhoto::class, NewPhotoTemplateBean::class, OrderInfo::class, OfflineUpdateTaskBean::class, DriverInfoBean::class, PhotoTemplateInfo::class], +@Database(entities = [EleWorkOrderBean::class, EleCarDamagePhotoBean::class, LocalResourceBean::class, WaterMarkerTemplateBean::class, WaterMarkerItemBean::class, ChangeBatteryPhoto::class, NewPhotoTemplateBean::class, OrderInfo::class, OfflineUpdateTaskBean::class, PhotoTemplateInfo::class], version = RoomHelper.VERSION, exportSchema = false) abstract class GlobalRoom : RoomDatabase() { @@ -43,7 +41,5 @@ abstract class GlobalRoom : RoomDatabase() { abstract fun offlineTaskDao() : OfflineDao - abstract fun driverInfoDao() : DriverInfoDao - abstract fun localResourceDao() : LocalResourceDao } diff --git a/servicing/src/main/java/com/za/room/db/user/DriverInfoBean.kt b/servicing/src/main/java/com/za/room/db/user/DriverInfoBean.kt index a0726cf..c1640db 100644 --- a/servicing/src/main/java/com/za/room/db/user/DriverInfoBean.kt +++ b/servicing/src/main/java/com/za/room/db/user/DriverInfoBean.kt @@ -1,11 +1,10 @@ package com.za.room.db.user -import androidx.room.Entity -import androidx.room.PrimaryKey +import android.os.Parcel +import android.os.Parcelable -@Entity(tableName = "driver_info") data class DriverInfoBean( - @PrimaryKey(autoGenerate = false) val userId : Int? = null, //用户id + val userId : Int? = null, //用户id val userName : String? = null, //用户姓名 val userPhone : String? = null, //用户手机号 val userPortrait : String? = null, //用户头像 @@ -23,4 +22,59 @@ data class DriverInfoBean( val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌 val plateNumber : String? = null, //车牌号 val deviceId : String? = null, -) \ No newline at end of file +) : Parcelable { + constructor(parcel : Parcel) : this(parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readString(), + parcel.readString(), + parcel.readString(), + parcel.readString(), + parcel.readString(), + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readString(), + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readString(), + parcel.readString(), + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readString(), + parcel.readValue(Int::class.java.classLoader) as? Int, + parcel.readString(), + parcel.readString()) { + } + + override fun writeToParcel(parcel : Parcel, flags : Int) { + parcel.writeValue(userId) + parcel.writeString(userName) + parcel.writeString(userPhone) + parcel.writeString(userPortrait) + parcel.writeString(rongyunToken) + parcel.writeString(logTime) + parcel.writeValue(supplierId) + parcel.writeString(supplierName) + parcel.writeValue(supplierType) + parcel.writeValue(loginLogId) + parcel.writeString(serviceList) + parcel.writeString(assistUserCode) + parcel.writeValue(authStatus) + parcel.writeValue(vehicleId) + parcel.writeString(vehicleName) + parcel.writeValue(vehicleState) + parcel.writeString(plateNumber) + parcel.writeString(deviceId) + } + + override fun describeContents() : Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel : Parcel) : DriverInfoBean { + return DriverInfoBean(parcel) + } + + override fun newArray(size : Int) : Array { + return arrayOfNulls(size) + } + } +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/room/db/user/DriverInfoDao.kt b/servicing/src/main/java/com/za/room/db/user/DriverInfoDao.kt deleted file mode 100644 index 6845c7a..0000000 --- a/servicing/src/main/java/com/za/room/db/user/DriverInfoDao.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.za.room.db.user - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import androidx.room.Transaction -import androidx.room.Update -import com.za.common.log.LogUtil - -@Dao -interface DriverInfoDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insert(driverInfoBean : DriverInfoBean) - - @Query("SELECT * FROM driver_info") - fun getDriverInfoFromUserId() : DriverInfoBean? - - - @Query("DELETE FROM driver_info") - fun deleteAll() - - @Update(onConflict = OnConflictStrategy.REPLACE) - fun update(driverInfoBean : DriverInfoBean) - - @Transaction - fun updateDriverInfo(driverInfoBean : DriverInfoBean?) { - if (driverInfoBean == null) { - LogUtil.print("DriverInfoDao", "updateDriverInfo driverInfoBean is null") - return - } - val driverInfo = getDriverInfoFromUserId() - if (driverInfo != null && driverInfo.userId == driverInfoBean.userId) { - update(driverInfoBean) - return - } - deleteAll() - insert(driverInfoBean) - } -} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/camera/ZdCameraXActivity.kt b/servicing/src/main/java/com/za/ui/camera/ZdCameraXActivity.kt index 5baaced..100da57 100644 --- a/servicing/src/main/java/com/za/ui/camera/ZdCameraXActivity.kt +++ b/servicing/src/main/java/com/za/ui/camera/ZdCameraXActivity.kt @@ -65,457 +65,490 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors class ZdCameraXActivity : AppCompatActivity() { - private var exposurePopupWindow: PopupWindow? = null + private var exposurePopupWindow : PopupWindow? = null - internal enum class FlashMode { - auto, open, light, close - } + internal enum class FlashMode { + auto, open, light, close + } - private var rootView: ConstraintLayout? = null - private var imageCapture: ImageCapture? = null - private var cameraInfo: CameraInfo? = null + private var rootView : ConstraintLayout? = null + private var imageCapture : ImageCapture? = null + private var cameraInfo : CameraInfo? = null - private var exposureState: ExposureState? = null - private var cameraExecutor: ExecutorService? = null - private var zoomState: LiveData? = null - private var viewFinder: PreviewView? = null - private var takePhoto: TakePhotoButtonView? = null - private var ivFlash: ImageView? = null - private var ivChangeCamera: ImageView? = null - private var ivConfirm: ImageView? = null - private var ivCancel: ImageView? = null - private lateinit var ivPreview: ImageFilterView - private var ivBack: ImageView? = null - private var sliderExposure: AppCompatSeekBar? = null - private var groupOperation: Group? = null - private var groupPreview: Group? = null - private var uri: Uri? = null - private var animatorSet: AnimatorSet? = null - private var location: Location? = null - private var camera: Camera? = null - private var isBack = true + private var exposureState : ExposureState? = null + private var cameraExecutor : ExecutorService? = null + private var zoomState : LiveData? = null + private var viewFinder : PreviewView? = null + private var takePhoto : TakePhotoButtonView? = null + private var ivFlash : ImageView? = null + private var ivChangeCamera : ImageView? = null + private var ivConfirm : ImageView? = null + private var ivCancel : ImageView? = null + private lateinit var ivPreview : ImageFilterView + private var ivBack : ImageView? = null + private var sliderExposure : AppCompatSeekBar? = null + private var groupOperation : Group? = null + private var groupPreview : Group? = null + private var uri : Uri? = null + private var animatorSet : AnimatorSet? = null + private var location : Location? = null + private var camera : Camera? = null + private var isBack = true - private var orientationEventListener: OrientationEventListener? = null - private var flashPopWindow: PopupWindow? = null - private var flashMode = FlashMode.close + private var orientationEventListener : OrientationEventListener? = null + private var flashPopWindow : PopupWindow? = null + private var flashMode = FlashMode.close - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_zd_camera_xactivity) - initView() - initLocation() - startCamera() - setOnClick() + override fun onCreate(savedInstanceState : Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_zd_camera_xactivity) + isBack = intent.getBooleanExtra("isBack", true) + initView() + initLocation() + startCamera() + setOnClick() - orientationEventListener = object : OrientationEventListener(this) { - override fun onOrientationChanged(orientation: Int) { - if (orientation == ORIENTATION_UNKNOWN || imageCapture == null) { - print("zdCamerax orientation", "orientation==$orientation") - return - } - when (orientation) { - in 45..134 -> { - imageCapture?.targetRotation = Surface.ROTATION_270 - } - in 135..224 -> { - imageCapture?.targetRotation = Surface.ROTATION_180 - } - in 225..314 -> { - imageCapture?.targetRotation = Surface.ROTATION_90 - } - else -> { - imageCapture?.targetRotation = Surface.ROTATION_0 - } - } - } - } - } + orientationEventListener = object : OrientationEventListener(this) { + override fun onOrientationChanged(orientation : Int) { + if (orientation == ORIENTATION_UNKNOWN || imageCapture == null) { + print("zdCamerax orientation", "orientation==$orientation") + return + } + when (orientation) { + in 45 .. 134 -> { + imageCapture?.targetRotation = Surface.ROTATION_270 + } - @SuppressLint("ObjectAnimatorBinding") - private fun initView() { - cameraExecutor = Executors.newSingleThreadExecutor() - rootView = findViewById(R.id.viewGroup_parent) - viewFinder = findViewById(R.id.viewFinder) - takePhoto = findViewById(R.id.iv_takePhoto) - ivConfirm = findViewById(R.id.iv_confirm) - ivCancel = findViewById(R.id.iv_cancel) - ivBack = findViewById(R.id.iv_back) - sliderExposure = findViewById(R.id.slider_exposureState) - groupOperation = findViewById(R.id.group_opera) - groupPreview = findViewById(R.id.group_preview) - groupPreview?.visibility = View.GONE - ivChangeCamera = findViewById(R.id.iv_changeCamera) - ivPreview = findViewById(R.id.iv_preview) - ivFlash = findViewById(R.id.iv_flash) - animatorSet = AnimatorSet() - animatorSet?.playTogether(ObjectAnimator.ofFloat(ivCancel, "translationX", 0f, -200f), ObjectAnimator.ofFloat(ivConfirm, "translationX", 200f)) + in 135 .. 224 -> { + imageCapture?.targetRotation = Surface.ROTATION_180 + } - animatorSet?.setDuration(500) - } + in 225 .. 314 -> { + imageCapture?.targetRotation = Surface.ROTATION_90 + } - @SuppressLint("ClickableViewAccessibility") - private fun setOnClick() { - takePhoto?.setOnClickListener(ClickProxy { v: View? -> takePhoto() }) + else -> { + imageCapture?.targetRotation = Surface.ROTATION_0 + } + } + } + } + } - ivChangeCamera?.setOnClickListener(ClickProxy { v: View? -> - isBack = !isBack - if (!isBack) { - if (flashPopWindow != null && flashPopWindow?.isShowing == true) { - flashPopWindow?.dismiss() - } - flashMode = FlashMode.close - ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) - } - startCamera() - }) + @SuppressLint("ObjectAnimatorBinding") + private fun initView() { + cameraExecutor = Executors.newSingleThreadExecutor() + rootView = findViewById(R.id.viewGroup_parent) + viewFinder = findViewById(R.id.viewFinder) + takePhoto = findViewById(R.id.iv_takePhoto) + ivConfirm = findViewById(R.id.iv_confirm) + ivCancel = findViewById(R.id.iv_cancel) + ivBack = findViewById(R.id.iv_back) + sliderExposure = findViewById(R.id.slider_exposureState) + groupOperation = findViewById(R.id.group_opera) + groupPreview = findViewById(R.id.group_preview) + groupPreview?.visibility = View.GONE + ivChangeCamera = findViewById(R.id.iv_changeCamera) + ivPreview = findViewById(R.id.iv_preview) + ivFlash = findViewById(R.id.iv_flash) + animatorSet = AnimatorSet() + animatorSet?.playTogether(ObjectAnimator.ofFloat(ivCancel, "translationX", 0f, - 200f), + ObjectAnimator.ofFloat(ivConfirm, "translationX", 200f)) - ivFlash?.setOnClickListener { - if (!isBack) { - ToastUtils.showShort("前置模式下无法开启!") - return@setOnClickListener - } - if (flashPopWindow != null && flashPopWindow?.isShowing==true) { - flashPopWindow?.dismiss() - } else { - showFlashView() - } - } + animatorSet?.setDuration(500) + } - ivCancel?.setOnClickListener { - groupPreview?.visibility = View.GONE - groupOperation?.visibility = View.VISIBLE - } + @SuppressLint("ClickableViewAccessibility") + private fun setOnClick() { + takePhoto?.setOnClickListener(ClickProxy { v : View? -> takePhoto() }) - ivConfirm?.setOnClickListener { - val intent = Intent() - if (uri != null) { - intent.putExtra("path", UriUtils.uri2File(uri).absolutePath) - } - setResult(RESULT_OK, intent) - finish() - } + ivChangeCamera?.setOnClickListener(ClickProxy { v : View? -> + isBack = ! isBack + if (! isBack) { + if (flashPopWindow != null && flashPopWindow?.isShowing == true) { + flashPopWindow?.dismiss() + } + flashMode = FlashMode.close + ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) + } + startCamera() + }) - ivBack?.setOnClickListener { finish() } + ivFlash?.setOnClickListener { + if (! isBack) { + ToastUtils.showShort("前置模式下无法开启!") + return@setOnClickListener + } + if (flashPopWindow != null && flashPopWindow?.isShowing == true) { + flashPopWindow?.dismiss() + } else { + showFlashView() + } + } - sliderExposure?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { - @SuppressLint("SetTextI18n") - override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { - if (exposureState != null) { - camera?.cameraControl?.setExposureCompensationIndex(Math.round(progress.toFloat())) - if (exposurePopupWindow != null) { - val textView = exposurePopupWindow?.contentView?.findViewWithTag("tv_exposureView") - textView?.text = progress.toString() + "" - } - } - } + ivCancel?.setOnClickListener { + groupPreview?.visibility = View.GONE + groupOperation?.visibility = View.VISIBLE + } - override fun onStartTrackingTouch(seekBar: SeekBar) { - showExposureView() - } + ivConfirm?.setOnClickListener { + val intent = Intent() + if (uri != null) { + intent.putExtra("path", UriUtils.uri2File(uri).absolutePath) + } + setResult(RESULT_OK, intent) + finish() + } - override fun onStopTrackingTouch(seekBar: SeekBar) { - viewFinder?.postDelayed({ exposurePopupWindow?.dismiss() }, 1000) - } - }) + ivBack?.setOnClickListener { finish() } - val cameraXPreviewViewTouchListener = CameraXPreviewViewTouchListener(this) - viewFinder?.setOnTouchListener(cameraXPreviewViewTouchListener) - cameraXPreviewViewTouchListener.setCustomTouchListener(object : CustomTouchListener { - override fun zoom(delta: Float) { - if (zoomState == null) { - return - } - val currentZoomRatio = zoomState?.value?.zoomRatio - currentZoomRatio?.let { - camera?.cameraControl?.setZoomRatio(it.times(delta)) - } + sliderExposure?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { + @SuppressLint("SetTextI18n") + override fun onProgressChanged(seekBar : SeekBar, progress : Int, fromUser : Boolean) { + if (exposureState != null) { + camera?.cameraControl?.setExposureCompensationIndex(Math.round(progress.toFloat())) + if (exposurePopupWindow != null) { + val textView = + exposurePopupWindow?.contentView?.findViewWithTag("tv_exposureView") + textView?.text = progress.toString() + "" + } + } + } - } + override fun onStartTrackingTouch(seekBar : SeekBar) { + showExposureView() + } - override fun click(event: MotionEvent) { - val action = viewFinder?.meteringPointFactory?.createPoint(event.x, event.y)?.let { FocusMeteringAction.Builder(it).build() } - rootView?.post { showTapView(event.rawX.toInt(), event.rawY.toInt()) } - action?.let { - camera?.cameraControl?.startFocusAndMetering(action) - } - } + override fun onStopTrackingTouch(seekBar : SeekBar) { + viewFinder?.postDelayed({ exposurePopupWindow?.dismiss() }, 1000) + } + }) - override fun doubleClick(x: Float, y: Float) { - if (zoomState == null) { - return - } - val currentZoomRatio = zoomState?.value?.zoomRatio - zoomState?.value?.minZoomRatio?.let { - if (currentZoomRatio!! > it) { - camera?.cameraControl?.setLinearZoom(0f) - } else { - camera?.cameraControl?.setLinearZoom(0.5f) - } - } + val cameraXPreviewViewTouchListener = CameraXPreviewViewTouchListener(this) + viewFinder?.setOnTouchListener(cameraXPreviewViewTouchListener) + cameraXPreviewViewTouchListener.setCustomTouchListener(object : CustomTouchListener { + override fun zoom(delta : Float) { + if (zoomState == null) { + return + } + val currentZoomRatio = zoomState?.value?.zoomRatio + currentZoomRatio?.let { + camera?.cameraControl?.setZoomRatio(it.times(delta)) + } - } - }) - } + } - private fun takePhoto() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - ThreadUtils.runOnUiThread { - PermissionX.init(this@ZdCameraXActivity).permissions(Manifest.permission.ACCESS_MEDIA_LOCATION) - .request { allGranted: Boolean, grantedList: List?, deniedList: List? -> - print("ZDCamerax ACCESS_MEDIA_LOCATION 权限请求结果", "allGranted==$allGranted") - if (!allGranted) { - ToastUtils.showLong("权限获取失败") - finish() - } - } - } - } - if (imageCapture == null) { - ToastUtils.showShort("相机打开失败") - finish() - } -// val filename = TimeUtils.date2String(Date(), "yyyyMMddHHmmss") -// val contentValues = ContentValues() -// contentValues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, filename) -// contentValues.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg") -// contentValues.put(MediaStore.Images.ImageColumns.DATE_TAKEN, System.currentTimeMillis()) -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { -// contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) -// } else { -// ImageUtils.save2Album() -// contentValues.put(MediaStore.Images.ImageColumns.DATA, getTakePictureParentPath() + File.separator + filename + ".jpg") -// } -// -// val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver, -// MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build() + override fun click(event : MotionEvent) { + val action = viewFinder?.meteringPointFactory?.createPoint(event.x, event.y) + ?.let { FocusMeteringAction.Builder(it).build() } + rootView?.post { showTapView(event.rawX.toInt(), event.rawY.toInt()) } + action?.let { + camera?.cameraControl?.startFocusAndMetering(action) + } + } + + override fun doubleClick(x : Float, y : Float) { + if (zoomState == null) { + return + } + val currentZoomRatio = zoomState?.value?.zoomRatio + zoomState?.value?.minZoomRatio?.let { + if (currentZoomRatio !! > it) { + camera?.cameraControl?.setLinearZoom(0f) + } else { + camera?.cameraControl?.setLinearZoom(0.5f) + } + } + + } + }) + } + + private fun takePhoto() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + ThreadUtils.runOnUiThread { + PermissionX.init(this@ZdCameraXActivity) + .permissions(Manifest.permission.ACCESS_MEDIA_LOCATION) + .request { allGranted : Boolean, grantedList : List?, deniedList : List? -> + print("ZDCamerax ACCESS_MEDIA_LOCATION 权限请求结果", + "allGranted==$allGranted") + if (! allGranted) { + ToastUtils.showLong("权限获取失败") + finish() + } + } + } + } + if (imageCapture == null) { + ToastUtils.showShort("相机打开失败") + finish() + } // val filename = TimeUtils.date2String(Date(), "yyyyMMddHHmmss") + // val contentValues = ContentValues() + // contentValues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, filename) + // contentValues.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg") + // contentValues.put(MediaStore.Images.ImageColumns.DATE_TAKEN, System.currentTimeMillis()) + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + // contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) + // } else { + // ImageUtils.save2Album() + // contentValues.put(MediaStore.Images.ImageColumns.DATA, getTakePictureParentPath() + File.separator + filename + ".jpg") + // } + // + // val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver, + // MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build() + // Create time stamped name and MediaStore entry. + val filename = SimpleDateFormat("yyyyMMddHHmmss", + Locale.getDefault()).format(System.currentTimeMillis()) + val contentValues = ContentValues().apply { + put(MediaStore.MediaColumns.DISPLAY_NAME, filename) + put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/中道救援") + } + } - // Create time stamped name and MediaStore entry. - val filename = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()) - .format(System.currentTimeMillis()) - val contentValues = ContentValues().apply { - put(MediaStore.MediaColumns.DISPLAY_NAME, filename) - put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { - put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/中道救援") - } - } - - // Create output options object which contains file + metadata - val outputOptions = ImageCapture.OutputFileOptions - .Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) - .build() + // Create output options object which contains file + metadata + val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver, + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + contentValues).build() - takePhoto?.startAnimation() + takePhoto?.startAnimation() - imageCapture?.takePicture(outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback { - override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { - this@ZdCameraXActivity.uri = outputFileResults.savedUri - //保存照片信息 - val exifInterface: ExifInterface - try { - exifInterface = ExifInterface(UriUtils.uri2File(outputFileResults.savedUri).absolutePath) - exifInterface.setAttribute(ExifInterface.TAG_DATETIME, filename) - if (location != null) { - exifInterface.setGpsInfo(location) - if (location?.latitude!! > 0f && location?.longitude != null && location?.longitude!! > 0f) { - exifInterface.setLatLong(location?.latitude!!, location?.longitude!!) - } - } + imageCapture?.takePicture(outputOptions, + ContextCompat.getMainExecutor(this), + object : ImageCapture.OnImageSavedCallback { + override fun onImageSaved(outputFileResults : ImageCapture.OutputFileResults) { + this@ZdCameraXActivity.uri = outputFileResults.savedUri //保存照片信息 + val exifInterface : ExifInterface + try { + exifInterface = + ExifInterface(UriUtils.uri2File(outputFileResults.savedUri).absolutePath) + exifInterface.setAttribute(ExifInterface.TAG_DATETIME, filename) + if (location != null) { + exifInterface.setGpsInfo(location) + if (location?.latitude !! > 0f && location?.longitude != null && location?.longitude !! > 0f) { + exifInterface.setLatLong(location?.latitude !!, + location?.longitude !!) + } + } - exifInterface.saveAttributes() - takePhoto?.cancelAnimation() - groupPreview?.visibility = View.VISIBLE - if (!this@ZdCameraXActivity.isFinishing) { - Glide.with(this@ZdCameraXActivity).load(outputFileResults.savedUri).into(ivPreview) - } - groupOperation?.visibility = View.GONE - animatorSet?.start() - } catch (e: IOException) { - takePhoto?.cancelAnimation() - ToastUtils.showShort("照片保存失败" + e.message) - print("照片保存失败", e) - } - } + exifInterface.saveAttributes() + takePhoto?.cancelAnimation() + groupPreview?.visibility = View.VISIBLE + if (! this@ZdCameraXActivity.isFinishing) { + Glide.with(this@ZdCameraXActivity).load(outputFileResults.savedUri) + .into(ivPreview) + } + groupOperation?.visibility = View.GONE + animatorSet?.start() + } catch (e : IOException) { + takePhoto?.cancelAnimation() + ToastUtils.showShort("照片保存失败" + e.message) + print("照片保存失败", e) + } + } - override fun onError(exception: ImageCaptureException) { - takePhoto?.cancelAnimation() - ToastUtils.showShort("Photo capture failed" + exception.message) - print("onCameraError", exception) - } - }) - } + override fun onError(exception : ImageCaptureException) { + takePhoto?.cancelAnimation() + ToastUtils.showShort("Photo capture failed" + exception.message) + print("onCameraError", exception) + } + }) + } - private fun startCamera() { - imageCapture = ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY).build() - val cameraProviderFuture = ProcessCameraProvider.getInstance(this) - cameraProviderFuture.addListener({ - try { - val cameraProvider = cameraProviderFuture.get() - val preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build() + private fun startCamera() { + imageCapture = + ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY) + .build() + val cameraProviderFuture = ProcessCameraProvider.getInstance(this) + cameraProviderFuture.addListener({ + try { + val cameraProvider = cameraProviderFuture.get() + val preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build() - preview.setSurfaceProvider(viewFinder?.surfaceProvider) - val cameraSelector = if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA - preview.targetRotation = Surface.ROTATION_0 - cameraProvider.unbindAll() - camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture) - cameraInfo = camera?.cameraInfo - zoomState = cameraInfo?.zoomState - exposureState = cameraInfo?.exposureState - if (exposureState?.isExposureCompensationSupported == true) { - sliderExposure?.visibility = View.VISIBLE - sliderExposure?.max = exposureState?.exposureCompensationRange?.upper ?: 1 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - sliderExposure?.min = exposureState?.exposureCompensationRange?.lower ?: 1 - } - } else { - sliderExposure?.visibility = View.GONE - } - } catch (e: ExecutionException) { - finish() - print("相机初始化失败", e) - } catch (e: InterruptedException) { - finish() - print("相机初始化失败", e) - } - }, ContextCompat.getMainExecutor(this)) - } + preview.surfaceProvider = viewFinder?.surfaceProvider + val cameraSelector = + if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA + preview.targetRotation = Surface.ROTATION_0 + cameraProvider.unbindAll() + camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture) + cameraInfo = camera?.cameraInfo + zoomState = cameraInfo?.zoomState + exposureState = cameraInfo?.exposureState + if (exposureState?.isExposureCompensationSupported == true) { + sliderExposure?.visibility = View.VISIBLE + sliderExposure?.max = exposureState?.exposureCompensationRange?.upper ?: 1 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + sliderExposure?.min = exposureState?.exposureCompensationRange?.lower ?: 1 + } + } else { + sliderExposure?.visibility = View.GONE + } + } catch (e : ExecutionException) { + finish() + print("相机初始化失败", e) + } catch (e : InterruptedException) { + finish() + print("相机初始化失败", e) + } + }, ContextCompat.getMainExecutor(this)) + } - private fun initLocation() { - val locationManager = ContextCompat.getSystemService(this, LocationManager::class.java) - if ((ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA), 102) - } else { - if (locationManager != null) { - location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) - } - } - } + private fun initLocation() { + val locationManager = ContextCompat.getSystemService(this, LocationManager::class.java) + if ((ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) && ActivityCompat.checkSelfPermission( + this, + Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + this, + Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( + this, + Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED + ) { + ActivityCompat.requestPermissions(this, + arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA), + 102) + } else { + if (locationManager != null) { + location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) + } + } + } - @SuppressLint("RtlHardcoded") - private fun showTapView(x: Int, y: Int) { - if (takePhoto?.visibility == View.GONE) { - return - } - try { - val popupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) - popupWindow.width = 200 - popupWindow.height = 200 - val imageView = ImageView(this) - imageView.setImageResource(R.drawable.focus_focusing) - imageView.scaleType = ImageView.ScaleType.CENTER_CROP - popupWindow.contentView = imageView - popupWindow.showAtLocation(rootView, Gravity.LEFT or Gravity.TOP, x, y) - viewFinder?.postDelayed({ popupWindow.dismiss() }, 1000) - viewFinder?.playSoundEffect(SoundEffectConstants.CLICK) - } catch (e: Exception) { - print("zdCameraX showTapView", e) - } - } + @SuppressLint("RtlHardcoded") + private fun showTapView(x : Int, y : Int) { + if (takePhoto?.visibility == View.GONE) { + return + } + try { + val popupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT) + popupWindow.width = 200 + popupWindow.height = 200 + val imageView = ImageView(this) + imageView.setImageResource(R.drawable.focus_focusing) + imageView.scaleType = ImageView.ScaleType.CENTER_CROP + popupWindow.contentView = imageView + popupWindow.showAtLocation(rootView, Gravity.LEFT or Gravity.TOP, x, y) + viewFinder?.postDelayed({ popupWindow.dismiss() }, 1000) + viewFinder?.playSoundEffect(SoundEffectConstants.CLICK) + } catch (e : Exception) { + print("zdCameraX showTapView", e) + } + } - @SuppressLint("RtlHardcoded", "SetTextI18n") - private fun showExposureView() { - if (takePhoto?.visibility == View.GONE) { - return - } - exposurePopupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) - exposurePopupWindow?.width = 300 - exposurePopupWindow?.height = 200 - val textView = TextView(this) - textView.setTextColor(Color.YELLOW) - textView.textSize = 50f - textView.tag = "tv_exposureView" - textView.gravity = Gravity.CENTER - textView.text = exposureState?.exposureCompensationIndex.toString() + "" - exposurePopupWindow?.contentView = textView - exposurePopupWindow?.showAtLocation(rootView, Gravity.CENTER, 0, 0) - } + @SuppressLint("RtlHardcoded", "SetTextI18n") + private fun showExposureView() { + if (takePhoto?.visibility == View.GONE) { + return + } + exposurePopupWindow = + PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + exposurePopupWindow?.width = 300 + exposurePopupWindow?.height = 200 + val textView = TextView(this) + textView.setTextColor(Color.YELLOW) + textView.textSize = 50f + textView.tag = "tv_exposureView" + textView.gravity = Gravity.CENTER + textView.text = exposureState?.exposureCompensationIndex.toString() + "" + exposurePopupWindow?.contentView = textView + exposurePopupWindow?.showAtLocation(rootView, Gravity.CENTER, 0, 0) + } - @SuppressLint("RtlHardcoded") - private fun showFlashView() { - if (flashPopWindow != null) { - flashPopWindow = null - } - flashPopWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) - @SuppressLint("InflateParams") val view = LayoutInflater.from(this).inflate(R.layout.item_flash_mode, null) - val tvFlashAuto = view.findViewById(R.id.tvFlashAuto) - val tvFlashOpen = view.findViewById(R.id.tvFlashOpen) - val tvFlashLight = view.findViewById(R.id.tvFlashLight) - val tvFlashClose = view.findViewById(R.id.tvFlashClose) + @SuppressLint("RtlHardcoded") + private fun showFlashView() { + if (flashPopWindow != null) { + flashPopWindow = null + } + flashPopWindow = + PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + @SuppressLint("InflateParams") val view = + LayoutInflater.from(this).inflate(R.layout.item_flash_mode, null) + val tvFlashAuto = view.findViewById(R.id.tvFlashAuto) + val tvFlashOpen = view.findViewById(R.id.tvFlashOpen) + val tvFlashLight = view.findViewById(R.id.tvFlashLight) + val tvFlashClose = view.findViewById(R.id.tvFlashClose) - when (flashMode) { - FlashMode.auto -> tvFlashAuto.setTextColor(Color.YELLOW) - FlashMode.open -> tvFlashOpen.setTextColor(Color.YELLOW) - FlashMode.light -> tvFlashLight.setTextColor(Color.YELLOW) - FlashMode.close -> tvFlashClose.setTextColor(Color.YELLOW) - } - tvFlashAuto.setOnClickListener { v: View? -> - if (imageCapture != null) { - camera?.cameraControl?.enableTorch(false) - imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO - ivFlash?.setImageResource(R.drawable.picture_ic_flash_auto) - flashMode = FlashMode.auto - } - flashPopWindow?.dismiss() - } - tvFlashOpen.setOnClickListener { v: View? -> - if (imageCapture != null) { - camera?.cameraControl?.enableTorch(false) - imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON - ivFlash?.setImageResource(R.drawable.picture_ic_flash_on) - flashMode = FlashMode.open - } - flashPopWindow?.dismiss() - } + when (flashMode) { + FlashMode.auto -> tvFlashAuto.setTextColor(Color.YELLOW) + FlashMode.open -> tvFlashOpen.setTextColor(Color.YELLOW) + FlashMode.light -> tvFlashLight.setTextColor(Color.YELLOW) + FlashMode.close -> tvFlashClose.setTextColor(Color.YELLOW) + } + tvFlashAuto.setOnClickListener { v : View? -> + if (imageCapture != null) { + camera?.cameraControl?.enableTorch(false) + imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO + ivFlash?.setImageResource(R.drawable.picture_ic_flash_auto) + flashMode = FlashMode.auto + } + flashPopWindow?.dismiss() + } + tvFlashOpen.setOnClickListener { v : View? -> + if (imageCapture != null) { + camera?.cameraControl?.enableTorch(false) + imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON + ivFlash?.setImageResource(R.drawable.picture_ic_flash_on) + flashMode = FlashMode.open + } + flashPopWindow?.dismiss() + } - tvFlashLight.setOnClickListener { v: View? -> - if (camera != null) { - camera?.cameraControl?.enableTorch(true) - ivFlash?.setImageResource(R.drawable.ic_flash_light) - flashMode = FlashMode.light - } - flashPopWindow?.dismiss() - } + tvFlashLight.setOnClickListener { v : View? -> + if (camera != null) { + camera?.cameraControl?.enableTorch(true) + ivFlash?.setImageResource(R.drawable.ic_flash_light) + flashMode = FlashMode.light + } + flashPopWindow?.dismiss() + } - tvFlashClose.setOnClickListener { v: View? -> - if (imageCapture != null) { - camera?.cameraControl?.enableTorch(false) - imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF - ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) - flashMode = FlashMode.close - } - flashPopWindow?.dismiss() - } + tvFlashClose.setOnClickListener { v : View? -> + if (imageCapture != null) { + camera?.cameraControl?.enableTorch(false) + imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF + ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) + flashMode = FlashMode.close + } + flashPopWindow?.dismiss() + } - flashPopWindow?.contentView = view - flashPopWindow?.showAtLocation(ivFlash, Gravity.LEFT or Gravity.TOP, 0, ivFlash?.y?.toInt()?.minus(view.height) - ?: 0) - } + flashPopWindow?.contentView = view + flashPopWindow?.showAtLocation(ivFlash, + Gravity.LEFT or Gravity.TOP, + 0, + ivFlash?.y?.toInt()?.minus(view.height) ?: 0) + } - override fun onPause() { - super.onPause() - if (camera != null && imageCapture != null) { - camera?.cameraControl?.enableTorch(false) - imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF - ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) - } - } + override fun onPause() { + super.onPause() + if (camera != null && imageCapture != null) { + camera?.cameraControl?.enableTorch(false) + imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF + ivFlash?.setImageResource(R.drawable.picture_ic_flash_off) + } + } - override fun onStart() { - super.onStart() - orientationEventListener?.enable() - } + override fun onStart() { + super.onStart() + orientationEventListener?.enable() + } - override fun onStop() { - super.onStop() - orientationEventListener?.disable() - } + override fun onStop() { + super.onStop() + orientationEventListener?.disable() + } - override fun onDestroy() { - super.onDestroy() - cameraExecutor?.shutdown() - } + override fun onDestroy() { + super.onDestroy() + cameraExecutor?.shutdown() + } } \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/main/ServiceLauncherActivity.kt b/servicing/src/main/java/com/za/ui/main/ServiceLauncherActivity.kt index a4469f8..38126fc 100644 --- a/servicing/src/main/java/com/za/ui/main/ServiceLauncherActivity.kt +++ b/servicing/src/main/java/com/za/ui/main/ServiceLauncherActivity.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.tooling.preview.Preview import coil.compose.AsyncImage import com.blankj.utilcode.util.ToastUtils import com.permissionx.guolindev.PermissionX @@ -195,6 +196,7 @@ class ServiceLauncherActivity : BaseActivity() { } } +@Preview @Composable private fun LauncherScreen() { Scaffold { paddingValues -> diff --git a/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt b/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt index 9ef1a56..ff71163 100644 --- a/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt +++ b/servicing/src/main/java/com/za/ui/main/ServicingMainActivity.kt @@ -2,22 +2,65 @@ package com.za.ui.main import android.content.Context import android.content.Intent +import androidx.compose.foundation.background +import androidx.compose.foundation.basicMarquee +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Done +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.blankj.utilcode.util.ActivityUtils import com.za.base.BaseActivity +import com.za.base.theme.bgColor +import com.za.base.view.CommonButton +import com.za.base.view.HeadView +import com.za.bean.db.order.OrderInfo import com.za.common.GlobalData import com.za.common.util.DeviceUtil +import com.za.ext.convertToFlowName +import com.za.ext.copy import com.za.ext.finish import com.za.ext.goStatusPage import com.za.service.ServiceManager import com.za.service.location.ZdLocationManager +import com.za.servicing.R import kotlinx.coroutines.launch class ServicingMainActivity : BaseActivity() { @@ -59,8 +102,8 @@ private fun ServicingMainScreen(jobCode : String? = null, rescueVehicle : String? = null, vm : ServicingMainVm = viewModel()) { val uiState = vm.uiState.collectAsStateWithLifecycle() - val context = LocalContext.current val scope = rememberCoroutineScope() + val context = LocalContext.current LaunchedEffect(Unit) { vm.dispatch(ServicingMainVm.Action.Init(jobCode, @@ -75,12 +118,200 @@ private fun ServicingMainScreen(jobCode : String? = null, } } - if (uiState.value.state == 2) { - Box { - Text(text = "加载失败") + Scaffold(topBar = { HeadView("订单信息确认", onBack = { context.finish() }) }, bottomBar = { + if (uiState.value.state == 1) { + CommonButton(text = "已确认,去服务") { + GlobalData.currentOrder?.goStatusPage(ActivityUtils.getTopActivity()) + } + } + }) { + Box(modifier = Modifier + .fillMaxSize() + .background(bgColor) + .padding(it)) { + if (uiState.value.state == 2) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CommonButton(text = "订单获取异常,点击重新获取") { + vm.dispatch(ServicingMainVm.Action.Init(jobCode, + phone, + taskCode, + vehicleId, + deviceId, + rescueVehicle)) + } + } + } else { + Box(modifier = Modifier + .fillMaxSize() + .padding(top = 10.dp), + contentAlignment = Alignment.TopCenter) { + OrderItemView(GlobalData.currentOrder) + } + } } - } else { - GlobalData.currentOrder?.goStatusPage(ActivityUtils.getTopActivity()) } - } + +@Composable +private fun OrderItemView(orderInfo : OrderInfo?) { + val context = LocalContext.current + + Card(modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp, vertical = 5.dp), + shape = RoundedCornerShape(16.dp), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp, hoveredElevation = 4.dp), + colors = CardDefaults.cardColors(containerColor = Color.White)) { + Column(modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp)) { // 订单头部 + Row(modifier = Modifier + .fillMaxWidth() + .background(brush = Brush.linearGradient(colors = listOf(Color(0xFFF5F9FF), + Color(0xFFEDF4FF)), + start = androidx.compose.ui.geometry.Offset(0f, 0f), + end = androidx.compose.ui.geometry.Offset(Float.POSITIVE_INFINITY, 0f)), + shape = RoundedCornerShape(12.dp)) + .padding(horizontal = 12.dp, vertical = 10.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically) { + Row(verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Text(text = orderInfo?.taskCode ?: "", + fontSize = 15.sp, + fontWeight = FontWeight.Bold, + color = Color(0xFF1A1A1A)) + + Icon(painter = painterResource(R.drawable.sv_copy), + contentDescription = "复制", + modifier = Modifier + .size(25.dp) + .clickable { + orderInfo?.taskCode?.copy(context) + }, + tint = Color(0xFF666666)) + } + Button(onClick = { + + }, + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFFF5A2C)), + contentPadding = PaddingValues(horizontal = 14.dp, vertical = 2.dp), + shape = RoundedCornerShape(16.dp), + modifier = Modifier.height(28.dp)) { + Text(text = orderInfo?.convertToFlowName() ?: "", + fontSize = 13.sp, + fontWeight = FontWeight.Medium) + } + } + + // 车辆位于 + if (! orderInfo?.addressProperty.isNullOrBlank()) { + Row(modifier = Modifier + .fillMaxWidth() + .background(color = Color(0xFFF8F9FA), shape = RoundedCornerShape(10.dp)) + .padding(vertical = 12.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically) { + Icon(painter = rememberVectorPainter(image = Icons.Default.Menu), + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = Color(0xFF3364B7)) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "服务类型:", fontSize = 13.sp, color = Color(0x802F3059)) + Spacer(modifier = Modifier.weight(1f)) + Text(text = orderInfo?.serviceTypeName ?: "", + fontSize = 15.sp, + fontWeight = FontWeight.SemiBold, + color = Color(0xFF2F3059)) + } + } + + // 车牌信息 + if (! orderInfo?.plateNumber.isNullOrBlank()) { + Row(modifier = Modifier + .fillMaxWidth() + .background(color = Color(0xFFF8F9FA), shape = RoundedCornerShape(10.dp)) + .padding(vertical = 12.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically) { + Icon(painter = painterResource(id = R.drawable.sv_map_marker_driver), + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = Color(0xFF3364B7)) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = "车牌号:", fontSize = 13.sp, color = Color(0x802F3059)) + Spacer(modifier = Modifier.weight(1f)) + Text(text = orderInfo?.plateNumber ?: "", + fontSize = 15.sp, + fontWeight = FontWeight.SemiBold, + color = Color(0xFF2F3059)) + } + } + + // 地址信息容器 + Column(modifier = Modifier + .fillMaxWidth() + .background(color = Color(0xFFFAFBFC), shape = RoundedCornerShape(12.dp)) + .padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { // 救援地址信息 + AddressItem(icon = { + Box(modifier = Modifier + .size(10.dp) + .background(Color(0xFFFD8205), CircleShape)) + }, label = "救援地", address = orderInfo?.address ?: "") + + // 只有当目的地不为空时才显示分割线和目的地信息 + if (! orderInfo?.distAddress.isNullOrBlank()) { + HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp), + color = Color(0xFFEEEEEE)) + + AddressItem(icon = { + Box(modifier = Modifier + .size(10.dp) + .background(Color(0xFF5CC4BF), CircleShape)) + }, label = "目的地", address = orderInfo?.distAddress ?: "") + } + } + + //重要提示 + if (! orderInfo?.importantTip.isNullOrBlank()) { // 订单状态 + Box(modifier = Modifier + .fillMaxWidth() + .background(brush = Brush.linearGradient(colors = listOf(Color(0xFFFFF3E0), + Color(0xFFFFE0B2)), + start = androidx.compose.ui.geometry.Offset(0f, 0f), + end = androidx.compose.ui.geometry.Offset(Float.POSITIVE_INFINITY, 0f)), + shape = RoundedCornerShape(10.dp)) + .padding(12.dp), + contentAlignment = Alignment.Center) { + Text(text = orderInfo?.importantTip ?: "", + color = Color(0xFFFF5722), + fontSize = 15.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.basicMarquee()) + } + } + } + } +} + +@Composable +private fun AddressItem(icon : @Composable () -> Unit, label : String, address : String) { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Row(verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp)) { + icon() + Text(text = label, fontSize = 13.sp, color = Color(0x802F3059)) + } + + Text(text = address, + fontSize = 15.sp, + color = Color(0xFF2F3059), + fontWeight = FontWeight.Medium, + modifier = Modifier.padding(start = 18.dp)) + } +} + +@Preview +@Composable +private fun ServiceMainPreview() { + ServicingMainScreen() +} \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/main/ServicingMainVm.kt b/servicing/src/main/java/com/za/ui/main/ServicingMainVm.kt index 585b418..7547d96 100644 --- a/servicing/src/main/java/com/za/ui/main/ServicingMainVm.kt +++ b/servicing/src/main/java/com/za/ui/main/ServicingMainVm.kt @@ -48,6 +48,9 @@ class ServicingMainVm : BaseVm( LoadingManager.hideLoading() GlobalData.currentOrder = orderInfo updateState(uiState.value.copy(state = 1)) + if (orderInfos.isNullOrEmpty()) { + ToastUtils.showShort("未查询到订单") + } }, failed = { updateState(uiState.value.copy(state = 2)) diff --git a/servicing/src/main/java/com/za/ui/new_order/NewOrderActivity.kt b/servicing/src/main/java/com/za/ui/new_order/NewOrderActivity.kt index cb0dbaa..57ee864 100644 --- a/servicing/src/main/java/com/za/ui/new_order/NewOrderActivity.kt +++ b/servicing/src/main/java/com/za/ui/new_order/NewOrderActivity.kt @@ -57,7 +57,6 @@ import coil.compose.AsyncImage import com.amap.api.location.AMapLocationClient import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.MapView -import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MarkerOptions diff --git a/servicing/src/main/java/com/za/ui/servicing/order_give_up/OrderGiveUpActivity.kt b/servicing/src/main/java/com/za/ui/servicing/order_give_up/OrderGiveUpActivity.kt index 8971fc5..5e86e05 100644 --- a/servicing/src/main/java/com/za/ui/servicing/order_give_up/OrderGiveUpActivity.kt +++ b/servicing/src/main/java/com/za/ui/servicing/order_give_up/OrderGiveUpActivity.kt @@ -43,102 +43,124 @@ import com.za.ui.view.SignatureView class OrderGiveUpActivity : BaseActivity() { - @Composable - override fun ContentView() { - val orderInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent.getParcelableExtra("orderInfo", OrderInfo::class.java) - } else { - intent.getParcelableExtra("orderInfo") - } + @Composable + override fun ContentView() { + val orderInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getParcelableExtra("orderInfo", OrderInfo::class.java) + } else { + intent.getParcelableExtra("orderInfo") + } - OrderGiveUpScreen(orderInfo = orderInfo, taskId = intent.getIntExtra("taskId", 0), giveUpType = intent.getIntExtra("giveUpType", 0)) - } + OrderGiveUpScreen(orderInfo = orderInfo, + taskId = intent.getIntExtra("taskId", 0), + giveUpType = intent.getIntExtra("giveUpType", 0)) + } - companion object { - //giveUp type - //0 师傅手机操作放弃 1 后台操作放弃 2 师傅出发前后台操作放弃 - fun goOrderGiveUpActivity(context: Context, - orderInfo: OrderInfo? = null, - taskId: Int? = null, - giveUpType: Int) { - val intent = Intent(context, OrderGiveUpActivity::class.java) - intent.putExtra("giveUpType", giveUpType) - intent.putExtra("orderInfo", orderInfo) - intent.putExtra("taskId", taskId) - context.startActivity(intent) - } - } + companion object { + //giveUp type + //0 师傅手机操作放弃 1 后台操作放弃 2 师傅出发前后台操作放弃 + fun goOrderGiveUpActivity(context : Context, + orderInfo : OrderInfo? = null, + taskId : Int? = null, + userOrderId : Int? = null, + giveUpType : Int) { + val intent = Intent(context, OrderGiveUpActivity::class.java) + intent.putExtra("giveUpType", giveUpType) + intent.putExtra("orderInfo", orderInfo) + intent.putExtra("taskId", taskId) + intent.putExtra("userOrderId", userOrderId) + context.startActivity(intent) + } + } } @Composable -fun OrderGiveUpScreen(vm: OrderGiveUpVm = viewModel(), orderInfo: OrderInfo?, taskId: Int, giveUpType: Int) { - val uiState = vm.uiState.collectAsStateWithLifecycle() - val context = LocalContext.current +fun OrderGiveUpScreen(vm : OrderGiveUpVm = viewModel(), + orderInfo : OrderInfo?, + taskId : Int, + giveUpType : Int) { + val uiState = vm.uiState.collectAsStateWithLifecycle() + val context = LocalContext.current - LaunchedEffect(key1 = Unit) { - vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(orderInfo = orderInfo, taskId = taskId, giveUpType = giveUpType))) - vm.dispatch(OrderGiveUpVm.Action.Init) - } + LaunchedEffect(key1 = Unit) { + vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(orderInfo = orderInfo, + taskId = taskId, + giveUpType = giveUpType))) + vm.dispatch(OrderGiveUpVm.Action.Init) + } - if (uiState.value.orderGiveUpSuccess == true) { - context.finish() - } + if (uiState.value.orderGiveUpSuccess == true) { + context.finish() + } - if (uiState.value.isGoNextPageDialog == true) { - CommonDialog(cancelText = "取消", confirmText = "是否确认放弃订单", title = "放弃订单", cancelEnable = true, cancel = { - vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) - }, dismiss = { - vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) - }, confirm = { - vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) - vm.dispatch(OrderGiveUpVm.Action.UpdateTask) - }) - } + if (uiState.value.isGoNextPageDialog == true) { + CommonDialog(cancelText = "取消", + confirmText = "是否确认放弃订单", + title = "放弃订单", + cancelEnable = true, + cancel = { + vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) + }, + dismiss = { + vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) + }, + confirm = { + vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) + vm.dispatch(OrderGiveUpVm.Action.UpdateTask) + }) + } - Scaffold(topBar = { - HeadView(title = "放弃信息", onBack = { context.finish() }) - }, bottomBar = { - CommonButton(text = "提交信息,确认放弃案件") { - vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = true))) - } - }) { it -> - LazyColumn(modifier = Modifier - .fillMaxSize() - .padding(it), contentPadding = PaddingValues(10.dp)) { + Scaffold(topBar = { + HeadView(title = "放弃信息", onBack = { context.finish() }) + }, bottomBar = { + CommonButton(text = "提交信息,确认放弃案件") { + vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = true))) + } + }) { it -> + LazyColumn(modifier = Modifier + .fillMaxSize() + .padding(it), + contentPadding = PaddingValues(10.dp)) { - itemsIndexed(items = uiState.value.photoTemplateList - ?: arrayListOf(), key = { _, item -> item.hashCode() }) { index: Int, item: PhotoTemplateInfo -> - InServicingPhotoView(photoTemplateInfo = item, index = index + 1, success = { - vm.dispatch(OrderGiveUpVm.Action.UpdatePhotoTemplate(it)) - }) - Spacer(modifier = Modifier.height(10.dp)) - } + itemsIndexed(items = uiState.value.photoTemplateList ?: arrayListOf(), + key = { _, item -> item.hashCode() }) { index : Int, item : PhotoTemplateInfo -> + InServicingPhotoView(photoTemplateInfo = item, index = index + 1, success = { + vm.dispatch(OrderGiveUpVm.Action.UpdatePhotoTemplate(it)) + }) + Spacer(modifier = Modifier.height(10.dp)) + } - if (uiState.value.giveUpType == 0) { - item { - Spacer(modifier = Modifier.height(10.dp)) - Column(modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 10.dp) - .background(color = Color.White, shape = RoundedCornerShape(6.dp)) - .padding(10.dp)) { + if (uiState.value.giveUpType == 0) { + item { + Spacer(modifier = Modifier.height(10.dp)) + Column(modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp) + .background(color = Color.White, shape = RoundedCornerShape(6.dp)) + .padding(10.dp)) { - Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text(text = "司机签名", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) - Spacer(Modifier.weight(1f)) - AsyncImage(model = R.drawable.sv_sign_new, contentDescription = "", modifier = Modifier.size(20.dp)) - } + Row(modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically) { + Text(text = "司机签名", + color = Color.Black, + fontWeight = FontWeight.Medium, + fontSize = 14.sp) + Spacer(Modifier.weight(1f)) + AsyncImage(model = R.drawable.sv_sign_new, + contentDescription = "", + modifier = Modifier.size(20.dp)) + } - Spacer(modifier = Modifier.height(10.dp)) - SignatureView(modifier = Modifier - .fillMaxWidth() - .height(122.dp), success = { - vm.dispatch(OrderGiveUpVm.Action.UploadSign(it)) - }, serverPath = uiState.value.serverServicePeopleSignPath) - } - } - } - } - } + Spacer(modifier = Modifier.height(10.dp)) + SignatureView(modifier = Modifier + .fillMaxWidth() + .height(122.dp), success = { + vm.dispatch(OrderGiveUpVm.Action.UploadSign(it)) + }, serverPath = uiState.value.serverServicePeopleSignPath) + } + } + } + } + } } \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/servicing/view/InServicingBottomView.kt b/servicing/src/main/java/com/za/ui/servicing/view/InServicingBottomView.kt index 32d5e6d..69497fc 100644 --- a/servicing/src/main/java/com/za/ui/servicing/view/InServicingBottomView.kt +++ b/servicing/src/main/java/com/za/ui/servicing/view/InServicingBottomView.kt @@ -46,186 +46,287 @@ import com.za.ui.servicing.order_give_up.OrderGiveUpActivity @OptIn(ExperimentalMaterial3Api::class) @Composable -fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: OrderInfo?, isCanBack: Boolean = true) { - val context = LocalContext.current - val showBottomSheetDialog = remember { mutableStateOf(false) } - val showNavigationDialog = remember { mutableStateOf(false) } - val showCallPhoneDialog = remember { mutableStateOf(false) } +fun InServicingHeadView(title : String, + onBack : () -> Unit = {}, + orderInfo : OrderInfo?, + isCanBack : Boolean = true) { + val context = LocalContext.current + val showBottomSheetDialog = remember { mutableStateOf(false) } + val showNavigationDialog = remember { mutableStateOf(false) } + val showCallPhoneDialog = remember { mutableStateOf(false) } + val showCallServicePhoneDialog = remember { mutableStateOf(false) } - if (showNavigationDialog.value) { - StartNavigationView(orderInfo = orderInfo, dismiss = { showNavigationDialog.value = false }) - } + if (showNavigationDialog.value) { + StartNavigationView(orderInfo = orderInfo, dismiss = { showNavigationDialog.value = false }) + } - if (showCallPhoneDialog.value) { - CommonDialog( - cancelText = "取消", - confirmText = "确定", - title = "是否联系客户?", - cancelEnable = true, - cancel = { - showCallPhoneDialog.value = false - }, - dismiss = { showCallPhoneDialog.value = false }, - confirm = { - showCallPhoneDialog.value = false - context.callPhone(orderInfo?.customerPhone) - context.finish() - }) - } + if (showCallPhoneDialog.value) { + CommonDialog(cancelText = "取消", + confirmText = "确定", + title = "是否联系客户?", + cancelEnable = true, + cancel = { + showCallPhoneDialog.value = false + }, + dismiss = { showCallPhoneDialog.value = false }, + confirm = { + showCallPhoneDialog.value = false + context.callPhone(orderInfo?.customerPhone) + context.finish() + }) + } + + if (showCallServicePhoneDialog.value) { + CommonDialog(cancelText = "取消", + confirmText = "确定", + title = "是否联系中道客服?", + cancelEnable = true, + cancel = { + showCallServicePhoneDialog.value = false + }, + dismiss = { showCallServicePhoneDialog.value = false }, + confirm = { + showCallServicePhoneDialog.value = false + context.callPhone(orderInfo?.hotline) + context.finish() + }) + } - if (showBottomSheetDialog.value) { - ModalBottomSheet(containerColor = Color.White, - onDismissRequest = { showBottomSheetDialog.value = false }) { - Column(modifier = Modifier - .fillMaxWidth() - .padding(10.dp)) { + if (showBottomSheetDialog.value) { + ModalBottomSheet(containerColor = Color.White, + onDismissRequest = { showBottomSheetDialog.value = false }) { + Column(modifier = Modifier + .fillMaxWidth() + .padding(10.dp)) { - if (!orderInfo?.customerReportImgs.isNullOrBlank()) { - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showBottomSheetDialog.value = false - OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ON_SITE_PHOTO) - }, contentAlignment = Alignment.Center) { - Text(text = "现场照片", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) - } - HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) - } + if (! orderInfo?.customerReportImgs.isNullOrBlank()) { + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + OrderRequirementsActivity.goOrderRequirementsActivity(context, + orderInfo, + type = Const.InServiceSettingType.ON_SITE_PHOTO) + }, contentAlignment = Alignment.Center) { + Text(text = "现场照片", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + } - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showNavigationDialog.value = true - showBottomSheetDialog.value = false - }, contentAlignment = Alignment.Center) { - Text(text = "开启外部导航", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) - } - HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showNavigationDialog.value = true + showBottomSheetDialog.value = false + }, contentAlignment = Alignment.Center) { + Text(text = "开启外部导航", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showBottomSheetDialog.value = false - OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ORDER_REQUIREMENTS) - }, contentAlignment = Alignment.Center) { - Text(text = "案件要求", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) - } - HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + OrderRequirementsActivity.goOrderRequirementsActivity(context, + orderInfo, + type = Const.InServiceSettingType.ORDER_REQUIREMENTS) + }, contentAlignment = Alignment.Center) { + Text(text = "案件要求", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showBottomSheetDialog.value = false - OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ORDER_DETAIL) - }, contentAlignment = Alignment.Center) { - Text(text = "案件详情", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) - } - HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + OrderRequirementsActivity.goOrderRequirementsActivity(context, + orderInfo, + type = Const.InServiceSettingType.ORDER_DETAIL) + }, contentAlignment = Alignment.Center) { + Text(text = "案件详情", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showBottomSheetDialog.value = false - OrderGiveUpActivity.goOrderGiveUpActivity(context, orderInfo = orderInfo, giveUpType = 0) - }, contentAlignment = Alignment.Center) { - Text(text = "订单放弃", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Red) - } - HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + OrderGiveUpActivity.goOrderGiveUpActivity(context, + orderInfo = orderInfo, + userOrderId = orderInfo?.userOrderId, + giveUpType = 0) + }, contentAlignment = Alignment.Center) { + Text(text = "订单放弃", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) - Box(modifier = Modifier - .fillMaxWidth() - .clickable { - showBottomSheetDialog.value = false - showCallPhoneDialog.value = true - }, contentAlignment = Alignment.Center) { - Text(text = "拨打电话", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) - } - Spacer(modifier = Modifier.height(10.dp)) + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + showCallPhoneDialog.value = true + }, contentAlignment = Alignment.Center) { + Text(text = "拨打客户电话", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } - } - } - } + HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) + + Box(modifier = Modifier + .fillMaxWidth() + .clickable { + showBottomSheetDialog.value = false + showCallServicePhoneDialog.value = true + }, contentAlignment = Alignment.Center) { + Text(text = "联系中道客服", + fontSize = 15.sp, + fontWeight = FontWeight.Medium, + color = Color.Black) + } + + Spacer(modifier = Modifier.height(10.dp)) + + } + } + } - CenterAlignedTopAppBar(modifier = Modifier - .fillMaxWidth() - .background(color = headBgColor) - .padding(top = headPadding), - colors = TopAppBarDefaults.centerAlignedTopAppBarColors().copy(containerColor = headBgColor, titleContentColor = Color.White), - title = { Text(text = title, fontSize = 15.sp, fontWeight = FontWeight.Medium) }, - navigationIcon = { - if (isCanBack) { - AsyncImage(model = R.drawable.sv_back, contentDescription = "", modifier = Modifier - .size(40.dp) - .clickable { onBack() } - .padding(10.dp)) - } - }, actions = { - Box(modifier = Modifier - .size(39.dp) - .clickable { showBottomSheetDialog.value = true } - .padding(10.dp), contentAlignment = Alignment.Center) { - AsyncImage(model = R.drawable.sv_setting, contentDescription = "", modifier = Modifier.fillMaxSize()) - } - }) + CenterAlignedTopAppBar(modifier = Modifier + .fillMaxWidth() + .background(color = headBgColor) + .padding(top = headPadding), + colors = TopAppBarDefaults.centerAlignedTopAppBarColors() + .copy(containerColor = headBgColor, titleContentColor = Color.White), + title = { Text(text = title, fontSize = 15.sp, fontWeight = FontWeight.Medium) }, + navigationIcon = { + if (isCanBack) { + AsyncImage(model = R.drawable.sv_back, + contentDescription = "", + modifier = Modifier + .size(40.dp) + .clickable { onBack() } + .padding(10.dp)) + } + }, + actions = { + Box(modifier = Modifier + .size(39.dp) + .clickable { showBottomSheetDialog.value = true } + .padding(10.dp), contentAlignment = Alignment.Center) { + AsyncImage(model = R.drawable.sv_setting, + contentDescription = "", + modifier = Modifier.fillMaxSize()) + } + }) } @Composable -fun StartNavigationView(orderInfo: OrderInfo?, dismiss: () -> Unit) { - val context = LocalContext.current +fun StartNavigationView(orderInfo : OrderInfo?, dismiss : () -> Unit) { + val context = LocalContext.current - Dialog(onDismissRequest = { dismiss() }) { - Row(modifier = Modifier - .fillMaxWidth() - .height(180.dp) - .background(color = Color.White, shape = RoundedCornerShape(8.dp)) - .padding(10.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceAround) { - if (MapUtil.isGdMapInstalled(context)) { - Column(modifier = Modifier.clickable { - if ("SENDTO" == orderInfo?.taskState) { - MapUtil.startNavigationGd(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) - } else { - MapUtil.startNavigationGd(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) - } - dismiss() - }) { - AsyncImage(model = R.drawable.sv_amap_icon, contentDescription = "", modifier = Modifier.size(60.dp)) - Spacer(modifier = Modifier.height(5.dp)) - Text(text = "高德地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) - } - } + Dialog(onDismissRequest = { dismiss() }) { + Row(modifier = Modifier + .fillMaxWidth() + .height(180.dp) + .background(color = Color.White, shape = RoundedCornerShape(8.dp)) + .padding(10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceAround) { + if (MapUtil.isGdMapInstalled(context)) { + Column(modifier = Modifier.clickable { + if ("SENDTO" == orderInfo?.taskState) { + MapUtil.startNavigationGd(context, + orderInfo.distLat, + lng = orderInfo.distLng, + address = orderInfo.distAddress) + } else { + MapUtil.startNavigationGd(context, + orderInfo?.lat, + lng = orderInfo?.lng, + address = orderInfo?.address) + } + dismiss() + }) { + AsyncImage(model = R.drawable.sv_amap_icon, + contentDescription = "", + modifier = Modifier.size(60.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "高德地图", + color = Color.Black, + fontWeight = FontWeight.Medium, + fontSize = 14.sp) + } + } - if (MapUtil.isBaiduMapInstalled(context)) { - Column(modifier = Modifier.clickable { - if ("SENDTO" == orderInfo?.taskState) { - MapUtil.startNavigationBd(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) - } else { - MapUtil.startNavigationBd(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) - } - dismiss() - }) { - AsyncImage(model = R.drawable.sv_baidu_icon, contentDescription = "", modifier = Modifier.size(60.dp)) - Spacer(modifier = Modifier.height(5.dp)) - Text(text = "百度地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) - } - } + if (MapUtil.isBaiduMapInstalled(context)) { + Column(modifier = Modifier.clickable { + if ("SENDTO" == orderInfo?.taskState) { + MapUtil.startNavigationBd(context, + orderInfo.distLat, + lng = orderInfo.distLng, + address = orderInfo.distAddress) + } else { + MapUtil.startNavigationBd(context, + orderInfo?.lat, + lng = orderInfo?.lng, + address = orderInfo?.address) + } + dismiss() + }) { + AsyncImage(model = R.drawable.sv_baidu_icon, + contentDescription = "", + modifier = Modifier.size(60.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "百度地图", + color = Color.Black, + fontWeight = FontWeight.Medium, + fontSize = 14.sp) + } + } - if (MapUtil.isTencentInstalled(context)) { - Column(modifier = Modifier.clickable { - if ("SENDTO" == orderInfo?.taskState) { - MapUtil.startNavigationTencent(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) - } else { - MapUtil.startNavigationTencent(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) - } - dismiss() - }) { - AsyncImage(model = R.drawable.sv_tencent_icon, contentDescription = "", modifier = Modifier.size(60.dp)) - Spacer(modifier = Modifier.height(5.dp)) - Text(text = "腾讯地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) - } - } - } - } + if (MapUtil.isTencentInstalled(context)) { + Column(modifier = Modifier.clickable { + if ("SENDTO" == orderInfo?.taskState) { + MapUtil.startNavigationTencent(context, + orderInfo.distLat, + lng = orderInfo.distLng, + address = orderInfo.distAddress) + } else { + MapUtil.startNavigationTencent(context, + orderInfo?.lat, + lng = orderInfo?.lng, + address = orderInfo?.address) + } + dismiss() + }) { + AsyncImage(model = R.drawable.sv_tencent_icon, + contentDescription = "", + modifier = Modifier.size(60.dp)) + Spacer(modifier = Modifier.height(5.dp)) + Text(text = "腾讯地图", + color = Color.Black, + fontWeight = FontWeight.Medium, + fontSize = 14.sp) + } + } + } + } } \ No newline at end of file diff --git a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt index 86e753c..b89a4eb 100644 --- a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt +++ b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartActivity.kt @@ -1,8 +1,12 @@ package com.za.ui.servicing.wait_to_start +import android.app.Activity +import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.Looper +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -55,476 +59,367 @@ import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.PolylineOptions +import com.blankj.utilcode.util.ToastUtils import com.za.base.BaseActivity import com.za.base.theme.headBgColor import com.za.base.view.CommonDialog import com.za.common.GlobalData +import com.za.common.log.LogUtil import com.za.common.util.ImageUtil import com.za.common.util.ServicingSpeechManager import com.za.ext.copy import com.za.ext.finish import com.za.ext.goNextPage import com.za.servicing.R +import com.za.ui.camera.ZdCameraXActivity import com.za.ui.servicing.view.InServicingHeadView class WaitToStartActivity : BaseActivity() { - @Composable - override fun ContentView() { - WaitToStartScreen() - } + @Composable + override fun ContentView() { + WaitToStartScreen() + } } @OptIn(ExperimentalMaterial3Api::class) @Composable -fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) { - val uiState = vm.uiState.collectAsStateWithLifecycle() - val context = LocalContext.current - val lifecycleOwner = LocalLifecycleOwner.current - val mapView = remember { MapView(context) } +fun WaitToStartScreen(vm : WaitToStartVm = viewModel()) { + val uiState = vm.uiState.collectAsStateWithLifecycle() + val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + val mapView = remember { MapView(context) } - // 添加 BottomSheet 状态 - val bottomSheetState = rememberStandardBottomSheetState( - initialValue = SheetValue.Expanded - ) - val scaffoldState = rememberBottomSheetScaffoldState( - bottomSheetState = bottomSheetState - ) + val getResult = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { it -> + if (it.resultCode == Activity.RESULT_OK) { + val value = it.data?.getStringExtra("path") + LogUtil.print("takePhoto", "path==$value") + if (value.isNullOrBlank()) { + ToastUtils.showLong("照片路径为空,请重新拍摄!") + return@rememberLauncherForActivityResult + } + vm.dispatch(WaitToStartVm.Action.CompareServicePeople(value)) + } + } - DisposableEffect(key1 = lifecycleOwner) { - val observer = LifecycleEventObserver { _, event -> - when (event) { - Lifecycle.Event.ON_CREATE -> { - mapView.onCreate(Bundle()) - vm.dispatch(WaitToStartVm.Action.Init) - ServicingSpeechManager.playStartTip(context) - } + // 添加 BottomSheet 状态 + val bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.Expanded) + val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) - Lifecycle.Event.ON_RESUME -> mapView.onResume() - Lifecycle.Event.ON_PAUSE -> mapView.onPause() - Lifecycle.Event.ON_DESTROY -> mapView.onDestroy() - else -> {} - } - } + DisposableEffect(key1 = lifecycleOwner) { + val observer = LifecycleEventObserver { _, event -> + when (event) { + Lifecycle.Event.ON_CREATE -> { + mapView.onCreate(Bundle()) + vm.dispatch(WaitToStartVm.Action.Init) + ServicingSpeechManager.playStartTip(context) + } - lifecycleOwner.lifecycle.addObserver(observer) - onDispose { - lifecycleOwner.lifecycle.removeObserver(observer) - } - } + Lifecycle.Event.ON_RESUME -> mapView.onResume() + Lifecycle.Event.ON_PAUSE -> mapView.onPause() + Lifecycle.Event.ON_DESTROY -> mapView.onDestroy() + else -> {} + } + } - if (uiState.value.goNextPage != null) { - goNextPage(uiState.value.goNextPage?.nextState, context) - } + lifecycleOwner.lifecycle.addObserver(observer) + onDispose { + lifecycleOwner.lifecycle.removeObserver(observer) + } + } - if (uiState.value.isGoNextPageDialog == true) { - CommonDialog( - cancelText = "取消", - confirmText = "前往下一步", - title = "是否前往下一步?", - cancelEnable = true, - cancel = { - vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) - }, - dismiss = { vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) }, - confirm = { - vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) - vm.dispatch(WaitToStartVm.Action.UpdateTask) - } - ) - } + if (uiState.value.goNextPage != null) { + goNextPage(uiState.value.goNextPage?.nextState, context) + vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(goNextPage = null))) + } - BottomSheetScaffold( - scaffoldState = scaffoldState, - topBar = { - InServicingHeadView( - title = "调度成功,等待发车", - onBack = { context.finish() }, - orderInfo = uiState.value.orderInfo - ) - }, - sheetContent = { - Column( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .verticalScroll(rememberScrollState()) - ) { - // 滑动指示器 - Box( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), - contentAlignment = Alignment.Center - ) { - Box( - modifier = Modifier - .width(32.dp) - .height(4.dp) - .background( - color = Color(0xFFE0E0E0), - shape = RoundedCornerShape(2.dp) - ) - ) - } + if (uiState.value.showServicePeopleConfirmDialog == true) { + CommonDialog(cancelText = "取消", + confirmText = "去拍照", + title = "服务人员确认", + cancelEnable = true, + cancel = { + vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy( + showServicePeopleConfirmDialog = false))) + }, + dismiss = { + vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy( + showServicePeopleConfirmDialog = false))) + }, + confirm = { + vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy( + showServicePeopleConfirmDialog = false))) + val intent = Intent(context, ZdCameraXActivity::class.java) + intent.putExtra("isBack", false) + getResult.launch(intent) + }) + } - // 距离和时间信息 - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = if (uiState.value.estimatedArrivalTime.isNotEmpty()) - "预计到达: ${uiState.value.estimatedArrivalTime}" - else - "计算中...", - color = Color(0xFF666666), - fontSize = 14.sp - ) + BottomSheetScaffold(scaffoldState = scaffoldState, + topBar = { + InServicingHeadView(title = "调度成功,等待发车", + onBack = { context.finish() }, + orderInfo = uiState.value.orderInfo) + }, + sheetContent = { + Column(modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .verticalScroll(rememberScrollState())) { // 滑动指示器 + Box(modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + contentAlignment = Alignment.Center) { + Box(modifier = Modifier + .width(32.dp) + .height(4.dp) + .background(color = Color(0xFFE0E0E0), shape = RoundedCornerShape(2.dp))) + } - Text( - text = if (uiState.value.remainingDistance > 0) - "距离救援地: %.1fkm".format(uiState.value.remainingDistance / 1000f) - else - "计算中...", - color = Color(0xFFFF4D4F), - fontSize = 14.sp - ) - } + // 距离和时间信息 + Row(modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically) { + Text(text = if (uiState.value.estimatedArrivalTime.isNotEmpty()) "预计到达: ${uiState.value.estimatedArrivalTime}" + else "计算中...", color = Color(0xFF666666), fontSize = 14.sp) - HorizontalDivider( - modifier = Modifier - .fillMaxWidth() - .alpha(0.1f) - ) + Text(text = if (uiState.value.remainingDistance > 0) "距离救援地: %.1fkm".format( + uiState.value.remainingDistance / 1000f) + else "计算中...", color = Color(0xFFFF4D4F), fontSize = 14.sp) + } - // 订单信息 - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp) - ) { - // 订单类型 - Text( - text = uiState.value.orderInfo?.serviceTypeName ?: "", - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - color = Color.Black - ) + HorizontalDivider(modifier = Modifier + .fillMaxWidth() + .alpha(0.1f)) - Spacer(modifier = Modifier.height(8.dp)) + // 订单信息 + Column(modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp)) { // 订单类型 + Text(text = uiState.value.orderInfo?.serviceTypeName ?: "", + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + color = Color.Black) - // 订单标签 - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Box( - modifier = Modifier - .background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp)) - .padding(horizontal = 6.dp, vertical = 2.dp) - ) { - Text( - text = "月结".takeIf { uiState.value.orderInfo?.settleType == 1 } - ?: "现金", - color = Color.White, - fontSize = 12.sp - ) - } + Spacer(modifier = Modifier.height(8.dp)) - Text( - text = uiState.value.orderInfo?.orderSource ?: "", - color = Color.Black, - fontSize = 12.sp - ) + // 订单标签 + Row(verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Box(modifier = Modifier + .background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp)) + .padding(horizontal = 6.dp, vertical = 2.dp)) { + Text(text = "月结".takeIf { uiState.value.orderInfo?.settleType == 1 } + ?: "现金", color = Color.White, fontSize = 12.sp) + } - Text( - text = uiState.value.orderInfo?.addressProperty ?: "", - color = Color(0xFFFD8205), - fontSize = 12.sp, - fontWeight = FontWeight.Medium - ) - } + Text(text = uiState.value.orderInfo?.orderSource ?: "", + color = Color.Black, + fontSize = 12.sp) - Spacer(modifier = Modifier.height(12.dp)) + Text(text = uiState.value.orderInfo?.addressProperty ?: "", + color = Color(0xFFFD8205), + fontSize = 12.sp, + fontWeight = FontWeight.Medium) + } - // 订单号 - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.clickable { uiState.value.orderInfo?.taskCode?.copy(context) } - ) { - Text( - text = "单号", - color = Color(0xFF999999), - fontSize = 13.sp - ) + Spacer(modifier = Modifier.height(12.dp)) - Spacer(modifier = Modifier.width(8.dp)) + // 订单号 + Row(verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { + uiState.value.orderInfo?.taskCode?.copy(context) + }) { + Text(text = "单号", color = Color(0xFF999999), fontSize = 13.sp) - Text( - text = uiState.value.orderInfo?.taskCode ?: "", - color = Color(0xFF666666), - fontSize = 14.sp - ) + Spacer(modifier = Modifier.width(8.dp)) - Spacer(modifier = Modifier.width(8.dp)) + Text(text = uiState.value.orderInfo?.taskCode ?: "", + color = Color(0xFF666666), + fontSize = 14.sp) - AsyncImage( - model = R.drawable.sv_copy, - contentDescription = "copy", - modifier = Modifier.size(16.dp) - ) - } + Spacer(modifier = Modifier.width(8.dp)) - Spacer(modifier = Modifier.height(16.dp)) + AsyncImage(model = R.drawable.sv_copy, + contentDescription = "copy", + modifier = Modifier.size(16.dp)) + } - // 地址信息 - Column( - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - // 救援地 - Row( - verticalAlignment = Alignment.Top, - modifier = Modifier.clickable { - // 点击救援地时移动地图到救援位置 - uiState.value.orderInfo?.let { order -> - if (order.lat != null && order.lat != 0.0 && - order.lng != null && order.lng != 0.0 - ) { - mapView.map.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(order.lat!!, order.lng!!), - 16f - ) - ) - } - } - } - ) { - AsyncImage( - model = R.drawable.sv_rescuing, - contentDescription = "rescue", - modifier = Modifier.size(16.dp) - ) + Spacer(modifier = Modifier.height(16.dp)) - Spacer(modifier = Modifier.width(8.dp)) + // 地址信息 + Column(verticalArrangement = Arrangement.spacedBy(16.dp)) { // 救援地 + Row(verticalAlignment = Alignment.Top, + modifier = Modifier.clickable { // 点击救援地时移动地图到救援位置 + uiState.value.orderInfo?.let { order -> + if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0) { + mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom( + LatLng(order.lat !!, order.lng !!), + 16f)) + } + } + }) { + AsyncImage(model = R.drawable.sv_rescuing, + contentDescription = "rescue", + modifier = Modifier.size(16.dp)) - Text( - text = uiState.value.orderInfo?.address ?: "", - color = Color.Black, - fontSize = 15.sp, - fontWeight = FontWeight.Medium - ) - } + Spacer(modifier = Modifier.width(8.dp)) - // 目的地 - if (!uiState.value.orderInfo?.distAddress.isNullOrBlank()) { - Row( - verticalAlignment = Alignment.Top, - modifier = Modifier.clickable { - // 点击目的地时移动地图到目的地位置 - uiState.value.orderInfo?.let { order -> - if (order.distLat != null && order.distLat != 0.0 && - order.distLng != null && order.distLng != 0.0 - ) { - mapView.map.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(order.distLat!!, order.distLng!!), - 16f - ) - ) - } - } - } - ) { - AsyncImage( - model = R.drawable.sv_dist, - contentDescription = "destination", - modifier = Modifier.size(16.dp) - ) + Text(text = uiState.value.orderInfo?.address ?: "", + color = Color.Black, + fontSize = 15.sp, + fontWeight = FontWeight.Medium) + } - Spacer(modifier = Modifier.width(8.dp)) + // 目的地 + if (! uiState.value.orderInfo?.distAddress.isNullOrBlank()) { + Row(verticalAlignment = Alignment.Top, + modifier = Modifier.clickable { // 点击目的地时移动地图到目的地位置 + uiState.value.orderInfo?.let { order -> + if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0) { + mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom( + LatLng(order.distLat !!, order.distLng !!), + 16f)) + } + } + }) { + AsyncImage(model = R.drawable.sv_dist, + contentDescription = "destination", + modifier = Modifier.size(16.dp)) - Text( - text = uiState.value.orderInfo?.distAddress ?: "", - color = Color.Black, - fontSize = 15.sp, - fontWeight = FontWeight.Medium - ) - } - } - } + Spacer(modifier = Modifier.width(8.dp)) - Spacer(modifier = Modifier.height(16.dp)) + Text(text = uiState.value.orderInfo?.distAddress ?: "", + color = Color.Black, + fontSize = 15.sp, + fontWeight = FontWeight.Medium) + } + } + } - // 发车按钮 - Button( - onClick = { vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = true))) }, - modifier = Modifier - .fillMaxWidth() - .height(44.dp) - .padding(horizontal = 16.dp), - colors = ButtonDefaults.buttonColors( - containerColor = headBgColor - ), - shape = RoundedCornerShape(8.dp) - ) { - Text( - text = "发车", - color = Color.White, - fontSize = 16.sp, - fontWeight = FontWeight.Medium - ) - } + Spacer(modifier = Modifier.height(16.dp)) - Spacer(modifier = Modifier.height(16.dp)) - } - } - }, - sheetPeekHeight = 180.dp, - sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), - sheetContainerColor = Color.White, - sheetDragHandle = null, - sheetSwipeEnabled = true - ) { paddingValues -> - Box( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - ) { - AndroidView( - modifier = Modifier.fillMaxSize(), - factory = { - AMapLocationClient.updatePrivacyShow(context, true, true) - AMapLocationClient.updatePrivacyAgree(context, true) - mapView.apply { - map.apply { - isTrafficEnabled = false - isMyLocationEnabled = false - uiSettings.isMyLocationButtonEnabled = false - uiSettings.setLogoBottomMargin(-100) - uiSettings.isZoomControlsEnabled = false + // 发车按钮 + Button(onClick = { + vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy( + showServicePeopleConfirmDialog = true))) + }, + modifier = Modifier + .fillMaxWidth() + .height(44.dp) + .padding(horizontal = 16.dp), + colors = ButtonDefaults.buttonColors(containerColor = headBgColor), + shape = RoundedCornerShape(8.dp)) { + Text(text = "发车", + color = Color.White, + fontSize = 16.sp, + fontWeight = FontWeight.Medium) + } - // 修改标记点点击事件 - setOnMarkerClickListener { marker -> - marker.showInfoWindow() - // 800ms后隐藏信息窗口 - Handler(Looper.getMainLooper()).postDelayed({ - marker.hideInfoWindow() - }, 800) - true - } - } - } - }, - update = { - // 清除旧标记和路线 - mapView.map.clear() + Spacer(modifier = Modifier.height(16.dp)) + } + } + }, + sheetPeekHeight = 180.dp, + sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), + sheetContainerColor = Color.White, + sheetDragHandle = null, + sheetSwipeEnabled = true) { paddingValues -> + Box(modifier = Modifier + .fillMaxSize() + .padding(paddingValues)) { + AndroidView(modifier = Modifier.fillMaxSize(), factory = { + AMapLocationClient.updatePrivacyShow(context, true, true) + AMapLocationClient.updatePrivacyAgree(context, true) + mapView.apply { + map.apply { + isTrafficEnabled = false + isMyLocationEnabled = false + uiSettings.isMyLocationButtonEnabled = false + uiSettings.setLogoBottomMargin(- 100) + uiSettings.isZoomControlsEnabled = false - // 先绘制路线 - uiState.value.routePoints?.let { points -> - mapView.map.addPolyline( - PolylineOptions() - .addAll(points) - .width(15f) - .setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.icon_road_green_arrow)) - .zIndex(1f) - ) - } + // 修改标记点点击事件 + setOnMarkerClickListener { marker -> + marker.showInfoWindow() // 800ms后隐藏信息窗口 + Handler(Looper.getMainLooper()).postDelayed({ + marker.hideInfoWindow() + }, 800) + true + } + } + } + }, update = { // 清除旧标记和路线 + mapView.map.clear() - // 再添加标记点,确保标记点在路线上层 - // 添加当前位置标记 - if (GlobalData.currentLocation != null) { - mapView.map.addMarker( - MarkerOptions() - .position(LatLng( - GlobalData.currentLocation?.latitude!!, - GlobalData.currentLocation?.longitude!! - )) - .title("当前位置") - .icon(ImageUtil.vectorToBitmap(context,R.drawable.ic_current_location)) - .anchor(0.5f, 0.5f) - .visible(true) - ) - } + // 先绘制路线 + uiState.value.routePoints?.let { points -> + mapView.map.addPolyline(PolylineOptions().addAll(points).width(15f) + .setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.icon_road_green_arrow)) + .zIndex(1f)) + } - // 添加救援地标记 - uiState.value.orderInfo?.let { order -> - if (order.lat != null && order.lat != 0.0 && - order.lng != null && order.lng != 0.0 && - GlobalData.currentLocation != null - ) { - mapView.map.addMarker( - MarkerOptions() - .position(LatLng(order.lat!!, order.lng!!)) - .title("救援地点") - .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map)) - .anchor(0.5f, 0.5f) - ) - } + // 再添加标记点,确保标记点在路线上层 + // 添加当前位置标记 + if (GlobalData.currentLocation != null) { + mapView.map.addMarker(MarkerOptions().position(LatLng(GlobalData.currentLocation?.latitude !!, + GlobalData.currentLocation?.longitude !!)).title("当前位置") + .icon(ImageUtil.vectorToBitmap(context, R.drawable.ic_current_location)) + .anchor(0.5f, 0.5f).visible(true)) + } - // 添加目的地标记 - if (order.distLat != null && order.distLat != 0.0 && - order.distLng != null && order.distLng != 0.0 && - GlobalData.currentLocation != null - ) { - mapView.map.addMarker( - MarkerOptions() - .position(LatLng(order.distLat!!, order.distLng!!)) - .title("目的地") - .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map)) - .anchor(0.5f, 0.5f) - ) - } - } + // 添加救援地标记 + uiState.value.orderInfo?.let { order -> + if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0 && GlobalData.currentLocation != null) { + mapView.map.addMarker(MarkerOptions().position(LatLng(order.lat !!, + order.lng !!)).title("救援地点") + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map)) + .anchor(0.5f, 0.5f)) + } - // 最后调整地图显示范围 - // 计算地图显示范围 - val bounds = LatLngBounds.Builder().apply { - // 添加当前位置 - GlobalData.currentLocation?.let { - include(LatLng(it.latitude, it.longitude)) - } + // 添加目的地标记 + if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0 && GlobalData.currentLocation != null) { + mapView.map.addMarker(MarkerOptions().position(LatLng(order.distLat !!, + order.distLng !!)).title("目的地") + .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map)) + .anchor(0.5f, 0.5f)) + } + } - // 添加救援地点 - uiState.value.orderInfo?.let { order -> - if (order.lat != null && order.lat != 0.0 && - order.lng != null && order.lng != 0.0 - ) { - include(LatLng(order.lat!!, order.lng!!)) - } + // 最后调整地图显示范围 + // 计算地图显示范围 + val bounds = LatLngBounds.Builder().apply { // 添加当前位置 + GlobalData.currentLocation?.let { + include(LatLng(it.latitude, it.longitude)) + } - // 添加目的地 - if (order.distLat != null && order.distLat != 0.0 && - order.distLng != null && order.distLng != 0.0 - ) { - include(LatLng(order.distLat!!, order.distLng!!)) - } - } - }.build() + // 添加救援地点 + uiState.value.orderInfo?.let { order -> + if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0) { + include(LatLng(order.lat !!, order.lng !!)) + } - // 调整地图显示范围,确保所有点都可见 - try { - mapView.map.animateCamera( - CameraUpdateFactory.newLatLngBounds(bounds, 100) - ) - } catch (e: Exception) { - // 如果计算边界失败,则使用默认缩放级别 - GlobalData.currentLocation?.let { - mapView.map.animateCamera( - CameraUpdateFactory.newLatLngZoom( - LatLng(it.latitude, it.longitude), - 15f - ) - ) - } - } - } - ) - } - } + // 添加目的地 + if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0) { + include(LatLng(order.distLat !!, order.distLng !!)) + } + } + }.build() + + // 调整地图显示范围,确保所有点都可见 + try { + mapView.map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)) + } catch (e : Exception) { // 如果计算边界失败,则使用默认缩放级别 + GlobalData.currentLocation?.let { + mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(it.latitude, + it.longitude), 15f)) + } + } + }) + } + } } diff --git a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt index 65f7c87..ce6111c 100644 --- a/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt +++ b/servicing/src/main/java/com/za/ui/servicing/wait_to_start/WaitToStartVm.kt @@ -15,20 +15,27 @@ import com.blankj.utilcode.util.ToastUtils import com.za.base.IServicingVm import com.za.base.view.LoadingManager import com.za.bean.db.order.OrderInfo +import com.za.bean.request.DriverFaceCompareRequest +import com.za.bean.request.IaiCompareFaceBean import com.za.bean.request.UpdateTaskBean import com.za.bean.request.UpdateTaskRequest import com.za.common.GlobalData import com.za.common.log.LogUtil import com.za.ext.toJson +import com.za.net.BaseObserver import com.za.net.CommonMethod +import com.za.net.RetrofitHelper import com.za.service.location.ZdLocationManager import com.za.servicing.R +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import java.io.File import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -47,6 +54,7 @@ class WaitToStartVm : IServicingVm( is Action.UpdateState -> updateState(action.uiState) is Action.StartTimer -> startTimer() is Action.UpdateTimer -> updateTimer() + is Action.CompareServicePeople -> compareServicePeople(action.localPath) } } @@ -216,6 +224,52 @@ class WaitToStartVm : IServicingVm( private fun updateTimer() { // 在这里处理倒计时更新逻辑 } + private fun compareServicePeople(localPath : String) { + LoadingManager.showLoading() + CommonMethod.uploadImage(file = File(localPath), success = { it -> + compilePeople(it, success = { + LoadingManager.hideLoading() + updateTask() + }, failed = { + LoadingManager.hideLoading() + ToastUtils.showLong(it) + }) + }, failed = { + LoadingManager.hideLoading() + ToastUtils.showLong(it) + }) + } + + private fun compilePeople(url : String?, + success : (IaiCompareFaceBean?) -> Unit, + failed : (String) -> Unit) { + if (url.isNullOrBlank()) { + ToastUtils.showLong("图片路径为空!") + return + } + val driverFaceCompareRequest = + DriverFaceCompareRequest(vehicleId = GlobalData.driverInfoBean?.vehicleId, + driverId = GlobalData.driverInfoBean?.userId, + photoUrl = url) + RetrofitHelper.getDefaultService().iaiCompareFace(driverFaceCompareRequest) + .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BaseObserver() { + override fun doSuccess(it : IaiCompareFaceBean?) { + if (it?.compareResult == true) { + success(it) + return + } + failed("人脸对比失败") + LogUtil.print("face", "人脸对比成功:$it") + } + + override fun doFailure(code : Int, msg : String?) { + failed(msg ?: "人脸对比失败") + LogUtil.print("face", "人脸对比失败:$msg") + } + }) + } + override fun onCleared() { super.onCleared() timerJob?.cancel() @@ -227,14 +281,15 @@ class WaitToStartVm : IServicingVm( data class UpdateState(val uiState : UiState) : Action() data object StartTimer : Action() data object UpdateTimer : Action() + data class CompareServicePeople(val localPath : String) : Action() } data class UiState(val orderInfo : OrderInfo? = null, val showCallPhoneDialog : Boolean? = false, val markers : ArrayList? = null, val goNextPage : UpdateTaskBean? = null, - val isGoNextPageDialog : Boolean? = null, val routePoints : List? = null, val remainingDistance : Float = 0f, + val showServicePeopleConfirmDialog : Boolean? = false, val estimatedArrivalTime : String = "") } \ No newline at end of file diff --git a/servicing/src/main/res/drawable/sv_copy.xml b/servicing/src/main/res/drawable/sv_copy.xml index 4d6e94c..8888a3b 100644 --- a/servicing/src/main/res/drawable/sv_copy.xml +++ b/servicing/src/main/res/drawable/sv_copy.xml @@ -1,14 +1,14 @@ + android:width="128dp" + android:height="128dp" + android:viewportWidth="1024" + android:viewportHeight="1024"> + android:pathData="M675.9,265.9H388.9c-68,0 -123.1,55.1 -123.1,123.1v287c-53.3,-2.6 -82,-33.8 -82,-89.3V273.3c0,-58 31.5,-89.5 89.5,-89.5h313.3c55.5,0 86.7,28.8 89.3,82z" + android:strokeAlpha="0.3" + android:fillColor="#1A73E8" + android:fillAlpha="0.3"/> + diff --git a/servicing/src/main/res/values/strings.xml b/servicing/src/main/res/values/strings.xml index 14c78cd..f8bd39d 100644 --- a/servicing/src/main/res/values/strings.xml +++ b/servicing/src/main/res/values/strings.xml @@ -18,4 +18,5 @@ 9.拖车服务时,救援人员仅按照道路救援中心的指令,将车辆拖往指定目的地,如果顾客需要变更拖车目的地,请与道路救援中心联系。\n 10.顾客如果要求自费服务项目,请与第三方公司或人员协商相关费用并现场向其支付。因为此类服务发生任何争议,请与数援人员双方自行解决,救援中心不再介入和负责。\n 11.服务完成后客户接收车辆时,应再次签字确认服务完成及车辆无损,中道救援不接受客户己在服务完成记录中签字后的任何索赔和投诉:若接车方为维修站,且维修站接车员签字确认车辆无损,则事后发现的任何车辆损伤及相关责任应由维修站承担。如客户认为被救车辆损伤由中道救援服务商造成,应出具权威部门出具的检测报告,中道救援将根据检测报告确定服务商是否进行赔偿。 + ServicePeopleConfirmActivity \ No newline at end of file diff --git a/servicing/src/main/res/values/themes.xml b/servicing/src/main/res/values/themes.xml index 75deb6e..7f913ea 100644 --- a/servicing/src/main/res/values/themes.xml +++ b/servicing/src/main/res/values/themes.xml @@ -2,4 +2,6 @@