feat(servicing): 新增快速登录功能并优化用户信息处理- 新增 FastLoginRequest 数据类用于快速登录

- 添加 iaiCompareFace API 接口用于人脸识别比较
- 更新 DriverInfo 数据类,增加 loginLogId 字段- 重构 GlobalData 中的用户信息存储逻辑,使用 MMKV替代数据库
- 优化 InServicingBottomView 中的订单放弃和拨打电话功能
- 更新 JpushBean,增加 userOrderId 字段
- 修改 AndroidManifest.xml 中的权限声明,使用动态应用ID
This commit is contained in:
songzhiling
2025-04-17 15:08:29 +08:00
parent 0f24648cb1
commit eb7a4585fa
30 changed files with 1626 additions and 1196 deletions

View File

@ -33,13 +33,22 @@ android {
] ]
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 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 { compileOptions {
sourceCompatibility JavaVersion.VERSION_11 sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11

View File

@ -27,7 +27,7 @@ class MainActivity : ComponentActivity() {
.fillMaxSize() .fillMaxSize()
.clickable { .clickable {
val uri = 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) val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent) startActivity(intent)
} }

View File

@ -13,7 +13,8 @@ jcore = "3.3.2"
jpush = "4.8.1" jpush = "4.8.1"
location = "5.6.1" location = "5.6.1"
loggingInterceptor = "4.11.0" loggingInterceptor = "4.11.0"
mmkv = "2.1.0" #这是一个长期维护的版本,不建议升级
mmkv = "1.3.11"
orgEclipsePahoAndroidService = "1.1.1" orgEclipsePahoAndroidService = "1.1.1"
orgEclipsePahoClientMqttv3 = "1.2.5" orgEclipsePahoClientMqttv3 = "1.2.5"
permissionx = "1.8.0" permissionx = "1.8.0"

View File

@ -3,8 +3,9 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-sdk tools:overrideLibrary="androidx.camera.view,androidx.camera:camera-camera2,androidx.camera.camera2,androidx.camera.lifecycle,androidx.camera.core" /> <uses-sdk tools:overrideLibrary="androidx.camera.view,androidx.camera:camera-camera2,androidx.camera.camera2,androidx.camera.lifecycle,androidx.camera.core" />
<permission <permission
android:name="com.za.rescue.dealer.permission.JPUSH_MESSAGE" android:name="${applicationId}.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" /> <!-- 位置相关权限 --> android:protectionLevel="signature" /> <!-- 位置相关权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
@ -78,9 +79,7 @@
<activity <activity
android:name="com.za.ui.main.ServiceLauncherActivity" android:name="com.za.ui.main.ServiceLauncherActivity"
android:exported="true" android:exported="true"
android:theme="@style/Theme.Dealer"> android:theme="@style/Theme.Dealer" />
</activity>
<activity <activity
android:name="com.za.ui.main.ServicingMainActivity" android:name="com.za.ui.main.ServicingMainActivity"
android:exported="false" android:exported="false"
@ -162,6 +161,7 @@
<activity <activity
android:name="com.za.ui.camera.ZdCameraXActivity" android:name="com.za.ui.camera.ZdCameraXActivity"
android:exported="false" android:exported="false"
android:theme="@style/Theme.Dealer"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
<meta-data <meta-data
android:name="android.app.lib_name" android:name="android.app.lib_name"
@ -202,7 +202,6 @@
android:exported="true" android:exported="true"
tools:node="replace"> tools:node="replace">
<intent-filter> <intent-filter>
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_ACTION" /> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_ACTION" />
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED_ACTION" /> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED_ACTION" />
<action android:name="cn.jpush.android.intent.CONNECTION" /> <action android:name="cn.jpush.android.intent.CONNECTION" />
@ -243,6 +242,7 @@
<category android:name="${applicationId}" /> <category android:name="${applicationId}" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<service <service
android:name="cn.jpush.android.service.DaemonService" android:name="cn.jpush.android.service.DaemonService"
android:enabled="true" android:enabled="true"

View File

@ -30,6 +30,7 @@ data class GeneralInfo(
val vehicleName : String? = null, val vehicleName : String? = null,
val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌 val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌
val supplierId : Int? = null, val supplierId : Int? = null,
val loginLogId : Int? = null,
val supplierName : String? = null, val supplierName : String? = null,
val supplierType : Int?, val supplierType : Int?,
val plateNumber : String? = null, //车牌号 val plateNumber : String? = null, //车牌号

View File

@ -16,7 +16,7 @@ data class JpushBean(
val carModel: String? = null,//车辆型号 "carModel":"秦" val carModel: String? = null,//车辆型号 "carModel":"秦"
val contract: String? = null, //车辆型号 "carModel":"秦" val contract: String? = null, //车辆型号 "carModel":"秦"
val typeDesc: String? = null, //推送的附加消息 revoke 撤回 giveUp放弃 reDispatch改派 val typeDesc: String? = null, //推送的附加消息 revoke 撤回 giveUp放弃 reDispatch改派
val userOrderId: Int? = null,
val carNo: String? = null, //客户车车牌号 "carNo":"粤AF53918" val carNo: String? = null, //客户车车牌号 "carNo":"粤AF53918"
val taskState: String? = null, //订单状态 "taskState":"GOTO" val taskState: String? = null, //订单状态 "taskState":"GOTO"
val address: String? = null, //任务地址 "address":"广东省广州市白云区107国道石井凰岗路342号(白云黄石、同德围地区近庆丰兴隆公园)美景大酒店" val address: String? = null, //任务地址 "address":"广东省广州市白云区107国道石井凰岗路342号(白云黄石、同德围地区近庆丰兴隆公园)美景大酒店"

View File

@ -0,0 +1,15 @@
package com.za.bean
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.za.bean.db.order.OrderInfo
class OrderInfoPreviewParameters : PreviewParameterProvider<OrderInfo> {
override val values : Sequence<OrderInfo>
get() = sequenceOf(OrderInfo(taskCode = "123456789",
address = "上海市浦东新区",
distAddress = "上海市浦东新区",
addressProperty = "服务中",
serviceTypeName = "救援",
plateNumber = "沪A12345",
importantTip = "请保持电话畅通,服务人员将尽快联系您。"))
}

View File

@ -1,5 +1,11 @@
package com.za.bean.request 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) 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)

View File

@ -15,6 +15,8 @@ data class LoginRequest(
var dashboardPath: String? = null //里程表照片路径 var dashboardPath: String? = null //里程表照片路径
) )
data class FastLoginRequest(var deviceId: String? = null)
data class PhoneBean( data class PhoneBean(
var versionRelease: String? = null,//系统版本 var versionRelease: String? = null,//系统版本
var model: String? = null,//手机型号 var model: String? = null,//手机型号

View File

@ -5,60 +5,82 @@ import com.amap.api.location.AMapLocation
import com.blankj.utilcode.util.AppUtils import com.blankj.utilcode.util.AppUtils
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
import com.za.bean.db.order.OrderInfo import com.za.bean.db.order.OrderInfo
import com.za.common.log.LogUtil
import com.za.room.RoomHelper import com.za.room.RoomHelper
import com.za.room.db.user.DriverInfoBean import com.za.room.db.user.DriverInfoBean
object GlobalData { object GlobalData {
lateinit var application : Application lateinit var application : Application
private val mmkv : MMKV by lazy { MMKV.defaultMMKV() }
var activityCount : Int = 0 var activityCount : Int = 0
var isMaster = AppUtils.getAppPackageName() == "com.za.rescue.dealer" var isMaster = AppUtils.getAppPackageName() == "com.za.rescue.dealer"
var token : String? = null var token : String? = null
get() { get() {
return MMKV.defaultMMKV().decodeString("ZD_TOKEN", null) return mmkv.decodeString("ZD_TOKEN", null)
} }
set(value) { set(value) {
MMKV.defaultMMKV().encode("ZD_TOKEN", value) mmkv.encode("ZD_TOKEN", value)
field = value field = value
} }
var regid : String? = null var regid : String? = null
get() { get() {
return MMKV.defaultMMKV().decodeString("regid", null) return mmkv.decodeString("regid", null)
} }
set(value) { set(value) {
MMKV.defaultMMKV().encode("regid", value) mmkv.encode("regid", value)
field = value field = value
} }
var aesKey : String? = null var aesKey : String? = null
get() { get() {
return MMKV.defaultMMKV().decodeString("AES_KEY", null) return mmkv.decodeString("AES_KEY", null)
} }
set(value) { set(value) {
MMKV.defaultMMKV().encode("AES_KEY", value) mmkv.encode("AES_KEY", value)
field = value field = value
} }
//新订单是否已经被处理 //新订单是否已经被处理
var isHandlerNewOrder : Boolean? = false var isHandlerNewOrder : Boolean? = false
var driverInfoBean : DriverInfoBean? = null private val lock = Any()
var driverInfoBean : DriverInfoBean?
get() { 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 field = driverInfoBean
return driverInfoBean return driverInfoBean
} }
set(value) { set(value) {
RoomHelper.db?.driverInfoDao()?.updateDriverInfo(value) mmkv.encode("lastLoginBean", value)
} }
var currentOrder : OrderInfo? = null var currentOrder : OrderInfo? = null
get() { get() {
return MMKV.defaultMMKV().decodeParcelable("currentOrder", OrderInfo::class.java) return mmkv.decodeParcelable("currentOrder", OrderInfo::class.java)
} }
set(value) { set(value) {
MMKV.defaultMMKV().encode("currentOrder", value) mmkv.encode("currentOrder", value)
if (RoomHelper.db?.orderDao()?.getCurrentOrder() == null && value != null) { if (RoomHelper.db?.orderDao()?.getCurrentOrder() == null && value != null) {
RoomHelper.db?.orderDao()?.insertOrder(value) RoomHelper.db?.orderDao()?.insertOrder(value)
} else if (value != null) { } else if (value != null) {
@ -78,10 +100,10 @@ object GlobalData {
var loginTime : Long? = null var loginTime : Long? = null
get() { get() {
return MMKV.defaultMMKV().decodeLong("loginTime", System.currentTimeMillis()) return mmkv.decodeLong("loginTime", System.currentTimeMillis())
} }
set(value) { set(value) {
MMKV.defaultMMKV().encode("loginTime", value ?: System.currentTimeMillis()) mmkv.encode("loginTime", value ?: System.currentTimeMillis())
field = value field = value
} }
@ -89,6 +111,7 @@ object GlobalData {
token = null token = null
aesKey = null aesKey = null
currentLocation = null currentLocation = null
driverInfoBean = null
loginTime = null loginTime = null
} }

View File

@ -37,12 +37,14 @@ import com.za.bean.request.CustomerPaymentCreateRequest
import com.za.bean.request.DriverFaceCompareBean import com.za.bean.request.DriverFaceCompareBean
import com.za.bean.request.DriverFaceCompareRequest import com.za.bean.request.DriverFaceCompareRequest
import com.za.bean.request.ElectronOrderResponse import com.za.bean.request.ElectronOrderResponse
import com.za.bean.request.FastLoginRequest
import com.za.bean.request.FetchVehicleMaintenanceSubmitHistoryRequestBean import com.za.bean.request.FetchVehicleMaintenanceSubmitHistoryRequestBean
import com.za.bean.request.GeneralInfoRequest import com.za.bean.request.GeneralInfoRequest
import com.za.bean.request.GiveUpTaskRequest import com.za.bean.request.GiveUpTaskRequest
import com.za.bean.request.HistoryDetailRequest import com.za.bean.request.HistoryDetailRequest
import com.za.bean.request.HistoryPhotoTemplateRequest import com.za.bean.request.HistoryPhotoTemplateRequest
import com.za.bean.request.HistoryTasksRequest import com.za.bean.request.HistoryTasksRequest
import com.za.bean.request.IaiCompareFaceBean
import com.za.bean.request.LoginRequest import com.za.bean.request.LoginRequest
import com.za.bean.request.OrderListRequest import com.za.bean.request.OrderListRequest
import com.za.bean.request.OrderPhotoOcrRecognizeRequest import com.za.bean.request.OrderPhotoOcrRecognizeRequest
@ -116,6 +118,9 @@ interface ApiService {
@POST("/driverApp/task/login") @POST("/driverApp/task/login")
fun login(@Body info : LoginRequest) : Observable<BaseResponse<DriverInfo?>> fun login(@Body info : LoginRequest) : Observable<BaseResponse<DriverInfo?>>
@POST("/driverApp/supplier/fastLogin")
fun fastLogin(@Body info : FastLoginRequest) : Observable<BaseResponse<DriverInfo?>>
//获取该手机号下面服务商列表 //获取该手机号下面服务商列表
@POST("/driverApp/supplier/getDriverListInfo") @POST("/driverApp/supplier/getDriverListInfo")
fun getDriverListInfo(@Body info : VerifyCodeRequest) : Observable<BaseResponse<List<AppNewDriverInfoDTO>>> fun getDriverListInfo(@Body info : VerifyCodeRequest) : Observable<BaseResponse<List<AppNewDriverInfoDTO>>>
@ -271,4 +276,7 @@ interface ApiService {
@POST("driverApp/base/getVoiceUrl") @POST("driverApp/base/getVoiceUrl")
fun getVoiceUrl(@Body info : AppNewOrderVoiceRequest) : Observable<BaseResponse<String>> fun getVoiceUrl(@Body info : AppNewOrderVoiceRequest) : Observable<BaseResponse<String>>
@POST("driverApp/supplier/iaiCompareFace")
fun iaiCompareFace(@Body info : DriverFaceCompareRequest) : Observable<BaseResponse<IaiCompareFaceBean>>
} }

View File

@ -2,7 +2,6 @@ package com.za.net
import android.net.ParseException import android.net.ParseException
import com.blankj.utilcode.util.ActivityUtils import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.ToastUtils
import com.google.gson.JsonParseException import com.google.gson.JsonParseException
import com.za.base.Const import com.za.base.Const
@ -105,21 +104,6 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
GlobalData.clearUserCache() GlobalData.clearUserCache()
ZdLocationManager.stopContinuousLocation() ZdLocationManager.stopContinuousLocation()
ActivityUtils.finishAllActivities() 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) { } catch (e: Exception) {
LogUtil.print("handlerTokenExpired", e) LogUtil.print("handlerTokenExpired", e)
} }

View File

@ -27,6 +27,7 @@ import com.za.common.util.DeviceUtil
import com.za.ext.toJson import com.za.ext.toJson
import com.za.offline.OfflineManager import com.za.offline.OfflineManager
import com.za.room.RoomHelper import com.za.room.RoomHelper
import com.za.room.db.user.DriverInfoBean
import com.za.ui.new_order.NewOrderActivity import com.za.ui.new_order.NewOrderActivity
import com.za.ui.order_report.ReportFloatingManager import com.za.ui.order_report.ReportFloatingManager
import com.za.water_marker.WaterMarkerTemplateManager import com.za.water_marker.WaterMarkerTemplateManager
@ -113,6 +114,8 @@ object CommonMethod {
}) })
} }
private var lastFetchGenerateInfoTime : Long = 0L
fun getGenerateInfo(vehicleId : Int? = null, fun getGenerateInfo(vehicleId : Int? = null,
userId : Int? = null, userId : Int? = null,
success : (GeneralInfo) -> Unit = {}, success : (GeneralInfo) -> Unit = {},
@ -130,10 +133,16 @@ object CommonMethod {
LogUtil.print("getGenerateInfo", "获取车辆信息失败") LogUtil.print("getGenerateInfo", "获取车辆信息失败")
return return
} }
val driverInfoBean = GlobalData.driverInfoBean if (GlobalData.driverInfoBean != null && (System.currentTimeMillis() - lastFetchGenerateInfoTime < 1000 * 10)) {
GlobalData.driverInfoBean = driverInfoBean?.copy(vehicleId = it.vehicleId, LogUtil.print("getGenerateInfo", "获取车辆信息成功但是时间间隔小于10秒不更新车辆信息")
success(it)
return
}
if (GlobalData.driverInfoBean == null) {
GlobalData.driverInfoBean = DriverInfoBean(vehicleId = it.vehicleId,
vehicleName = it.vehicleName, vehicleName = it.vehicleName,
userName = it.userName, userName = it.userName,
loginLogId = it.loginLogId,
userPhone = it.userPhone, userPhone = it.userPhone,
plateNumber = it.plateNumber, plateNumber = it.plateNumber,
vehicleState = it.vehicleState, vehicleState = it.vehicleState,
@ -145,7 +154,25 @@ object CommonMethod {
supplierName = it.supplierName, supplierName = it.supplierName,
authStatus = it.authStatus, authStatus = it.authStatus,
serviceList = it.serviceList?.toString()) 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", LogUtil.print("GlobalData.driverInfoBean",
"${GlobalData.driverInfoBean?.toJson()}}") "${GlobalData.driverInfoBean?.toJson()}}")

View File

@ -11,7 +11,7 @@ import com.za.room.db.GlobalRoom
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
object RoomHelper { object RoomHelper {
const val VERSION: Int = 37 const val VERSION: Int = 38
private lateinit var mContext: Context private lateinit var mContext: Context
var db: GlobalRoom? = null var db: GlobalRoom? = null

View File

@ -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.ChangeBatteryDao
import com.za.room.db.order.OrderDao import com.za.room.db.order.OrderDao
import com.za.room.db.order.PhotoTemplateDao 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.LocalResourceBean
import com.za.room.db.user.LocalResourceDao import com.za.room.db.user.LocalResourceDao
import com.za.room.db.water_marker.WaterMarkerDao 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, version = RoomHelper.VERSION,
exportSchema = false) exportSchema = false)
abstract class GlobalRoom : RoomDatabase() { abstract class GlobalRoom : RoomDatabase() {
@ -43,7 +41,5 @@ abstract class GlobalRoom : RoomDatabase() {
abstract fun offlineTaskDao() : OfflineDao abstract fun offlineTaskDao() : OfflineDao
abstract fun driverInfoDao() : DriverInfoDao
abstract fun localResourceDao() : LocalResourceDao abstract fun localResourceDao() : LocalResourceDao
} }

View File

@ -1,11 +1,10 @@
package com.za.room.db.user package com.za.room.db.user
import androidx.room.Entity import android.os.Parcel
import androidx.room.PrimaryKey import android.os.Parcelable
@Entity(tableName = "driver_info")
data class DriverInfoBean( data class DriverInfoBean(
@PrimaryKey(autoGenerate = false) val userId : Int? = null, //用户id val userId : Int? = null, //用户id
val userName : String? = null, //用户姓名 val userName : String? = null, //用户姓名
val userPhone : String? = null, //用户手机号 val userPhone : String? = null, //用户手机号
val userPortrait : String? = null, //用户头像 val userPortrait : String? = null, //用户头像
@ -23,4 +22,59 @@ data class DriverInfoBean(
val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌 val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌
val plateNumber : String? = null, //车牌号 val plateNumber : String? = null, //车牌号
val deviceId : String? = null, val deviceId : String? = null,
) ) : 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<DriverInfoBean> {
override fun createFromParcel(parcel : Parcel) : DriverInfoBean {
return DriverInfoBean(parcel)
}
override fun newArray(size : Int) : Array<DriverInfoBean?> {
return arrayOfNulls(size)
}
}
}

View File

@ -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)
}
}

