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 @@
+
+
\ No newline at end of file
diff --git a/zd_sdk_demo.jks b/zd_sdk_demo.jks
new file mode 100644
index 0000000..0571616
Binary files /dev/null and b/zd_sdk_demo.jks differ