View File

@ -65,65 +65,69 @@ import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
class ZdCameraXActivity : AppCompatActivity() { class ZdCameraXActivity : AppCompatActivity() {
private var exposurePopupWindow: PopupWindow? = null private var exposurePopupWindow : PopupWindow? = null
internal enum class FlashMode { internal enum class FlashMode {
auto, open, light, close auto, open, light, close
} }
private var rootView: ConstraintLayout? = null private var rootView : ConstraintLayout? = null
private var imageCapture: ImageCapture? = null private var imageCapture : ImageCapture? = null
private var cameraInfo: CameraInfo? = null private var cameraInfo : CameraInfo? = null
private var exposureState: ExposureState? = null private var exposureState : ExposureState? = null
private var cameraExecutor: ExecutorService? = null private var cameraExecutor : ExecutorService? = null
private var zoomState: LiveData<ZoomState>? = null private var zoomState : LiveData<ZoomState>? = null
private var viewFinder: PreviewView? = null private var viewFinder : PreviewView? = null
private var takePhoto: TakePhotoButtonView? = null private var takePhoto : TakePhotoButtonView? = null
private var ivFlash: ImageView? = null private var ivFlash : ImageView? = null
private var ivChangeCamera: ImageView? = null private var ivChangeCamera : ImageView? = null
private var ivConfirm: ImageView? = null private var ivConfirm : ImageView? = null
private var ivCancel: ImageView? = null private var ivCancel : ImageView? = null
private lateinit var ivPreview: ImageFilterView private lateinit var ivPreview : ImageFilterView
private var ivBack: ImageView? = null private var ivBack : ImageView? = null
private var sliderExposure: AppCompatSeekBar? = null private var sliderExposure : AppCompatSeekBar? = null
private var groupOperation: Group? = null private var groupOperation : Group? = null
private var groupPreview: Group? = null private var groupPreview : Group? = null
private var uri: Uri? = null private var uri : Uri? = null
private var animatorSet: AnimatorSet? = null private var animatorSet : AnimatorSet? = null
private var location: Location? = null private var location : Location? = null
private var camera: Camera? = null private var camera : Camera? = null
private var isBack = true private var isBack = true
private var orientationEventListener: OrientationEventListener? = null private var orientationEventListener : OrientationEventListener? = null
private var flashPopWindow: PopupWindow? = null private var flashPopWindow : PopupWindow? = null
private var flashMode = FlashMode.close private var flashMode = FlashMode.close
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_zd_camera_xactivity) setContentView(R.layout.activity_zd_camera_xactivity)
isBack = intent.getBooleanExtra("isBack", true)
initView() initView()
initLocation() initLocation()
startCamera() startCamera()
setOnClick() setOnClick()
orientationEventListener = object : OrientationEventListener(this) { orientationEventListener = object : OrientationEventListener(this) {
override fun onOrientationChanged(orientation: Int) { override fun onOrientationChanged(orientation : Int) {
if (orientation == ORIENTATION_UNKNOWN || imageCapture == null) { if (orientation == ORIENTATION_UNKNOWN || imageCapture == null) {
print("zdCamerax orientation", "orientation==$orientation") print("zdCamerax orientation", "orientation==$orientation")
return return
} }
when (orientation) { when (orientation) {
in 45..134 -> { in 45 .. 134 -> {
imageCapture?.targetRotation = Surface.ROTATION_270 imageCapture?.targetRotation = Surface.ROTATION_270
} }
in 135..224 -> {
in 135 .. 224 -> {
imageCapture?.targetRotation = Surface.ROTATION_180 imageCapture?.targetRotation = Surface.ROTATION_180
} }
in 225..314 -> {
in 225 .. 314 -> {
imageCapture?.targetRotation = Surface.ROTATION_90 imageCapture?.targetRotation = Surface.ROTATION_90
} }
else -> { else -> {
imageCapture?.targetRotation = Surface.ROTATION_0 imageCapture?.targetRotation = Surface.ROTATION_0
} }
@ -149,18 +153,19 @@ class ZdCameraXActivity : AppCompatActivity() {
ivPreview = findViewById(R.id.iv_preview) ivPreview = findViewById(R.id.iv_preview)
ivFlash = findViewById(R.id.iv_flash) ivFlash = findViewById(R.id.iv_flash)
animatorSet = AnimatorSet() animatorSet = AnimatorSet()
animatorSet?.playTogether(ObjectAnimator.ofFloat(ivCancel, "translationX", 0f, -200f), ObjectAnimator.ofFloat(ivConfirm, "translationX", 200f)) animatorSet?.playTogether(ObjectAnimator.ofFloat(ivCancel, "translationX", 0f, - 200f),
ObjectAnimator.ofFloat(ivConfirm, "translationX", 200f))
animatorSet?.setDuration(500) animatorSet?.setDuration(500)
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
private fun setOnClick() { private fun setOnClick() {
takePhoto?.setOnClickListener(ClickProxy { v: View? -> takePhoto() }) takePhoto?.setOnClickListener(ClickProxy { v : View? -> takePhoto() })
ivChangeCamera?.setOnClickListener(ClickProxy { v: View? -> ivChangeCamera?.setOnClickListener(ClickProxy { v : View? ->
isBack = !isBack isBack = ! isBack
if (!isBack) { if (! isBack) {
if (flashPopWindow != null && flashPopWindow?.isShowing == true) { if (flashPopWindow != null && flashPopWindow?.isShowing == true) {
flashPopWindow?.dismiss() flashPopWindow?.dismiss()
} }
@ -171,11 +176,11 @@ class ZdCameraXActivity : AppCompatActivity() {
}) })
ivFlash?.setOnClickListener { ivFlash?.setOnClickListener {
if (!isBack) { if (! isBack) {
ToastUtils.showShort("前置模式下无法开启!") ToastUtils.showShort("前置模式下无法开启!")
return@setOnClickListener return@setOnClickListener
} }
if (flashPopWindow != null && flashPopWindow?.isShowing==true) { if (flashPopWindow != null && flashPopWindow?.isShowing == true) {
flashPopWindow?.dismiss() flashPopWindow?.dismiss()
} else { } else {
showFlashView() showFlashView()
@ -200,21 +205,22 @@ class ZdCameraXActivity : AppCompatActivity() {
sliderExposure?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { sliderExposure?.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar : SeekBar, progress : Int, fromUser : Boolean) {
if (exposureState != null) { if (exposureState != null) {
camera?.cameraControl?.setExposureCompensationIndex(Math.round(progress.toFloat())) camera?.cameraControl?.setExposureCompensationIndex(Math.round(progress.toFloat()))
if (exposurePopupWindow != null) { if (exposurePopupWindow != null) {
val textView = exposurePopupWindow?.contentView?.findViewWithTag<TextView>("tv_exposureView") val textView =
exposurePopupWindow?.contentView?.findViewWithTag<TextView>("tv_exposureView")
textView?.text = progress.toString() + "" textView?.text = progress.toString() + ""
} }
} }
} }
override fun onStartTrackingTouch(seekBar: SeekBar) { override fun onStartTrackingTouch(seekBar : SeekBar) {
showExposureView() showExposureView()
} }
override fun onStopTrackingTouch(seekBar: SeekBar) { override fun onStopTrackingTouch(seekBar : SeekBar) {
viewFinder?.postDelayed({ exposurePopupWindow?.dismiss() }, 1000) viewFinder?.postDelayed({ exposurePopupWindow?.dismiss() }, 1000)
} }
}) })
@ -222,7 +228,7 @@ class ZdCameraXActivity : AppCompatActivity() {
val cameraXPreviewViewTouchListener = CameraXPreviewViewTouchListener(this) val cameraXPreviewViewTouchListener = CameraXPreviewViewTouchListener(this)
viewFinder?.setOnTouchListener(cameraXPreviewViewTouchListener) viewFinder?.setOnTouchListener(cameraXPreviewViewTouchListener)
cameraXPreviewViewTouchListener.setCustomTouchListener(object : CustomTouchListener { cameraXPreviewViewTouchListener.setCustomTouchListener(object : CustomTouchListener {
override fun zoom(delta: Float) { override fun zoom(delta : Float) {
if (zoomState == null) { if (zoomState == null) {
return return
} }
@ -233,21 +239,22 @@ class ZdCameraXActivity : AppCompatActivity() {
} }
override fun click(event: MotionEvent) { override fun click(event : MotionEvent) {
val action = viewFinder?.meteringPointFactory?.createPoint(event.x, event.y)?.let { FocusMeteringAction.Builder(it).build() } val action = viewFinder?.meteringPointFactory?.createPoint(event.x, event.y)
?.let { FocusMeteringAction.Builder(it).build() }
rootView?.post { showTapView(event.rawX.toInt(), event.rawY.toInt()) } rootView?.post { showTapView(event.rawX.toInt(), event.rawY.toInt()) }
action?.let { action?.let {
camera?.cameraControl?.startFocusAndMetering(action) camera?.cameraControl?.startFocusAndMetering(action)
} }
} }
override fun doubleClick(x: Float, y: Float) { override fun doubleClick(x : Float, y : Float) {
if (zoomState == null) { if (zoomState == null) {
return return
} }
val currentZoomRatio = zoomState?.value?.zoomRatio val currentZoomRatio = zoomState?.value?.zoomRatio
zoomState?.value?.minZoomRatio?.let { zoomState?.value?.minZoomRatio?.let {
if (currentZoomRatio!! > it) { if (currentZoomRatio !! > it) {
camera?.cameraControl?.setLinearZoom(0f) camera?.cameraControl?.setLinearZoom(0f)
} else { } else {
camera?.cameraControl?.setLinearZoom(0.5f) camera?.cameraControl?.setLinearZoom(0.5f)
@ -261,10 +268,12 @@ class ZdCameraXActivity : AppCompatActivity() {
private fun takePhoto() { private fun takePhoto() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ThreadUtils.runOnUiThread { ThreadUtils.runOnUiThread {
PermissionX.init(this@ZdCameraXActivity).permissions(Manifest.permission.ACCESS_MEDIA_LOCATION) PermissionX.init(this@ZdCameraXActivity)
.request { allGranted: Boolean, grantedList: List<String?>?, deniedList: List<String?>? -> .permissions(Manifest.permission.ACCESS_MEDIA_LOCATION)
print("ZDCamerax ACCESS_MEDIA_LOCATION 权限请求结果", "allGranted==$allGranted") .request { allGranted : Boolean, grantedList : List<String?>?, deniedList : List<String?>? ->
if (!allGranted) { print("ZDCamerax ACCESS_MEDIA_LOCATION 权限请求结果",
"allGranted==$allGranted")
if (! allGranted) {
ToastUtils.showLong("权限获取失败") ToastUtils.showLong("权限获取失败")
finish() finish()
} }
@ -274,74 +283,76 @@ class ZdCameraXActivity : AppCompatActivity() {
if (imageCapture == null) { if (imageCapture == null) {
ToastUtils.showShort("相机打开失败") ToastUtils.showShort("相机打开失败")
finish() finish()
} } // val filename = TimeUtils.date2String(Date(), "yyyyMMddHHmmss")
// val filename = TimeUtils.date2String(Date(), "yyyyMMddHHmmss") // val contentValues = ContentValues()
// val contentValues = ContentValues() // contentValues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, filename)
// contentValues.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, filename) // contentValues.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg")
// contentValues.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/jpeg") // contentValues.put(MediaStore.Images.ImageColumns.DATE_TAKEN, System.currentTimeMillis())
// contentValues.put(MediaStore.Images.ImageColumns.DATE_TAKEN, System.currentTimeMillis()) // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
// contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) // } else {
// } else { // ImageUtils.save2Album()
// ImageUtils.save2Album() // contentValues.put(MediaStore.Images.ImageColumns.DATA, getTakePictureParentPath() + File.separator + filename + ".jpg")
// contentValues.put(MediaStore.Images.ImageColumns.DATA, getTakePictureParentPath() + File.separator + filename + ".jpg") // }
// } //
// // val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver,
// val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver, // MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build()
// MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build()
// Create time stamped name and MediaStore entry. // Create time stamped name and MediaStore entry.
val filename = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()) val filename = SimpleDateFormat("yyyyMMddHHmmss",
.format(System.currentTimeMillis()) Locale.getDefault()).format(System.currentTimeMillis())
val contentValues = ContentValues().apply { val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename) put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/中道救援") put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/中道救援")
} }
} }
// Create output options object which contains file + metadata // Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver,
.Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
.build() contentValues).build()
takePhoto?.startAnimation() takePhoto?.startAnimation()
imageCapture?.takePicture(outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback { imageCapture?.takePicture(outputOptions,
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { ContextCompat.getMainExecutor(this),
this@ZdCameraXActivity.uri = outputFileResults.savedUri object : ImageCapture.OnImageSavedCallback {
//保存照片信息 override fun onImageSaved(outputFileResults : ImageCapture.OutputFileResults) {
val exifInterface: ExifInterface this@ZdCameraXActivity.uri = outputFileResults.savedUri //保存照片信息
val exifInterface : ExifInterface
try { try {
exifInterface = ExifInterface(UriUtils.uri2File(outputFileResults.savedUri).absolutePath) exifInterface =
ExifInterface(UriUtils.uri2File(outputFileResults.savedUri).absolutePath)
exifInterface.setAttribute(ExifInterface.TAG_DATETIME, filename) exifInterface.setAttribute(ExifInterface.TAG_DATETIME, filename)
if (location != null) { if (location != null) {
exifInterface.setGpsInfo(location) exifInterface.setGpsInfo(location)
if (location?.latitude!! > 0f && location?.longitude != null && location?.longitude!! > 0f) { if (location?.latitude !! > 0f && location?.longitude != null && location?.longitude !! > 0f) {
exifInterface.setLatLong(location?.latitude!!, location?.longitude!!) exifInterface.setLatLong(location?.latitude !!,
location?.longitude !!)
} }
} }
exifInterface.saveAttributes() exifInterface.saveAttributes()
takePhoto?.cancelAnimation() takePhoto?.cancelAnimation()
groupPreview?.visibility = View.VISIBLE groupPreview?.visibility = View.VISIBLE
if (!this@ZdCameraXActivity.isFinishing) { if (! this@ZdCameraXActivity.isFinishing) {
Glide.with(this@ZdCameraXActivity).load(outputFileResults.savedUri).into(ivPreview) Glide.with(this@ZdCameraXActivity).load(outputFileResults.savedUri)
.into(ivPreview)
} }
groupOperation?.visibility = View.GONE groupOperation?.visibility = View.GONE
animatorSet?.start() animatorSet?.start()
} catch (e: IOException) { } catch (e : IOException) {
takePhoto?.cancelAnimation() takePhoto?.cancelAnimation()
ToastUtils.showShort("照片保存失败" + e.message) ToastUtils.showShort("照片保存失败" + e.message)
print("照片保存失败", e) print("照片保存失败", e)
} }
} }
override fun onError(exception: ImageCaptureException) { override fun onError(exception : ImageCaptureException) {
takePhoto?.cancelAnimation() takePhoto?.cancelAnimation()
ToastUtils.showShort("Photo capture failed" + exception.message) ToastUtils.showShort("Photo capture failed" + exception.message)
print("onCameraError", exception) print("onCameraError", exception)
@ -350,15 +361,18 @@ class ZdCameraXActivity : AppCompatActivity() {
} }
private fun startCamera() { private fun startCamera() {
imageCapture = ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY).build() imageCapture =
ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this) val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({ cameraProviderFuture.addListener({
try { try {
val cameraProvider = cameraProviderFuture.get() val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build() val preview = Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).build()
preview.setSurfaceProvider(viewFinder?.surfaceProvider) preview.surfaceProvider = viewFinder?.surfaceProvider
val cameraSelector = if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA val cameraSelector =
if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA
preview.targetRotation = Surface.ROTATION_0 preview.targetRotation = Surface.ROTATION_0
cameraProvider.unbindAll() cameraProvider.unbindAll()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture) camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
@ -374,10 +388,10 @@ class ZdCameraXActivity : AppCompatActivity() {
} else { } else {
sliderExposure?.visibility = View.GONE sliderExposure?.visibility = View.GONE
} }
} catch (e: ExecutionException) { } catch (e : ExecutionException) {
finish() finish()
print("相机初始化失败", e) print("相机初始化失败", e)
} catch (e: InterruptedException) { } catch (e : InterruptedException) {
finish() finish()
print("相机初始化失败", e) print("相机初始化失败", e)
} }
@ -386,8 +400,21 @@ class ZdCameraXActivity : AppCompatActivity() {
private fun initLocation() { private fun initLocation() {
val locationManager = ContextCompat.getSystemService(this, LocationManager::class.java) 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) { if ((ActivityCompat.checkSelfPermission(this,
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA), 102) 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 { } else {
if (locationManager != null) { if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
@ -396,12 +423,13 @@ class ZdCameraXActivity : AppCompatActivity() {
} }
@SuppressLint("RtlHardcoded") @SuppressLint("RtlHardcoded")
private fun showTapView(x: Int, y: Int) { private fun showTapView(x : Int, y : Int) {
if (takePhoto?.visibility == View.GONE) { if (takePhoto?.visibility == View.GONE) {
return return
} }
try { try {
val popupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) val popupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
popupWindow.width = 200 popupWindow.width = 200
popupWindow.height = 200 popupWindow.height = 200
val imageView = ImageView(this) val imageView = ImageView(this)
@ -411,7 +439,7 @@ class ZdCameraXActivity : AppCompatActivity() {
popupWindow.showAtLocation(rootView, Gravity.LEFT or Gravity.TOP, x, y) popupWindow.showAtLocation(rootView, Gravity.LEFT or Gravity.TOP, x, y)
viewFinder?.postDelayed({ popupWindow.dismiss() }, 1000) viewFinder?.postDelayed({ popupWindow.dismiss() }, 1000)
viewFinder?.playSoundEffect(SoundEffectConstants.CLICK) viewFinder?.playSoundEffect(SoundEffectConstants.CLICK)
} catch (e: Exception) { } catch (e : Exception) {
print("zdCameraX showTapView", e) print("zdCameraX showTapView", e)
} }
} }
@ -421,7 +449,8 @@ class ZdCameraXActivity : AppCompatActivity() {
if (takePhoto?.visibility == View.GONE) { if (takePhoto?.visibility == View.GONE) {
return return
} }
exposurePopupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) exposurePopupWindow =
PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
exposurePopupWindow?.width = 300 exposurePopupWindow?.width = 300
exposurePopupWindow?.height = 200 exposurePopupWindow?.height = 200
val textView = TextView(this) val textView = TextView(this)
@ -439,8 +468,10 @@ class ZdCameraXActivity : AppCompatActivity() {
if (flashPopWindow != null) { if (flashPopWindow != null) {
flashPopWindow = null flashPopWindow = null
} }
flashPopWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) flashPopWindow =
@SuppressLint("InflateParams") val view = LayoutInflater.from(this).inflate(R.layout.item_flash_mode, null) 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<TextView>(R.id.tvFlashAuto) val tvFlashAuto = view.findViewById<TextView>(R.id.tvFlashAuto)
val tvFlashOpen = view.findViewById<TextView>(R.id.tvFlashOpen) val tvFlashOpen = view.findViewById<TextView>(R.id.tvFlashOpen)
val tvFlashLight = view.findViewById<TextView>(R.id.tvFlashLight) val tvFlashLight = view.findViewById<TextView>(R.id.tvFlashLight)
@ -452,7 +483,7 @@ class ZdCameraXActivity : AppCompatActivity() {
FlashMode.light -> tvFlashLight.setTextColor(Color.YELLOW) FlashMode.light -> tvFlashLight.setTextColor(Color.YELLOW)
FlashMode.close -> tvFlashClose.setTextColor(Color.YELLOW) FlashMode.close -> tvFlashClose.setTextColor(Color.YELLOW)
} }
tvFlashAuto.setOnClickListener { v: View? -> tvFlashAuto.setOnClickListener { v : View? ->
if (imageCapture != null) { if (imageCapture != null) {
camera?.cameraControl?.enableTorch(false) camera?.cameraControl?.enableTorch(false)
imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO
@ -461,7 +492,7 @@ class ZdCameraXActivity : AppCompatActivity() {
} }
flashPopWindow?.dismiss() flashPopWindow?.dismiss()
} }
tvFlashOpen.setOnClickListener { v: View? -> tvFlashOpen.setOnClickListener { v : View? ->
if (imageCapture != null) { if (imageCapture != null) {
camera?.cameraControl?.enableTorch(false) camera?.cameraControl?.enableTorch(false)
imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON
@ -471,7 +502,7 @@ class ZdCameraXActivity : AppCompatActivity() {
flashPopWindow?.dismiss() flashPopWindow?.dismiss()
} }
tvFlashLight.setOnClickListener { v: View? -> tvFlashLight.setOnClickListener { v : View? ->
if (camera != null) { if (camera != null) {
camera?.cameraControl?.enableTorch(true) camera?.cameraControl?.enableTorch(true)
ivFlash?.setImageResource(R.drawable.ic_flash_light) ivFlash?.setImageResource(R.drawable.ic_flash_light)
@ -480,7 +511,7 @@ class ZdCameraXActivity : AppCompatActivity() {
flashPopWindow?.dismiss() flashPopWindow?.dismiss()
} }
tvFlashClose.setOnClickListener { v: View? -> tvFlashClose.setOnClickListener { v : View? ->
if (imageCapture != null) { if (imageCapture != null) {
camera?.cameraControl?.enableTorch(false) camera?.cameraControl?.enableTorch(false)
imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF
@ -491,8 +522,10 @@ class ZdCameraXActivity : AppCompatActivity() {
} }
flashPopWindow?.contentView = view flashPopWindow?.contentView = view
flashPopWindow?.showAtLocation(ivFlash, Gravity.LEFT or Gravity.TOP, 0, ivFlash?.y?.toInt()?.minus(view.height) flashPopWindow?.showAtLocation(ivFlash,
?: 0) Gravity.LEFT or Gravity.TOP,
0,
ivFlash?.y?.toInt()?.minus(view.height) ?: 0)
} }
override fun onPause() { override fun onPause() {

View File

@ -16,6 +16,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.tooling.preview.Preview
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.ToastUtils
import com.permissionx.guolindev.PermissionX import com.permissionx.guolindev.PermissionX
@ -195,6 +196,7 @@ class ServiceLauncherActivity : BaseActivity() {
} }
} }
@Preview
@Composable @Composable
private fun LauncherScreen() { private fun LauncherScreen() {
Scaffold { paddingValues -> Scaffold { paddingValues ->

View File

@ -2,22 +2,65 @@ package com.za.ui.main
import android.content.Context import android.content.Context
import android.content.Intent 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.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.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope 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.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.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.blankj.utilcode.util.ActivityUtils import com.blankj.utilcode.util.ActivityUtils
import com.za.base.BaseActivity 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.GlobalData
import com.za.common.util.DeviceUtil 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.finish
import com.za.ext.goStatusPage import com.za.ext.goStatusPage
import com.za.service.ServiceManager import com.za.service.ServiceManager
import com.za.service.location.ZdLocationManager import com.za.service.location.ZdLocationManager
import com.za.servicing.R
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ServicingMainActivity : BaseActivity() { class ServicingMainActivity : BaseActivity() {
@ -59,8 +102,8 @@ private fun ServicingMainScreen(jobCode : String? = null,
rescueVehicle : String? = null, rescueVehicle : String? = null,
vm : ServicingMainVm = viewModel()) { vm : ServicingMainVm = viewModel()) {
val uiState = vm.uiState.collectAsStateWithLifecycle() val uiState = vm.uiState.collectAsStateWithLifecycle()
val context = LocalContext.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val context = LocalContext.current
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
vm.dispatch(ServicingMainVm.Action.Init(jobCode, vm.dispatch(ServicingMainVm.Action.Init(jobCode,
@ -75,12 +118,200 @@ private fun ServicingMainScreen(jobCode : String? = null,
} }
} }
if (uiState.value.state == 2) { Scaffold(topBar = { HeadView("订单信息确认", onBack = { context.finish() }) }, bottomBar = {
Box { if (uiState.value.state == 1) {
Text(text = "加载失败") CommonButton(text = "已确认,去服务") {
}
} else {
GlobalData.currentOrder?.goStatusPage(ActivityUtils.getTopActivity()) 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)
}
}
}
}
}
@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()
} }

View File

@ -48,6 +48,9 @@ class ServicingMainVm : BaseVm<ServicingMainVm.Action, ServicingMainVm.UiState>(
LoadingManager.hideLoading() LoadingManager.hideLoading()
GlobalData.currentOrder = orderInfo GlobalData.currentOrder = orderInfo
updateState(uiState.value.copy(state = 1)) updateState(uiState.value.copy(state = 1))
if (orderInfos.isNullOrEmpty()) {
ToastUtils.showShort("未查询到订单")
}
}, },
failed = { failed = {
updateState(uiState.value.copy(state = 2)) updateState(uiState.value.copy(state = 2))

View File

@ -57,7 +57,6 @@ import coil.compose.AsyncImage
import com.amap.api.location.AMapLocationClient import com.amap.api.location.AMapLocationClient
import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.MapView 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.LatLng
import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MarkerOptions

View File

@ -51,20 +51,24 @@ class OrderGiveUpActivity : BaseActivity() {
intent.getParcelableExtra("orderInfo") 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 { companion object {
//giveUp type //giveUp type
//0 师傅手机操作放弃 1 后台操作放弃 2 师傅出发前后台操作放弃 //0 师傅手机操作放弃 1 后台操作放弃 2 师傅出发前后台操作放弃
fun goOrderGiveUpActivity(context: Context, fun goOrderGiveUpActivity(context : Context,
orderInfo: OrderInfo? = null, orderInfo : OrderInfo? = null,
taskId: Int? = null, taskId : Int? = null,
giveUpType: Int) { userOrderId : Int? = null,
giveUpType : Int) {
val intent = Intent(context, OrderGiveUpActivity::class.java) val intent = Intent(context, OrderGiveUpActivity::class.java)
intent.putExtra("giveUpType", giveUpType) intent.putExtra("giveUpType", giveUpType)
intent.putExtra("orderInfo", orderInfo) intent.putExtra("orderInfo", orderInfo)
intent.putExtra("taskId", taskId) intent.putExtra("taskId", taskId)
intent.putExtra("userOrderId", userOrderId)
context.startActivity(intent) context.startActivity(intent)
} }
} }
@ -72,12 +76,17 @@ class OrderGiveUpActivity : BaseActivity() {
@Composable @Composable
fun OrderGiveUpScreen(vm: OrderGiveUpVm = viewModel(), orderInfo: OrderInfo?, taskId: Int, giveUpType: Int) { fun OrderGiveUpScreen(vm : OrderGiveUpVm = viewModel(),
orderInfo : OrderInfo?,
taskId : Int,
giveUpType : Int) {
val uiState = vm.uiState.collectAsStateWithLifecycle() val uiState = vm.uiState.collectAsStateWithLifecycle()
val context = LocalContext.current val context = LocalContext.current
LaunchedEffect(key1 = Unit) { LaunchedEffect(key1 = Unit) {
vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(orderInfo = orderInfo, taskId = taskId, giveUpType = giveUpType))) vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(orderInfo = orderInfo,
taskId = taskId,
giveUpType = giveUpType)))
vm.dispatch(OrderGiveUpVm.Action.Init) vm.dispatch(OrderGiveUpVm.Action.Init)
} }
@ -86,11 +95,17 @@ fun OrderGiveUpScreen(vm: OrderGiveUpVm = viewModel(), orderInfo: OrderInfo?, ta
} }
if (uiState.value.isGoNextPageDialog == true) { if (uiState.value.isGoNextPageDialog == true) {
CommonDialog(cancelText = "取消", confirmText = "是否确认放弃订单", title = "放弃订单", cancelEnable = true, cancel = { CommonDialog(cancelText = "取消",
confirmText = "是否确认放弃订单",
title = "放弃订单",
cancelEnable = true,
cancel = {
vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false)))
}, dismiss = { },
dismiss = {
vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false)))
}, confirm = { },
confirm = {
vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) vm.dispatch(OrderGiveUpVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false)))
vm.dispatch(OrderGiveUpVm.Action.UpdateTask) vm.dispatch(OrderGiveUpVm.Action.UpdateTask)
}) })
@ -105,10 +120,11 @@ fun OrderGiveUpScreen(vm: OrderGiveUpVm = viewModel(), orderInfo: OrderInfo?, ta
}) { it -> }) { it ->
LazyColumn(modifier = Modifier LazyColumn(modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(it), contentPadding = PaddingValues(10.dp)) { .padding(it),
contentPadding = PaddingValues(10.dp)) {
itemsIndexed(items = uiState.value.photoTemplateList itemsIndexed(items = uiState.value.photoTemplateList ?: arrayListOf(),
?: arrayListOf(), key = { _, item -> item.hashCode() }) { index: Int, item: PhotoTemplateInfo -> key = { _, item -> item.hashCode() }) { index : Int, item : PhotoTemplateInfo ->
InServicingPhotoView(photoTemplateInfo = item, index = index + 1, success = { InServicingPhotoView(photoTemplateInfo = item, index = index + 1, success = {
vm.dispatch(OrderGiveUpVm.Action.UpdatePhotoTemplate(it)) vm.dispatch(OrderGiveUpVm.Action.UpdatePhotoTemplate(it))
}) })
@ -124,10 +140,16 @@ fun OrderGiveUpScreen(vm: OrderGiveUpVm = viewModel(), orderInfo: OrderInfo?, ta
.background(color = Color.White, shape = RoundedCornerShape(6.dp)) .background(color = Color.White, shape = RoundedCornerShape(6.dp))
.padding(10.dp)) { .padding(10.dp)) {
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Row(modifier = Modifier.fillMaxWidth(),
Text(text = "司机签名", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) verticalAlignment = Alignment.CenterVertically) {
Text(text = "司机签名",
color = Color.Black,
fontWeight = FontWeight.Medium,
fontSize = 14.sp)
Spacer(Modifier.weight(1f)) Spacer(Modifier.weight(1f))
AsyncImage(model = R.drawable.sv_sign_new, contentDescription = "", modifier = Modifier.size(20.dp)) AsyncImage(model = R.drawable.sv_sign_new,
contentDescription = "",
modifier = Modifier.size(20.dp))
} }
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))

View File

@ -46,19 +46,22 @@ import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: OrderInfo?, isCanBack: Boolean = true) { fun InServicingHeadView(title : String,
onBack : () -> Unit = {},
orderInfo : OrderInfo?,
isCanBack : Boolean = true) {
val context = LocalContext.current val context = LocalContext.current
val showBottomSheetDialog = remember { mutableStateOf(false) } val showBottomSheetDialog = remember { mutableStateOf(false) }
val showNavigationDialog = remember { mutableStateOf(false) } val showNavigationDialog = remember { mutableStateOf(false) }
val showCallPhoneDialog = remember { mutableStateOf(false) } val showCallPhoneDialog = remember { mutableStateOf(false) }
val showCallServicePhoneDialog = remember { mutableStateOf(false) }
if (showNavigationDialog.value) { if (showNavigationDialog.value) {
StartNavigationView(orderInfo = orderInfo, dismiss = { showNavigationDialog.value = false }) StartNavigationView(orderInfo = orderInfo, dismiss = { showNavigationDialog.value = false })
} }
if (showCallPhoneDialog.value) { if (showCallPhoneDialog.value) {
CommonDialog( CommonDialog(cancelText = "取消",
cancelText = "取消",
confirmText = "确定", confirmText = "确定",
title = "是否联系客户?", title = "是否联系客户?",
cancelEnable = true, cancelEnable = true,
@ -73,6 +76,22 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
}) })
} }
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) { if (showBottomSheetDialog.value) {
ModalBottomSheet(containerColor = Color.White, ModalBottomSheet(containerColor = Color.White,
@ -81,14 +100,19 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
.fillMaxWidth() .fillMaxWidth()
.padding(10.dp)) { .padding(10.dp)) {
if (!orderInfo?.customerReportImgs.isNullOrBlank()) { if (! orderInfo?.customerReportImgs.isNullOrBlank()) {
Box(modifier = Modifier Box(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ON_SITE_PHOTO) OrderRequirementsActivity.goOrderRequirementsActivity(context,
orderInfo,
type = Const.InServiceSettingType.ON_SITE_PHOTO)
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "现场照片", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) Text(text = "现场照片",
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = Color.Black)
} }
HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5)
} }
@ -99,7 +123,10 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
showNavigationDialog.value = true showNavigationDialog.value = true
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "开启外部导航", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) Text(text = "开启外部导航",
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = Color.Black)
} }
HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5)
@ -107,9 +134,14 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ORDER_REQUIREMENTS) OrderRequirementsActivity.goOrderRequirementsActivity(context,
orderInfo,
type = Const.InServiceSettingType.ORDER_REQUIREMENTS)
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "案件要求", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) Text(text = "案件要求",
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = Color.Black)
} }
HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5)
@ -117,9 +149,14 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
OrderRequirementsActivity.goOrderRequirementsActivity(context, orderInfo, type = Const.InServiceSettingType.ORDER_DETAIL) OrderRequirementsActivity.goOrderRequirementsActivity(context,
orderInfo,
type = Const.InServiceSettingType.ORDER_DETAIL)
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "案件详情", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) Text(text = "案件详情",
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = Color.Black)
} }
HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5)
@ -127,9 +164,15 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
OrderGiveUpActivity.goOrderGiveUpActivity(context, orderInfo = orderInfo, giveUpType = 0) OrderGiveUpActivity.goOrderGiveUpActivity(context,
orderInfo = orderInfo,
userOrderId = orderInfo?.userOrderId,
giveUpType = 0)
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "订单放弃", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Red) Text(text = "订单放弃",
fontSize = 15.sp,
fontWeight = FontWeight.Medium,
color = Color.Black)
} }
HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5) HorizontalDivider(modifier = Modifier.padding(vertical = 10.dp), color = black5)
@ -139,8 +182,26 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
showBottomSheetDialog.value = false showBottomSheetDialog.value = false
showCallPhoneDialog.value = true showCallPhoneDialog.value = true
}, contentAlignment = Alignment.Center) { }, contentAlignment = Alignment.Center) {
Text(text = "拨打电话", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Color.Black) 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)) Spacer(modifier = Modifier.height(10.dp))
} }
@ -152,27 +213,33 @@ fun InServicingHeadView(title: String, onBack: () -> Unit = {}, orderInfo: Order
.fillMaxWidth() .fillMaxWidth()
.background(color = headBgColor) .background(color = headBgColor)
.padding(top = headPadding), .padding(top = headPadding),
colors = TopAppBarDefaults.centerAlignedTopAppBarColors().copy(containerColor = headBgColor, titleContentColor = Color.White), colors = TopAppBarDefaults.centerAlignedTopAppBarColors()
.copy(containerColor = headBgColor, titleContentColor = Color.White),
title = { Text(text = title, fontSize = 15.sp, fontWeight = FontWeight.Medium) }, title = { Text(text = title, fontSize = 15.sp, fontWeight = FontWeight.Medium) },
navigationIcon = { navigationIcon = {
if (isCanBack) { if (isCanBack) {
AsyncImage(model = R.drawable.sv_back, contentDescription = "", modifier = Modifier AsyncImage(model = R.drawable.sv_back,
contentDescription = "",
modifier = Modifier
.size(40.dp) .size(40.dp)
.clickable { onBack() } .clickable { onBack() }
.padding(10.dp)) .padding(10.dp))
} }
}, actions = { },
actions = {
Box(modifier = Modifier Box(modifier = Modifier
.size(39.dp) .size(39.dp)
.clickable { showBottomSheetDialog.value = true } .clickable { showBottomSheetDialog.value = true }
.padding(10.dp), contentAlignment = Alignment.Center) { .padding(10.dp), contentAlignment = Alignment.Center) {
AsyncImage(model = R.drawable.sv_setting, contentDescription = "", modifier = Modifier.fillMaxSize()) AsyncImage(model = R.drawable.sv_setting,
contentDescription = "",
modifier = Modifier.fillMaxSize())
} }
}) })
} }
@Composable @Composable
fun StartNavigationView(orderInfo: OrderInfo?, dismiss: () -> Unit) { fun StartNavigationView(orderInfo : OrderInfo?, dismiss : () -> Unit) {
val context = LocalContext.current val context = LocalContext.current
Dialog(onDismissRequest = { dismiss() }) { Dialog(onDismissRequest = { dismiss() }) {
@ -180,50 +247,84 @@ fun StartNavigationView(orderInfo: OrderInfo?, dismiss: () -> Unit) {
.fillMaxWidth() .fillMaxWidth()
.height(180.dp) .height(180.dp)
.background(color = Color.White, shape = RoundedCornerShape(8.dp)) .background(color = Color.White, shape = RoundedCornerShape(8.dp))
.padding(10.dp), verticalAlignment = Alignment.CenterVertically, .padding(10.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround) { horizontalArrangement = Arrangement.SpaceAround) {
if (MapUtil.isGdMapInstalled(context)) { if (MapUtil.isGdMapInstalled(context)) {
Column(modifier = Modifier.clickable { Column(modifier = Modifier.clickable {
if ("SENDTO" == orderInfo?.taskState) { if ("SENDTO" == orderInfo?.taskState) {
MapUtil.startNavigationGd(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) MapUtil.startNavigationGd(context,
orderInfo.distLat,
lng = orderInfo.distLng,
address = orderInfo.distAddress)
} else { } else {
MapUtil.startNavigationGd(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) MapUtil.startNavigationGd(context,
orderInfo?.lat,
lng = orderInfo?.lng,
address = orderInfo?.address)
} }
dismiss() dismiss()
}) { }) {
AsyncImage(model = R.drawable.sv_amap_icon, contentDescription = "", modifier = Modifier.size(60.dp)) AsyncImage(model = R.drawable.sv_amap_icon,
contentDescription = "",
modifier = Modifier.size(60.dp))
Spacer(modifier = Modifier.height(5.dp)) Spacer(modifier = Modifier.height(5.dp))
Text(text = "高德地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) Text(text = "高德地图",
color = Color.Black,
fontWeight = FontWeight.Medium,
fontSize = 14.sp)
} }
} }
if (MapUtil.isBaiduMapInstalled(context)) { if (MapUtil.isBaiduMapInstalled(context)) {
Column(modifier = Modifier.clickable { Column(modifier = Modifier.clickable {
if ("SENDTO" == orderInfo?.taskState) { if ("SENDTO" == orderInfo?.taskState) {
MapUtil.startNavigationBd(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) MapUtil.startNavigationBd(context,
orderInfo.distLat,
lng = orderInfo.distLng,
address = orderInfo.distAddress)
} else { } else {
MapUtil.startNavigationBd(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) MapUtil.startNavigationBd(context,
orderInfo?.lat,
lng = orderInfo?.lng,
address = orderInfo?.address)
} }
dismiss() dismiss()
}) { }) {
AsyncImage(model = R.drawable.sv_baidu_icon, contentDescription = "", modifier = Modifier.size(60.dp)) AsyncImage(model = R.drawable.sv_baidu_icon,
contentDescription = "",
modifier = Modifier.size(60.dp))
Spacer(modifier = Modifier.height(5.dp)) Spacer(modifier = Modifier.height(5.dp))
Text(text = "百度地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) Text(text = "百度地图",
color = Color.Black,
fontWeight = FontWeight.Medium,
fontSize = 14.sp)
} }
} }
if (MapUtil.isTencentInstalled(context)) { if (MapUtil.isTencentInstalled(context)) {
Column(modifier = Modifier.clickable { Column(modifier = Modifier.clickable {
if ("SENDTO" == orderInfo?.taskState) { if ("SENDTO" == orderInfo?.taskState) {
MapUtil.startNavigationTencent(context, orderInfo.distLat, lng = orderInfo.distLng, address = orderInfo.distAddress) MapUtil.startNavigationTencent(context,
orderInfo.distLat,
lng = orderInfo.distLng,
address = orderInfo.distAddress)
} else { } else {
MapUtil.startNavigationTencent(context, orderInfo?.lat, lng = orderInfo?.lng, address = orderInfo?.address) MapUtil.startNavigationTencent(context,
orderInfo?.lat,
lng = orderInfo?.lng,
address = orderInfo?.address)
} }
dismiss() dismiss()
}) { }) {
AsyncImage(model = R.drawable.sv_tencent_icon, contentDescription = "", modifier = Modifier.size(60.dp)) AsyncImage(model = R.drawable.sv_tencent_icon,
contentDescription = "",
modifier = Modifier.size(60.dp))
Spacer(modifier = Modifier.height(5.dp)) Spacer(modifier = Modifier.height(5.dp))
Text(text = "腾讯地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp) Text(text = "腾讯地图",
color = Color.Black,
fontWeight = FontWeight.Medium,
fontSize = 14.sp)
} }
} }
} }

View File

@ -1,8 +1,12 @@
package com.za.ui.servicing.wait_to_start package com.za.ui.servicing.wait_to_start
import android.app.Activity
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -55,16 +59,19 @@ import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.PolylineOptions import com.amap.api.maps.model.PolylineOptions
import com.blankj.utilcode.util.ToastUtils
import com.za.base.BaseActivity import com.za.base.BaseActivity
import com.za.base.theme.headBgColor import com.za.base.theme.headBgColor
import com.za.base.view.CommonDialog import com.za.base.view.CommonDialog
import com.za.common.GlobalData import com.za.common.GlobalData
import com.za.common.log.LogUtil
import com.za.common.util.ImageUtil import com.za.common.util.ImageUtil
import com.za.common.util.ServicingSpeechManager import com.za.common.util.ServicingSpeechManager
import com.za.ext.copy import com.za.ext.copy
import com.za.ext.finish import com.za.ext.finish
import com.za.ext.goNextPage import com.za.ext.goNextPage
import com.za.servicing.R import com.za.servicing.R
import com.za.ui.camera.ZdCameraXActivity
import com.za.ui.servicing.view.InServicingHeadView import com.za.ui.servicing.view.InServicingHeadView
@ -77,19 +84,28 @@ class WaitToStartActivity : BaseActivity() {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) { fun WaitToStartScreen(vm : WaitToStartVm = viewModel()) {
val uiState = vm.uiState.collectAsStateWithLifecycle() val uiState = vm.uiState.collectAsStateWithLifecycle()
val context = LocalContext.current val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current val lifecycleOwner = LocalLifecycleOwner.current
val mapView = remember { MapView(context) } val mapView = remember { MapView(context) }
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))
}
}
// 添加 BottomSheet 状态 // 添加 BottomSheet 状态
val bottomSheetState = rememberStandardBottomSheetState( val bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.Expanded)
initialValue = SheetValue.Expanded val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
)
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = bottomSheetState
)
DisposableEffect(key1 = lifecycleOwner) { DisposableEffect(key1 = lifecycleOwner) {
val observer = LifecycleEventObserver { _, event -> val observer = LifecycleEventObserver { _, event ->
@ -115,245 +131,171 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
if (uiState.value.goNextPage != null) { if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context) goNextPage(uiState.value.goNextPage?.nextState, context)
vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(goNextPage = null)))
} }
if (uiState.value.isGoNextPageDialog == true) { if (uiState.value.showServicePeopleConfirmDialog == true) {
CommonDialog( CommonDialog(cancelText = "取消",
cancelText = "取消", confirmText = "去拍照",
confirmText = "前往下一步", title = "服务人员确认",
title = "是否前往下一步?",
cancelEnable = true, cancelEnable = true,
cancel = { cancel = {
vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(
showServicePeopleConfirmDialog = false)))
},
dismiss = {
vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(
showServicePeopleConfirmDialog = false)))
}, },
dismiss = { vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) },
confirm = { confirm = {
vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = false))) vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(
vm.dispatch(WaitToStartVm.Action.UpdateTask) showServicePeopleConfirmDialog = false)))
} val intent = Intent(context, ZdCameraXActivity::class.java)
) intent.putExtra("isBack", false)
getResult.launch(intent)
})
} }
BottomSheetScaffold( BottomSheetScaffold(scaffoldState = scaffoldState,
scaffoldState = scaffoldState,
topBar = { topBar = {
InServicingHeadView( InServicingHeadView(title = "调度成功,等待发车",
title = "调度成功,等待发车",
onBack = { context.finish() }, onBack = { context.finish() },
orderInfo = uiState.value.orderInfo orderInfo = uiState.value.orderInfo)
)
}, },
sheetContent = { sheetContent = {
Column( Column(modifier = Modifier
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())) { // 滑动指示器
) { Box(modifier = Modifier
// 滑动指示器
Box(
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 8.dp), .padding(vertical = 8.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center) {
) { Box(modifier = Modifier
Box(
modifier = Modifier
.width(32.dp) .width(32.dp)
.height(4.dp) .height(4.dp)
.background( .background(color = Color(0xFFE0E0E0), shape = RoundedCornerShape(2.dp)))
color = Color(0xFFE0E0E0),
shape = RoundedCornerShape(2.dp)
)
)
} }
// 距离和时间信息 // 距离和时间信息
Row( Row(modifier = Modifier
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp), .padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically) {
) { Text(text = if (uiState.value.estimatedArrivalTime.isNotEmpty()) "预计到达: ${uiState.value.estimatedArrivalTime}"
Text( else "计算中...", color = Color(0xFF666666), fontSize = 14.sp)
text = if (uiState.value.estimatedArrivalTime.isNotEmpty())
"预计到达: ${uiState.value.estimatedArrivalTime}"
else
"计算中...",
color = Color(0xFF666666),
fontSize = 14.sp
)
Text( Text(text = if (uiState.value.remainingDistance > 0) "距离救援地: %.1fkm".format(
text = if (uiState.value.remainingDistance > 0) uiState.value.remainingDistance / 1000f)
"距离救援地: %.1fkm".format(uiState.value.remainingDistance / 1000f) else "计算中...", color = Color(0xFFFF4D4F), fontSize = 14.sp)
else
"计算中...",
color = Color(0xFFFF4D4F),
fontSize = 14.sp
)
} }
HorizontalDivider( HorizontalDivider(modifier = Modifier
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.alpha(0.1f) .alpha(0.1f))
)
// 订单信息 // 订单信息
Column( Column(modifier = Modifier
modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp) .padding(horizontal = 16.dp, vertical = 12.dp)) { // 订单类型
) { Text(text = uiState.value.orderInfo?.serviceTypeName ?: "",
// 订单类型
Text(
text = uiState.value.orderInfo?.serviceTypeName ?: "",
fontSize = 18.sp, fontSize = 18.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = Color.Black color = Color.Black)
)
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
// 订单标签 // 订单标签
Row( Row(verticalAlignment = Alignment.CenterVertically,
verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
horizontalArrangement = Arrangement.spacedBy(8.dp) Box(modifier = Modifier
) {
Box(
modifier = Modifier
.background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp)) .background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp))
.padding(horizontal = 6.dp, vertical = 2.dp) .padding(horizontal = 6.dp, vertical = 2.dp)) {
) { Text(text = "月结".takeIf { uiState.value.orderInfo?.settleType == 1 }
Text( ?: "现金", color = Color.White, fontSize = 12.sp)
text = "月结".takeIf { uiState.value.orderInfo?.settleType == 1 }
?: "现金",
color = Color.White,
fontSize = 12.sp
)
} }
Text( Text(text = uiState.value.orderInfo?.orderSource ?: "",
text = uiState.value.orderInfo?.orderSource ?: "",
color = Color.Black, color = Color.Black,
fontSize = 12.sp fontSize = 12.sp)
)
Text( Text(text = uiState.value.orderInfo?.addressProperty ?: "",
text = uiState.value.orderInfo?.addressProperty ?: "",
color = Color(0xFFFD8205), color = Color(0xFFFD8205),
fontSize = 12.sp, fontSize = 12.sp,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium)
)
} }
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
// 订单号 // 订单号
Row( Row(verticalAlignment = Alignment.CenterVertically,
verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clickable {
modifier = Modifier.clickable { uiState.value.orderInfo?.taskCode?.copy(context) } uiState.value.orderInfo?.taskCode?.copy(context)
) { }) {
Text( Text(text = "单号", color = Color(0xFF999999), fontSize = 13.sp)
text = "单号",
color = Color(0xFF999999),
fontSize = 13.sp
)
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text( Text(text = uiState.value.orderInfo?.taskCode ?: "",
text = uiState.value.orderInfo?.taskCode ?: "",
color = Color(0xFF666666), color = Color(0xFF666666),
fontSize = 14.sp fontSize = 14.sp)
)
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
AsyncImage( AsyncImage(model = R.drawable.sv_copy,
model = R.drawable.sv_copy,
contentDescription = "copy", contentDescription = "copy",
modifier = Modifier.size(16.dp) modifier = Modifier.size(16.dp))
)
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// 地址信息 // 地址信息
Column( Column(verticalArrangement = Arrangement.spacedBy(16.dp)) { // 救援地
verticalArrangement = Arrangement.spacedBy(16.dp) Row(verticalAlignment = Alignment.Top,
) { modifier = Modifier.clickable { // 点击救援地时移动地图到救援位置
// 救援地
Row(
verticalAlignment = Alignment.Top,
modifier = Modifier.clickable {
// 点击救援地时移动地图到救援位置
uiState.value.orderInfo?.let { order -> uiState.value.orderInfo?.let { order ->
if (order.lat != null && order.lat != 0.0 && if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0) {
order.lng != null && order.lng != 0.0 mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom(
) { LatLng(order.lat !!, order.lng !!),
mapView.map.animateCamera( 16f))
CameraUpdateFactory.newLatLngZoom(
LatLng(order.lat!!, order.lng!!),
16f
)
)
} }
} }
} }) {
) { AsyncImage(model = R.drawable.sv_rescuing,
AsyncImage(
model = R.drawable.sv_rescuing,
contentDescription = "rescue", contentDescription = "rescue",
modifier = Modifier.size(16.dp) modifier = Modifier.size(16.dp))
)
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text( Text(text = uiState.value.orderInfo?.address ?: "",
text = uiState.value.orderInfo?.address ?: "",
color = Color.Black, color = Color.Black,
fontSize = 15.sp, fontSize = 15.sp,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium)
)
} }
// 目的地 // 目的地
if (!uiState.value.orderInfo?.distAddress.isNullOrBlank()) { if (! uiState.value.orderInfo?.distAddress.isNullOrBlank()) {
Row( Row(verticalAlignment = Alignment.Top,
verticalAlignment = Alignment.Top, modifier = Modifier.clickable { // 点击目的地时移动地图到目的地位置
modifier = Modifier.clickable {
// 点击目的地时移动地图到目的地位置
uiState.value.orderInfo?.let { order -> uiState.value.orderInfo?.let { order ->
if (order.distLat != null && order.distLat != 0.0 && if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0) {
order.distLng != null && order.distLng != 0.0 mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom(
) { LatLng(order.distLat !!, order.distLng !!),
mapView.map.animateCamera( 16f))
CameraUpdateFactory.newLatLngZoom(
LatLng(order.distLat!!, order.distLng!!),
16f
)
)
} }
} }
} }) {
) { AsyncImage(model = R.drawable.sv_dist,
AsyncImage(
model = R.drawable.sv_dist,
contentDescription = "destination", contentDescription = "destination",
modifier = Modifier.size(16.dp) modifier = Modifier.size(16.dp))
)
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Text( Text(text = uiState.value.orderInfo?.distAddress ?: "",
text = uiState.value.orderInfo?.distAddress ?: "",
color = Color.Black, color = Color.Black,
fontSize = 15.sp, fontSize = 15.sp,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium)
)
} }
} }
} }
@ -361,23 +303,20 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// 发车按钮 // 发车按钮
Button( Button(onClick = {
onClick = { vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(isGoNextPageDialog = true))) }, vm.dispatch(WaitToStartVm.Action.UpdateState(uiState.value.copy(
showServicePeopleConfirmDialog = true)))
},
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(44.dp) .height(44.dp)
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(containerColor = headBgColor),
containerColor = headBgColor shape = RoundedCornerShape(8.dp)) {
), Text(text = "发车",
shape = RoundedCornerShape(8.dp)
) {
Text(
text = "发车",
color = Color.White, color = Color.White,
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium)
)
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@ -388,16 +327,11 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp),
sheetContainerColor = Color.White, sheetContainerColor = Color.White,
sheetDragHandle = null, sheetDragHandle = null,
sheetSwipeEnabled = true sheetSwipeEnabled = true) { paddingValues ->
) { paddingValues -> Box(modifier = Modifier
Box(
modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(paddingValues) .padding(paddingValues)) {
) { AndroidView(modifier = Modifier.fillMaxSize(), factory = {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = {
AMapLocationClient.updatePrivacyShow(context, true, true) AMapLocationClient.updatePrivacyShow(context, true, true)
AMapLocationClient.updatePrivacyAgree(context, true) AMapLocationClient.updatePrivacyAgree(context, true)
mapView.apply { mapView.apply {
@ -405,13 +339,12 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
isTrafficEnabled = false isTrafficEnabled = false
isMyLocationEnabled = false isMyLocationEnabled = false
uiSettings.isMyLocationButtonEnabled = false uiSettings.isMyLocationButtonEnabled = false
uiSettings.setLogoBottomMargin(-100) uiSettings.setLogoBottomMargin(- 100)
uiSettings.isZoomControlsEnabled = false uiSettings.isZoomControlsEnabled = false
// 修改标记点点击事件 // 修改标记点点击事件
setOnMarkerClickListener { marker -> setOnMarkerClickListener { marker ->
marker.showInfoWindow() marker.showInfoWindow() // 800ms后隐藏信息窗口
// 800ms后隐藏信息窗口
Handler(Looper.getMainLooper()).postDelayed({ Handler(Looper.getMainLooper()).postDelayed({
marker.hideInfoWindow() marker.hideInfoWindow()
}, 800) }, 800)
@ -419,111 +352,73 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
} }
} }
} }
}, }, update = { // 清除旧标记和路线
update = {
// 清除旧标记和路线
mapView.map.clear() mapView.map.clear()
// 先绘制路线 // 先绘制路线
uiState.value.routePoints?.let { points -> uiState.value.routePoints?.let { points ->
mapView.map.addPolyline( mapView.map.addPolyline(PolylineOptions().addAll(points).width(15f)
PolylineOptions()
.addAll(points)
.width(15f)
.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.icon_road_green_arrow)) .setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.icon_road_green_arrow))
.zIndex(1f) .zIndex(1f))
)
} }
// 再添加标记点,确保标记点在路线上层 // 再添加标记点,确保标记点在路线上层
// 添加当前位置标记 // 添加当前位置标记
if (GlobalData.currentLocation != null) { if (GlobalData.currentLocation != null) {
mapView.map.addMarker( mapView.map.addMarker(MarkerOptions().position(LatLng(GlobalData.currentLocation?.latitude !!,
MarkerOptions() GlobalData.currentLocation?.longitude !!)).title("当前位置")
.position(LatLng( .icon(ImageUtil.vectorToBitmap(context, R.drawable.ic_current_location))
GlobalData.currentLocation?.latitude!!, .anchor(0.5f, 0.5f).visible(true))
GlobalData.currentLocation?.longitude!!
))
.title("当前位置")
.icon(ImageUtil.vectorToBitmap(context,R.drawable.ic_current_location))
.anchor(0.5f, 0.5f)
.visible(true)
)
} }
// 添加救援地标记 // 添加救援地标记
uiState.value.orderInfo?.let { order -> uiState.value.orderInfo?.let { order ->
if (order.lat != null && order.lat != 0.0 && if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0 && GlobalData.currentLocation != null) {
order.lng != null && order.lng != 0.0 && mapView.map.addMarker(MarkerOptions().position(LatLng(order.lat !!,
GlobalData.currentLocation != null order.lng !!)).title("救援地点")
) {
mapView.map.addMarker(
MarkerOptions()
.position(LatLng(order.lat!!, order.lng!!))
.title("救援地点")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map)) .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map))
.anchor(0.5f, 0.5f) .anchor(0.5f, 0.5f))
)
} }
// 添加目的地标记 // 添加目的地标记
if (order.distLat != null && order.distLat != 0.0 && if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0 && GlobalData.currentLocation != null) {
order.distLng != null && order.distLng != 0.0 && mapView.map.addMarker(MarkerOptions().position(LatLng(order.distLat !!,
GlobalData.currentLocation != null order.distLng !!)).title("目的地")
) {
mapView.map.addMarker(
MarkerOptions()
.position(LatLng(order.distLat!!, order.distLng!!))
.title("目的地")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map)) .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map))
.anchor(0.5f, 0.5f) .anchor(0.5f, 0.5f))
)
} }
} }
// 最后调整地图显示范围 // 最后调整地图显示范围
// 计算地图显示范围 // 计算地图显示范围
val bounds = LatLngBounds.Builder().apply { val bounds = LatLngBounds.Builder().apply { // 添加当前位置
// 添加当前位置
GlobalData.currentLocation?.let { GlobalData.currentLocation?.let {
include(LatLng(it.latitude, it.longitude)) include(LatLng(it.latitude, it.longitude))
} }
// 添加救援地点 // 添加救援地点
uiState.value.orderInfo?.let { order -> uiState.value.orderInfo?.let { order ->
if (order.lat != null && order.lat != 0.0 && if (order.lat != null && order.lat != 0.0 && order.lng != null && order.lng != 0.0) {
order.lng != null && order.lng != 0.0 include(LatLng(order.lat !!, order.lng !!))
) {
include(LatLng(order.lat!!, order.lng!!))
} }
// 添加目的地 // 添加目的地
if (order.distLat != null && order.distLat != 0.0 && if (order.distLat != null && order.distLat != 0.0 && order.distLng != null && order.distLng != 0.0) {
order.distLng != null && order.distLng != 0.0 include(LatLng(order.distLat !!, order.distLng !!))
) {
include(LatLng(order.distLat!!, order.distLng!!))
} }
} }
}.build() }.build()
// 调整地图显示范围,确保所有点都可见 // 调整地图显示范围,确保所有点都可见
try { try {
mapView.map.animateCamera( mapView.map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100))
CameraUpdateFactory.newLatLngBounds(bounds, 100) } catch (e : Exception) { // 如果计算边界失败,则使用默认缩放级别
)
} catch (e: Exception) {
// 如果计算边界失败,则使用默认缩放级别
GlobalData.currentLocation?.let { GlobalData.currentLocation?.let {
mapView.map.animateCamera( mapView.map.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(it.latitude,
CameraUpdateFactory.newLatLngZoom( it.longitude), 15f))
LatLng(it.latitude, it.longitude),
15f
)
)
} }
} }
} })
)
} }
} }
} }

View File

@ -15,20 +15,27 @@ import com.blankj.utilcode.util.ToastUtils
import com.za.base.IServicingVm import com.za.base.IServicingVm
import com.za.base.view.LoadingManager import com.za.base.view.LoadingManager
import com.za.bean.db.order.OrderInfo 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.UpdateTaskBean
import com.za.bean.request.UpdateTaskRequest import com.za.bean.request.UpdateTaskRequest
import com.za.common.GlobalData import com.za.common.GlobalData
import com.za.common.log.LogUtil import com.za.common.log.LogUtil
import com.za.ext.toJson import com.za.ext.toJson
import com.za.net.BaseObserver
import com.za.net.CommonMethod import com.za.net.CommonMethod
import com.za.net.RetrofitHelper
import com.za.service.location.ZdLocationManager import com.za.service.location.ZdLocationManager
import com.za.servicing.R 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.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@ -47,6 +54,7 @@ class WaitToStartVm : IServicingVm<WaitToStartVm.Action, WaitToStartVm.UiState>(
is Action.UpdateState -> updateState(action.uiState) is Action.UpdateState -> updateState(action.uiState)
is Action.StartTimer -> startTimer() is Action.StartTimer -> startTimer()
is Action.UpdateTimer -> updateTimer() is Action.UpdateTimer -> updateTimer()
is Action.CompareServicePeople -> compareServicePeople(action.localPath)
} }
} }
@ -216,6 +224,52 @@ class WaitToStartVm : IServicingVm<WaitToStartVm.Action, WaitToStartVm.UiState>(
private fun updateTimer() { // 在这里处理倒计时更新逻辑 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<IaiCompareFaceBean>() {
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() { override fun onCleared() {
super.onCleared() super.onCleared()
timerJob?.cancel() timerJob?.cancel()
@ -227,14 +281,15 @@ class WaitToStartVm : IServicingVm<WaitToStartVm.Action, WaitToStartVm.UiState>(
data class UpdateState(val uiState : UiState) : Action() data class UpdateState(val uiState : UiState) : Action()
data object StartTimer : Action() data object StartTimer : Action()
data object UpdateTimer : Action() data object UpdateTimer : Action()
data class CompareServicePeople(val localPath : String) : Action()
} }
data class UiState(val orderInfo : OrderInfo? = null, data class UiState(val orderInfo : OrderInfo? = null,
val showCallPhoneDialog : Boolean? = false, val showCallPhoneDialog : Boolean? = false,
val markers : ArrayList<MarkerOptions>? = null, val markers : ArrayList<MarkerOptions>? = null,
val goNextPage : UpdateTaskBean? = null, val goNextPage : UpdateTaskBean? = null,
val isGoNextPageDialog : Boolean? = null,
val routePoints : List<LatLng>? = null, val routePoints : List<LatLng>? = null,
val remainingDistance : Float = 0f, val remainingDistance : Float = 0f,
val showServicePeopleConfirmDialog : Boolean? = false,
val estimatedArrivalTime : String = "") val estimatedArrivalTime : String = "")
} }

View File

@ -1,14 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="11dp" android:width="128dp"
android:height="11dp" android:height="128dp"
android:viewportWidth="11" android:viewportWidth="1024"
android:viewportHeight="11"> android:viewportHeight="1024">
<path <path
android:pathData="M3.25,8.804L3.26,8.793L7.74,8.793C8.301,8.793 8.76,8.334 8.76,7.773L8.76,4.257L8.757,1.244L8.76,1.245L8.76,1.053C8.76,0.492 8.301,0.033 7.74,0.033L1.02,0.033C0.459,0.033 0,0.492 0,1.053L0,7.773C0,8.334 0.459,8.793 1.02,8.793L2.14,8.793L2.15,8.804L3.25,8.804ZM7.18,7.872L1.58,7.872C1.189,7.872 0.921,7.604 0.921,7.213L0.921,1.613C0.921,1.222 1.189,0.953 1.58,0.953L7.18,0.953C7.571,0.953 7.84,1.222 7.84,1.613L7.84,7.213C7.84,7.604 7.571,7.872 7.18,7.872ZM9.98,11.033C10.541,11.033 11,10.574 11,10.013L11,3.293C11,2.732 10.541,2.273 9.98,2.273L9.556,2.273L9.557,3.205C9.872,3.261 10.079,3.51 10.079,3.853L10.079,9.453C10.079,9.844 9.811,10.112 9.42,10.112L3.82,10.112C3.482,10.112 3.235,9.911 3.175,9.604L2.239,9.604L2.24,10.013C2.24,10.574 2.699,11.033 3.26,11.033L9.98,11.033Z" 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.8312872" android:strokeAlpha="0.3"
android:strokeWidth="1" android:fillColor="#1A73E8"
android:fillColor="#9197AB" android:fillAlpha="0.3"/>
android:fillType="nonZero" <path
android:strokeColor="#00000000" android:pathData="M437.4,347.9h313.3c58,0 89.5,31.5 89.5,89.5v313.3c0,58 -31.5,89.5 -89.5,89.5H437.4c-58,0 -89.5,-31.5 -89.5,-89.5V437.4c0,-58 31.5,-89.5 89.5,-89.5z"
android:fillAlpha="0.8312872"/> android:fillColor="#1A73E8"/>
</vector> </vector>

View File

@ -18,4 +18,5 @@
9.拖车服务时,救援人员仅按照道路救援中心的指令,将车辆拖往指定目的地,如果顾客需要变更拖车目的地,请与道路救援中心联系。\n 9.拖车服务时,救援人员仅按照道路救援中心的指令,将车辆拖往指定目的地,如果顾客需要变更拖车目的地,请与道路救援中心联系。\n
10.顾客如果要求自费服务项目,请与第三方公司或人员协商相关费用并现场向其支付。因为此类服务发生任何争议,请与数援人员双方自行解决,救援中心不再介入和负责。\n 10.顾客如果要求自费服务项目,请与第三方公司或人员协商相关费用并现场向其支付。因为此类服务发生任何争议,请与数援人员双方自行解决,救援中心不再介入和负责。\n
11.服务完成后客户接收车辆时,应再次签字确认服务完成及车辆无损,中道救援不接受客户己在服务完成记录中签字后的任何索赔和投诉:若接车方为维修站,且维修站接车员签字确认车辆无损,则事后发现的任何车辆损伤及相关责任应由维修站承担。如客户认为被救车辆损伤由中道救援服务商造成,应出具权威部门出具的检测报告,中道救援将根据检测报告确定服务商是否进行赔偿。</string> 11.服务完成后客户接收车辆时,应再次签字确认服务完成及车辆无损,中道救援不接受客户己在服务完成记录中签字后的任何索赔和投诉:若接车方为维修站,且维修站接车员签字确认车辆无损,则事后发现的任何车辆损伤及相关责任应由维修站承担。如客户认为被救车辆损伤由中道救援服务商造成,应出具权威部门出具的检测报告,中道救援将根据检测报告确定服务商是否进行赔偿。</string>
<string name="title_activity_service_people_confirm">ServicePeopleConfirmActivity</string>
</resources> </resources>

View File

@ -2,4 +2,6 @@
<resources> <resources>
<style name="Theme.Dealer" parent="Theme.AppCompat.Light.NoActionBar" /> <style name="Theme.Dealer" parent="Theme.AppCompat.Light.NoActionBar" />
<style name="Theme.Zd_sdk_demo" parent="android:Theme.Material.Light.NoActionBar" />
</resources> </resources>

BIN
zd_sdk_demo.jks Normal file

Binary file not shown.