refactor(user): 重构司机信息存储逻辑

- 将司机信息从 MMKV 迁移到 Room 数据库
- 新增 DriverInfoBean 实体类和 DriverInfoDao接口
- 更新 GlobalData 中的 driverInfo 相关逻辑- 修改相关 Activity 和 ViewModel 中的代码,使用新的数据库存储方式- 优化了司机信息的获取和更新流程
This commit is contained in:
songzhiling
2025-04-16 15:58:07 +08:00
parent d2f2752499
commit 0f24648cb1
53 changed files with 1259 additions and 1272 deletions

View File

@ -4,7 +4,7 @@
<uses-sdk tools:overrideLibrary="androidx.camera.view,androidx.camera:camera-camera2,androidx.camera.camera2,androidx.camera.lifecycle,androidx.camera.core" />
<permission
android:name="${applicationId}.permission.JPUSH_MESSAGE"
android:name="com.za.rescue.dealer.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" /> <!-- 位置相关权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
@ -243,7 +243,10 @@
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<service
android:name="cn.jpush.android.service.DaemonService"
android:enabled="true"
android:exported="true" />
</application>
</manifest>

View File

@ -78,9 +78,9 @@ object AppConfig {
*/
fun getTrainUrl(keyWord: String = ""): String {
if (keyWord.isEmpty()) {
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfo?.userId}"
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
}
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfo?.userId}&keyword=$keyWord"
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
}
/**
@ -91,8 +91,8 @@ object AppConfig {
*/
fun getDocmentUrl(keyWord: String = ""): String {
if (keyWord.isEmpty()) {
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfo?.userId}"
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
}
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfo?.userId}&keyword=$keyWord"
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
}
}

View File

@ -12,64 +12,14 @@ data class DriverInfo(
var userName : String? = null, //用户姓名
var userPhone : String? = null, //用户手机号
var callphone : String? = null,
var supplierId : String? = null, //经销商id
var supplierId : Int? = null, //经销商id
var supplierName : String? = null, //经销商名称
var supplierType : Int? = null, //经销商类型 1子公司 2供应商
var loginLogId : Int? = null,
var serviceList : List<String>? = null, //车辆服务列表
var assistUserCode : String? = null,
val authStatus : Int? = null, // 0 未认证 1 已认证
) : Parcelable {
constructor(parcel : Parcel) : this(parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
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.readValue(Int::class.java.classLoader) as? Int,
parcel.createStringArrayList(),
parcel.readString(),
parcel.readValue(Int::class.java.classLoader) as? Int) {
}
override fun writeToParcel(parcel : Parcel, flags : Int) {
parcel.writeString(userPortrait)
parcel.writeString(token)
parcel.writeString(rongyunToken)
parcel.writeString(logTime)
parcel.writeValue(userId)
parcel.writeString(userName)
parcel.writeString(userPhone)
parcel.writeString(callphone)
parcel.writeString(supplierId)
parcel.writeString(supplierName)
parcel.writeValue(supplierType)
parcel.writeValue(loginLogId)
parcel.writeStringList(serviceList)
parcel.writeString(assistUserCode)
parcel.writeValue(authStatus)
}
override fun describeContents() : Int {
return 0
}
companion object CREATOR : Parcelable.Creator<DriverInfo> {
override fun createFromParcel(parcel : Parcel) : DriverInfo {
return DriverInfo(parcel)
}
override fun newArray(size : Int) : Array<DriverInfo?> {
return arrayOfNulls(size)
}
}
}
)
data class GeneralInfo(
var userId : Int? = null, //用户id
@ -214,3 +164,56 @@ data class LoginWithTaskBean(val supplierName : String? = null,
val jobNumber : String? = null,
val vehicleId : Int? = null,
val supplierType : Int? = null)
data class AppNewDriverInfoDTO(val userId : Int? = null,
val userName : String? = null,
val userPhone : String? = null,
val supplierCode : String? = null,
val appLoginCode : String? = null,
val supplierId : Int? = null,
val supplierName : String? = null,
val supplierType : Int? = null,
val authStatus : Int? = null,
val tiedVehicle : VehicleInfo? = null, //绑定的车辆,如果该服务商下面绑定的有车辆,则返回绑定车辆信息
val loginTime : String? = null) : Parcelable {
constructor(parcel : Parcel) : this(parcel.readValue(Int::class.java.classLoader) as? Int,
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.readParcelable(VehicleInfo::class.java.classLoader),
parcel.readString()) {
}
override fun writeToParcel(parcel : Parcel, flags : Int) {
parcel.writeValue(userId)
parcel.writeString(userName)
parcel.writeString(userPhone)
parcel.writeString(supplierCode)
parcel.writeString(appLoginCode)
parcel.writeValue(supplierId)
parcel.writeString(supplierName)
parcel.writeValue(supplierType)
parcel.writeValue(authStatus)
parcel.writeParcelable(tiedVehicle, flags)
parcel.writeString(loginTime)
}
override fun describeContents() : Int {
return 0
}
companion object CREATOR : Parcelable.Creator<AppNewDriverInfoDTO> {
override fun createFromParcel(parcel : Parcel) : AppNewDriverInfoDTO {
return AppNewDriverInfoDTO(parcel)
}
override fun newArray(size : Int) : Array<AppNewDriverInfoDTO?> {
return arrayOfNulls(size)
}
}
}

View File

@ -4,53 +4,83 @@ import android.os.Parcel
import android.os.Parcelable
data class VehicleInfo(
var vehicleId: Int? = null, //车辆id
var vehicleName: String? = null,//车辆名称(车牌号)
var userName: String? = null, //当前用车司机姓名(工号)
var userPhone: String? = null, //当前用车司机电话
var status: Int? = null, //车辆状态 0 不在线 1 在线
val plateNumber: String? = null, //车牌号
var vehicleState: Int? = null, //车辆是否空闲 0 空闲 1 忙碌 2置忙 8维修
var terminalId: Long? = null, //车辆高德tid
var exitMileage: Int? = null, //上次退出公里数
var supplierType: Int? = null, //经销商类型
var vehicleId : Int? = null, //车辆id
var vehicleName : String? = null, //车辆名称(车牌号)
var userName : String? = null, //当前用车司机姓名(工号)
var userPhone : String? = null, //当前用车司机电话
var status : Int? = null, //车辆状态 0 不在线 1 在线
val plateNumber : String? = null, //车牌号
var vehicleState : Int? = null, //车辆是否空闲 0 空闲 1 忙碌 2置忙 8维修
var terminalId : Long? = null, //车辆高德tid
var exitMileage : Int? = null, //上次退出公里数
var supplierType : Int? = null, //经销商类型
) : Parcelable {
constructor(parcel : Parcel) : this(parcel.readValue(Int::class.java.classLoader) as? Int,
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(Long::class.java.classLoader) as? Long,
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.readValue(Int::class.java.classLoader) as? Int) {
}
constructor(parcel : Parcel) : this(parcel.readValue(Int::class.java.classLoader) as? Int,
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(Long::class.java.classLoader) as? Long,
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.readValue(Int::class.java.classLoader) as? Int) {
}
override fun writeToParcel(parcel : Parcel, flags : Int) {
parcel.writeValue(vehicleId)
parcel.writeString(vehicleName)
parcel.writeString(userName)
parcel.writeString(userPhone)
parcel.writeValue(status)
parcel.writeString(plateNumber)
parcel.writeValue(vehicleState)
parcel.writeValue(terminalId)
parcel.writeValue(exitMileage)
parcel.writeValue(supplierType)
}
override fun writeToParcel(parcel : Parcel, flags : Int) {
parcel.writeValue(vehicleId)
parcel.writeString(vehicleName)
parcel.writeString(userName)
parcel.writeString(userPhone)
parcel.writeValue(status)
parcel.writeString(plateNumber)
parcel.writeValue(vehicleState)
parcel.writeValue(terminalId)
parcel.writeValue(exitMileage)
parcel.writeValue(supplierType)
}
override fun describeContents() : Int {
return 0
}
override fun describeContents() : Int {
return 0
}
companion object CREATOR : Parcelable.Creator<VehicleInfo> {
override fun createFromParcel(parcel : Parcel) : VehicleInfo {
return VehicleInfo(parcel)
}
companion object CREATOR : Parcelable.Creator<VehicleInfo> {
override fun createFromParcel(parcel : Parcel) : VehicleInfo {
return VehicleInfo(parcel)
}
override fun newArray(size : Int) : Array<VehicleInfo?> {
return arrayOfNulls(size)
}
}
override fun newArray(size : Int) : Array<VehicleInfo?> {
return arrayOfNulls(size)
}
}
}
data class LastLoginBean(val phone : String? = null,
val supplierId : Int? = null,
val vehicleId : Int?):Parcelable {
constructor(parcel : Parcel) : this(parcel.readString(),
parcel.readValue(Int::class.java.classLoader) as? Int,
parcel.readValue(Int::class.java.classLoader) as? Int) {
}
override fun writeToParcel(parcel : Parcel, flags : Int) {
parcel.writeString(phone)
parcel.writeValue(supplierId)
parcel.writeValue(vehicleId)
}
override fun describeContents() : Int {
return 0
}
companion object CREATOR : Parcelable.Creator<LastLoginBean> {
override fun createFromParcel(parcel : Parcel) : LastLoginBean {
return LastLoginBean(parcel)
}
override fun newArray(size : Int) : Array<LastLoginBean?> {
return arrayOfNulls(size)
}
}
}

View File

@ -0,0 +1,3 @@
package com.za.bean.request
data class AppNewOrderVoiceRequest(var voiceWords : String? = null)

View File

@ -4,10 +4,9 @@ import android.app.Application
import com.amap.api.location.AMapLocation
import com.blankj.utilcode.util.AppUtils
import com.tencent.mmkv.MMKV
import com.za.bean.DriverInfo
import com.za.bean.VehicleInfo
import com.za.bean.db.order.OrderInfo
import com.za.room.RoomHelper
import com.za.room.db.user.DriverInfoBean
object GlobalData {
lateinit var application : Application
@ -16,20 +15,19 @@ object GlobalData {
var token : String? = null
get() {
return MMKV.defaultMMKV().decodeString("TOKEN", null)
return MMKV.defaultMMKV().decodeString("ZD_TOKEN", null)
}
set(value) {
MMKV.defaultMMKV().encode("TOKEN", value)
MMKV.defaultMMKV().encode("ZD_TOKEN", value)
field = value
}
//记录上次登录的手机号
var lastLoginPhone : String? = null
var regid : String? = null
get() {
return MMKV.defaultMMKV().decodeString("lastLoginPhone", null)
return MMKV.defaultMMKV().decodeString("regid", null)
}
set(value) {
MMKV.defaultMMKV().encode("lastLoginPhone", value)
MMKV.defaultMMKV().encode("regid", value)
field = value
}
@ -42,25 +40,19 @@ object GlobalData {
field = value
}
var driverInfo : DriverInfo? = null
//新订单是否已经被处理
var isHandlerNewOrder : Boolean? = false
var driverInfoBean : DriverInfoBean? = null
get() {
return MMKV.defaultMMKV().decodeParcelable("driverInfo", DriverInfo::class.java)
val driverInfoBean = RoomHelper.db?.driverInfoDao()?.getDriverInfoFromUserId()
field = driverInfoBean
return driverInfoBean
}
set(value) {
MMKV.defaultMMKV().encode("driverInfo", value)
field = value
RoomHelper.db?.driverInfoDao()?.updateDriverInfo(value)
}
var vehicleInfo : VehicleInfo? = null
get() {
return MMKV.defaultMMKV().decodeParcelable("vehicleInfo", VehicleInfo::class.java)
}
set(value) {
MMKV.defaultMMKV().encode("vehicleInfo", value)
field = value
}
var currentOrder : OrderInfo? = null
get() {
return MMKV.defaultMMKV().decodeParcelable("currentOrder", OrderInfo::class.java)
@ -77,11 +69,10 @@ object GlobalData {
var currentLocation : AMapLocation? = null
get() {
return MMKV.defaultMMKV().decodeParcelable("currentLocation", AMapLocation::class.java)
return field
}
set(value) {
value?.time = System.currentTimeMillis()
MMKV.defaultMMKV().encode("currentLocation", value)
field = value
}
@ -97,8 +88,6 @@ object GlobalData {
fun clearUserCache() {
token = null
aesKey = null
driverInfo = null
vehicleInfo = null
currentLocation = null
loginTime = null
}

View File

@ -3,7 +3,6 @@ package com.za.common
import android.app.Application
import com.tencent.bugly.Bugly
import com.tencent.mmkv.MMKV
import com.tencent.mmkv.MMKVLogLevel
import com.za.base.AppConfig
import com.za.common.log.LogUtil
import com.za.room.RoomHelper
@ -11,6 +10,7 @@ import com.za.service.location.ZdLocationManager
object ZDManager {
lateinit var application : Application
fun init(application : Application, isRelease : Boolean = false) {
this.application = application
thirdSdkInit(isRelease)
@ -22,8 +22,9 @@ object ZDManager {
} else {
AppConfig.crm1()
}
GlobalData.application = application
MMKV.initialize(application, MMKVLogLevel.LevelInfo)
GlobalData.application = application // 在 Application 中初始化 MMKV所有进程共享同一存储路径
val rootDir = application.filesDir.absolutePath + "/mmkv"
MMKV.initialize(application, rootDir)
Bugly.init(application, "6972a6b56d", true)
LogUtil.init(application)
RoomHelper.init(application)

View File

@ -15,7 +15,6 @@ import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.TimeUtils
import com.za.common.GlobalData
import com.za.common.util.AppFileManager
import com.za.servicing.BuildConfig
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -40,278 +39,272 @@ import java.util.concurrent.atomic.AtomicBoolean
import kotlin.concurrent.thread
object LogUtil {
private var context: Application? = null
private var logDestinationPath: String? = null
private var orderLogDirPath: String? = null
private var normalLogDirPath: String? = null
private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private val logBuffer = StringBuilder()
private val isWriting = AtomicBoolean(false)
private var context : Application? = null
private var logDestinationPath : String? = null
private var orderLogDirPath : String? = null
private var normalLogDirPath : String? = null
private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private val logBuffer = StringBuilder()
private val isWriting = AtomicBoolean(false)
fun init(context: Application) {
this.context = context
fun init(context : Application) {
this.context = context
logDestinationPath = AppFileManager.getLogPath(context).also { path ->
createDirectoryIfNotExists(path)
orderLogDirPath = "$path${File.separator}order_log".also { createDirectoryIfNotExists(it) }
normalLogDirPath = "$path${File.separator}normal_log".also { createDirectoryIfNotExists(it) }
}
logDestinationPath = AppFileManager.getLogPath(context).also { path ->
createDirectoryIfNotExists(path)
orderLogDirPath =
"$path${File.separator}order_log".also { createDirectoryIfNotExists(it) }
normalLogDirPath =
"$path${File.separator}normal_log".also { createDirectoryIfNotExists(it) }
}
initializeWorkManager(context)
}
initializeWorkManager(context)
}
private fun createDirectoryIfNotExists(path: String) {
File(path).apply { if (!exists()) mkdir() }
}
private fun createDirectoryIfNotExists(path : String) {
File(path).apply { if (! exists()) mkdir() }
}
private fun initializeWorkManager(context: Application) {
if (!WorkManager.isInitialized()) {
WorkManager.initialize(context, Configuration.Builder()
.setMinimumLoggingLevel(Log.INFO)
.build())
}
private fun initializeWorkManager(context : Application) {
if (! WorkManager.isInitialized()) {
WorkManager.initialize(context,
Configuration.Builder().setMinimumLoggingLevel(Log.INFO).build())
}
WorkManager.getInstance(context).apply {
cancelAllWorkByTag("logWorkRequest")
enqueue(PeriodicWorkRequest.Builder(LogTask::class.java, 20, TimeUnit.MINUTES)
.addTag("logWorkRequest")
.build())
}
}
WorkManager.getInstance(context).apply {
cancelAllWorkByTag("logWorkRequest")
enqueue(PeriodicWorkRequest.Builder(LogTask::class.java, 20, TimeUnit.MINUTES)
.addTag("logWorkRequest").build())
}
}
fun print(tag: String, content: String) {
val time = getCurrentTime()
val logEntry = "$time---$tag---$content\n"
fun print(tag : String, content : String) {
val time = getCurrentTime()
val logEntry = "$time---$tag---$content\n"
Log.e("normal", "$tag---$content")
synchronized(logBuffer) {
logBuffer.append(logEntry)
}
if (BuildConfig.DEBUG) {
Log.e("normal", "$tag---$content")
}
if (logBuffer.length > 4096) {
coroutineScope.launch {
flushBuffer()
}
}
}
synchronized(logBuffer) {
logBuffer.append(logEntry)
}
fun print(tag : String, throwable : Throwable) {
val content = StringWriter()
val printWriter = PrintWriter(content)
throwable.printStackTrace(printWriter)
print(tag, content.toString())
}
if (logBuffer.length > 4096) {
coroutineScope.launch {
flushBuffer()
}
}
}
private suspend fun flushBuffer() = withContext(Dispatchers.IO) {
if (! isWriting.compareAndSet(false, true)) return@withContext
fun print(tag: String, throwable: Throwable) {
val content = StringWriter()
val printWriter = PrintWriter(content)
throwable.printStackTrace(printWriter)
print(tag, content.toString())
}
val logContent : String
synchronized(logBuffer) {
if (logBuffer.isEmpty()) {
isWriting.set(false)
return@withContext
}
logContent = logBuffer.toString()
logBuffer.clear()
}
private suspend fun flushBuffer() = withContext(Dispatchers.IO) {
if (!isWriting.compareAndSet(false, true)) return@withContext
try {
val fileName = "normal_log.txt"
val logFile = File("$normalLogDirPath${File.separator}$fileName")
val logContent: String
synchronized(logBuffer) {
if (logBuffer.isEmpty()) {
isWriting.set(false)
return@withContext
}
logContent = logBuffer.toString()
logBuffer.clear()
}
logFile.parentFile?.mkdirs()
try {
val fileName = "normal_log.txt"
val logFile = File("$normalLogDirPath${File.separator}$fileName")
if (! logFile.exists()) {
logFile.createNewFile()
addLogHead(logFile, getCurrentTime())
}
logFile.parentFile?.mkdirs()
BufferedWriter(FileWriter(logFile, true)).use { writer ->
writer.write(logContent)
writer.flush()
}
if (!logFile.exists()) {
logFile.createNewFile()
addLogHead(logFile, getCurrentTime())
}
if (logFile.length() >= 8 * MemoryConstants.MB) {
rotateLogFile(logFile)
}
} catch (e : IOException) {
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
} catch (e : Exception) {
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
} finally {
isWriting.set(false)
}
}
BufferedWriter(FileWriter(logFile, true)).use { writer ->
writer.write(logContent)
writer.flush()
}
private fun rotateLogFile(file : File) {
if (! file.exists()) return
if (logFile.length() >= 8 * MemoryConstants.MB) {
rotateLogFile(logFile)
}
} catch (e: IOException) {
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
} catch (e: Exception) {
Log.e("LogUtil", "Error in flushBuffer: ${e.message}")
} finally {
isWriting.set(false)
}
}
val newFileName = buildString {
append(AppUtils.getAppVersionCode())
append("_")
append(GlobalData.driverInfoBean?.vehicleName ?: "unknown")
append("_")
append(GlobalData.driverInfoBean?.userName ?: "unknown")
append("_")
append(TimeUtils.getNowString())
append(".txt")
}
private fun rotateLogFile(file: File) {
if (!file.exists()) return
val newFile = File("$normalLogDirPath${File.separator}$newFileName")
val newFileName = buildString {
append(AppUtils.getAppVersionCode())
append("_")
append(GlobalData.vehicleInfo?.vehicleName ?: "unknown")
append("_")
append(GlobalData.driverInfo?.userName ?: "unknown")
append("_")
append(TimeUtils.getNowString())
append(".txt")
}
try {
if (file.renameTo(newFile)) {
compressAndUploadLog(newFile) // 创建新的日志文件
file.createNewFile()
addLogHead(file, getCurrentTime())
} else {
print("LogUtil", "Failed to rename log file")
}
} catch (e : Exception) {
print("LogUtil", "Error during log rotation: ${e.message}")
}
}
val newFile = File("$normalLogDirPath${File.separator}$newFileName")
private fun compressAndUploadLog(logFile : File) = coroutineScope.launch {
try {
val compressedFile = File("${logFile.absolutePath}.7z")
compress(logFile, compressedFile.absolutePath)
upload(logFile, compressedFile)
} catch (e : Exception) {
print("LogUtil", e.toString())
}
}
try {
if (file.renameTo(newFile)) {
compressAndUploadLog(newFile)
// 创建新的日志文件
file.createNewFile()
addLogHead(file, getCurrentTime())
} else {
print("LogUtil", "Failed to rename log file")
}
} catch (e: Exception) {
print("LogUtil", "Error during log rotation: ${e.message}")
}
}
private fun deleteLog(file : File) {
try {
FileUtils.delete(file.absolutePath)
} catch (e : Exception) {
e.printStackTrace()
}
}
private fun compressAndUploadLog(logFile: File) = coroutineScope.launch {
try {
val compressedFile = File("${logFile.absolutePath}.7z")
compress(logFile, compressedFile.absolutePath)
upload(logFile, compressedFile)
} catch (e: Exception) {
print("LogUtil", e.toString())
}
}
fun updateNormalLog() {
thread {
if (GlobalData.token.isNullOrBlank()) {
return@thread
}
val fileName = "normal_log.txt"
val file = File("$normalLogDirPath${File.separator}$fileName")
val reName =
"${AppUtils.getAppVersionCode()}_${GlobalData.driverInfoBean?.vehicleName}_${GlobalData.driverInfoBean?.userName}_${TimeUtils.getNowString()}.txt"
val reNamePath = "$normalLogDirPath${File.separator}$reName"
file.renameTo(File(reNamePath))
normalLogDirPath?.let { it ->
File(it).listFiles()?.forEach {
if (it.length() / MemoryConstants.MB >= 10) {
deleteLog(it)
return@thread
}
if (it.exists() && ! it.name.contains("normal_log")) {
if (it.name.contains("7z")) {
upload(null, desFile = it)
} else {
val zipNamePath = it.absolutePath + ".7z"
val zipFile = File(zipNamePath)
if (! zipFile.exists()) {
try {
zipFile.createNewFile()
} catch (e : IOException) {
e.printStackTrace()
}
}
compress(it, zipNamePath)
}
}
}
}
}
}
private fun deleteLog(file: File) {
try {
FileUtils.delete(file.absolutePath)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun compress(srcFile : File, desFilePath : String) {
try {
val out = XZCompressorOutputStream(FileOutputStream(desFilePath))
addToArchiveCompression(out, srcFile, File(desFilePath))
} catch (e : Exception) {
e.printStackTrace()
}
}
fun updateNormalLog() {
thread {
if (GlobalData.token.isNullOrBlank()) {
return@thread
}
val fileName = "normal_log.txt"
val file = File("$normalLogDirPath${File.separator}$fileName")
val reName = "${AppUtils.getAppVersionCode()}_${GlobalData.vehicleInfo?.vehicleName}_${GlobalData.driverInfo?.userName}_${TimeUtils.getNowString()}.txt"
val reNamePath = "$normalLogDirPath${File.separator}$reName"
file.renameTo(File(reNamePath))
normalLogDirPath?.let { it ->
File(it).listFiles()?.forEach {
if (it.length() / MemoryConstants.MB >= 10) {
deleteLog(it)
return@thread
}
if (it.exists() && !it.name.contains("normal_log")) {
if (it.name.contains("7z")) {
upload(null, desFile = it)
} else {
val zipNamePath = it.absolutePath + ".7z"
val zipFile = File(zipNamePath)
if (!zipFile.exists()) {
try {
zipFile.createNewFile()
} catch (e: IOException) {
e.printStackTrace()
}
}
compress(it, zipNamePath)
}
}
}
}
}
}
private fun addToArchiveCompression(sevenZOutputFile : XZCompressorOutputStream,
srcFile : File,
desFile : File) {
if (srcFile.isFile) {
var inputStream : FileInputStream? = null
try {
inputStream = FileInputStream(srcFile)
val b = ByteArray(2048)
var count : Int
while (inputStream.read(b).also { count = it } != - 1) {
sevenZOutputFile.write(b, 0, count)
}
sevenZOutputFile.close()
inputStream.close()
upload(srcFile, desFile)
} catch (e : Exception) {
e.printStackTrace()
} finally {
try {
sevenZOutputFile.close()
inputStream !!.close()
} catch (e : Exception) {
e.printStackTrace()
}
}
}
}
private fun compress(srcFile: File, desFilePath: String) {
try {
val out = XZCompressorOutputStream(FileOutputStream(desFilePath))
addToArchiveCompression(out, srcFile, File(desFilePath))
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun upload(srcFile : File?, desFile : File) {
val requestBody : RequestBody = desFile.asRequestBody("multipart/form-data".toMediaType())
val part = MultipartBody.Part.createFormData("file", desFile.name, requestBody)
private fun addToArchiveCompression(
sevenZOutputFile: XZCompressorOutputStream,
srcFile: File, desFile: File
) {
if (srcFile.isFile) {
var inputStream: FileInputStream? = null
try {
inputStream = FileInputStream(srcFile)
val b = ByteArray(2048)
var count: Int
while (inputStream.read(b).also { count = it } != -1) {
sevenZOutputFile.write(b, 0, count)
}
sevenZOutputFile.close()
inputStream.close()
upload(srcFile, desFile)
} catch (e: Exception) {
e.printStackTrace()
} finally {
try {
sevenZOutputFile.close()
inputStream!!.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
val disposable =
LogRetrofitHelper.getDefaultService().uploadLog(part, desFile.name, "rescue-app")
.subscribeOn(Schedulers.io()).subscribe({ it ->
if (it.code == 200) {
deleteLog(desFile)
}
srcFile?.let {
deleteLog(it)
}
}, {}, {})
}
private fun upload(srcFile: File?, desFile: File) {
val requestBody: RequestBody = desFile.asRequestBody("multipart/form-data".toMediaType())
val part = MultipartBody.Part.createFormData("file", desFile.name, requestBody)
private fun addLogHead(file : File, time : String) {
file.appendBytes("${time}---应用版本---${AppUtils.getAppVersionName()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---系统版本---Android${DeviceUtils.getSDKVersionName()} ${DeviceUtils.getSDKVersionCode()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---ROM---${DeviceUtils.getManufacturer()} ${DeviceUtils.getModel()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---build---${AppUtils.getAppVersionCode()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---APP名称---中道救援-司机端".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---车辆名称---${GlobalData.driverInfoBean?.vehicleName}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---司机名称---${GlobalData.driverInfoBean?.userName ?: GlobalData.driverInfoBean?.userName}".toByteArray())
file.appendBytes("\n".toByteArray())
}
val disposable = LogRetrofitHelper.getDefaultService()
.uploadLog(part, desFile.name, "rescue-app")
.subscribeOn(Schedulers.io())
.subscribe({ it ->
if (it.code == 200) {
deleteLog(desFile)
}
srcFile?.let {
deleteLog(it)
}
}, {
}, {})
}
private fun getCurrentTime() : String {
return TimeUtils.millis2String(System.currentTimeMillis(), "yyyy/MM/dd HH:mm:ss.SSS")
}
private fun addLogHead(file: File, time: String) {
file.appendBytes("${time}---应用版本---${AppUtils.getAppVersionName()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---系统版本---Android${DeviceUtils.getSDKVersionName()} ${DeviceUtils.getSDKVersionCode()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---ROM---${DeviceUtils.getManufacturer()} ${DeviceUtils.getModel()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---build---${AppUtils.getAppVersionCode()}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---APP名称---中道救援-司机端".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---车辆名称---${GlobalData.vehicleInfo?.vehicleName}".toByteArray())
file.appendBytes("\n".toByteArray())
file.appendBytes("$time---司机名称---${GlobalData.driverInfo?.userName ?: GlobalData.vehicleInfo?.userName}".toByteArray())
file.appendBytes("\n".toByteArray())
}
private fun getCurrentTime(): String {
return TimeUtils.millis2String(System.currentTimeMillis(), "yyyy/MM/dd HH:mm:ss.SSS")
}
class LogTask(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
updateNormalLog()
return Result.success()
}
}
class LogTask(appContext : Context, workerParams : WorkerParameters) :
Worker(appContext, workerParams) {
override fun doWork() : Result {
updateNormalLog()
return Result.success()
}
}
}

View File

@ -8,6 +8,7 @@ import android.content.pm.PackageManager
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.ToastUtils
import com.za.call.CallLogManager
import com.za.call.ContactRecordBean

View File

@ -26,26 +26,35 @@ fun Any?.toJson() : String? {
return JSON.toJSON(this).toString()
}
fun OrderInfo.goStatusPage(context : Context) {
fun OrderInfo.goStatusPage(context : Context, isFinishActivity : Boolean? = true) {
when (this.taskState) { //等待发车
"START" -> {
if (! RoomHelper.db?.photoTemplateDao()
?.getOrderPhotoTemplateFromTaskNode(10100, userOrderId ?: 0).isNullOrEmpty()
) {
context.navigationActivity(DeparturePhotoActivity::class.java)
context.navigationActivity(DeparturePhotoActivity::class.java,
isFinish = isFinishActivity)
return
}
context.navigationActivity(WaitToStartActivity::class.java)
context.navigationActivity(WaitToStartActivity::class.java, isFinish = isFinishActivity)
}
"GOTO" -> context.navigationActivity(GoAccidentSiteActivity::class.java) //验证服务资格
"VERIFY" -> context.navigationActivity(VerifyOrderActivity::class.java) //检查车辆
"EXAMINE" -> context.navigationActivity(CheckVehicleActivity::class.java) //作业中
"OPERATION" -> context.navigationActivity(InOperationActivity::class.java) //前往目的地
"SENDTO" -> context.navigationActivity(GoToDestinationActivity::class.java) //目的地照片
"DESTPHOTO" -> context.navigationActivity(DestinationPhotoActivity::class.java) //结算
"SETTLEMENT" -> context.navigationActivity(OrderConfirmActivity::class.java) //任务结束
"FINISH" -> context.navigationActivity(WaitToStartActivity::class.java)
"GOTO" -> context.navigationActivity(GoAccidentSiteActivity::class.java,
isFinish = isFinishActivity) //验证服务资格
"VERIFY" -> context.navigationActivity(VerifyOrderActivity::class.java,
isFinish = isFinishActivity) //检查车辆
"EXAMINE" -> context.navigationActivity(CheckVehicleActivity::class.java,
isFinish = isFinishActivity) //作业
"OPERATION" -> context.navigationActivity(InOperationActivity::class.java,
isFinish = isFinishActivity) //前往目的地
"SENDTO" -> context.navigationActivity(GoToDestinationActivity::class.java,
isFinish = isFinishActivity) //目的地照片
"DESTPHOTO" -> context.navigationActivity(DestinationPhotoActivity::class.java,
isFinish = isFinishActivity) //结算中
"SETTLEMENT" -> context.navigationActivity(OrderConfirmActivity::class.java,
isFinish = isFinishActivity) //任务结束
"FINISH" -> context.navigationActivity(WaitToStartActivity::class.java,
isFinish = isFinishActivity)
}
}
@ -61,25 +70,34 @@ fun OrderInfo.getNextStatus() : String? {
return flowStr
}
fun goNextPage(status : String?, context : Context) {
fun goNextPage(status : String?, context : Context, isFinishActivity : Boolean? = true) {
when (status) { //等待发车
"START" -> {
if (! RoomHelper.db?.photoTemplateDao()?.getOrderPhotoTemplateFromTaskNode(10100,
GlobalData.currentOrder?.userOrderId ?: 0).isNullOrEmpty()
) {
context.navigationActivity(DeparturePhotoActivity::class.java)
context.navigationActivity(DeparturePhotoActivity::class.java,
isFinish = isFinishActivity)
return
}
context.navigationActivity(WaitToStartActivity::class.java)
context.navigationActivity(WaitToStartActivity::class.java, isFinish = isFinishActivity)
} //前往事发地
"GOTO" -> context.navigationActivity(GoAccidentSiteActivity::class.java) //验证服务资格
"VERIFY" -> context.navigationActivity(VerifyOrderActivity::class.java) //检查车辆
"EXAMINE" -> context.navigationActivity(CheckVehicleActivity::class.java) //作业中
"OPERATION" -> context.navigationActivity(InOperationActivity::class.java) //前往目的地
"SENDTO" -> context.navigationActivity(GoToDestinationActivity::class.java) //目的地照片
"DESTPHOTO" -> context.navigationActivity(DestinationPhotoActivity::class.java) //结算
"SETTLEMENT" -> context.navigationActivity(OrderConfirmActivity::class.java) //任务结束
"FINISH" -> context.navigationActivity(WaitToStartActivity::class.java)
"GOTO" -> context.navigationActivity(GoAccidentSiteActivity::class.java,
isFinish = isFinishActivity) //验证服务资格
"VERIFY" -> context.navigationActivity(VerifyOrderActivity::class.java,
isFinish = isFinishActivity) //检查车辆
"EXAMINE" -> context.navigationActivity(CheckVehicleActivity::class.java,
isFinish = isFinishActivity) //作业
"OPERATION" -> context.navigationActivity(InOperationActivity::class.java,
isFinish = true) //前往目的地
"SENDTO" -> context.navigationActivity(GoToDestinationActivity::class.java,
isFinish = isFinishActivity) //目的地照片
"DESTPHOTO" -> context.navigationActivity(DestinationPhotoActivity::class.java,
isFinish = isFinishActivity) //结算中
"SETTLEMENT" -> context.navigationActivity(OrderConfirmActivity::class.java,
isFinish = isFinishActivity) //任务结束
"FINISH" -> context.navigationActivity(WaitToStartActivity::class.java,
isFinish = isFinishActivity)
}
}

View File

@ -1,5 +1,6 @@
package com.za.net
import com.za.bean.AppNewDriverInfoDTO
import com.za.bean.BaseResponse
import com.za.bean.BatteryCostQueryBean
import com.za.bean.BatteryCostQueryRequest
@ -30,6 +31,7 @@ import com.za.bean.VehicleInfo
import com.za.bean.db.order.OrderInfo
import com.za.bean.db.order.PhotoTemplateInfo
import com.za.bean.request.AcceptOrderRequest
import com.za.bean.request.AppNewOrderVoiceRequest
import com.za.bean.request.CustomerPaymentCreateBean
import com.za.bean.request.CustomerPaymentCreateRequest
import com.za.bean.request.DriverFaceCompareBean
@ -114,6 +116,10 @@ interface ApiService {
@POST("/driverApp/task/login")
fun login(@Body info : LoginRequest) : Observable<BaseResponse<DriverInfo?>>
//获取该手机号下面服务商列表
@POST("/driverApp/supplier/getDriverListInfo")
fun getDriverListInfo(@Body info : VerifyCodeRequest) : Observable<BaseResponse<List<AppNewDriverInfoDTO>>>
@POST("/driverApp/task/loginWithTask")
fun loginWithTask(@Body loginWithTaskRequest : LoginWithTaskRequest) : Observable<BaseResponse<LoginWithTaskBean>>
@ -262,4 +268,7 @@ interface ApiService {
//获取车辆维修历史
@POST("/driverApp/supplier/v2/vehicleMaintenanceList")
fun vehicleMaintenanceList(@Body info : FetchVehicleMaintenanceSubmitHistoryRequestBean) : Observable<BaseResponse<List<VehicleMaintenanceHistoryBean>>>
@POST("driverApp/base/getVoiceUrl")
fun getVoiceUrl(@Body info : AppNewOrderVoiceRequest) : Observable<BaseResponse<String>>
}

View File

@ -5,12 +5,10 @@ import android.graphics.BitmapFactory
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.ImageUtils
import com.za.base.Const
import com.za.bean.DriverInfo
import com.za.bean.GeneralInfo
import com.za.bean.ImageBean
import com.za.bean.JpushBean
import com.za.bean.NewOrderRequestBean
import com.za.bean.VehicleInfo
import com.za.bean.db.ele.EleCarDamagePhotoBean
import com.za.bean.db.ele.EleWorkOrderBean
import com.za.bean.db.order.OrderInfo
@ -120,8 +118,8 @@ object CommonMethod {
success : (GeneralInfo) -> Unit = {},
failed : (String?) -> Unit = {}) {
val generalInfoRequest =
GeneralInfoRequest(vehicleId = vehicleId ?: GlobalData.vehicleInfo?.vehicleId,
driverId = userId ?: GlobalData.driverInfo?.userId,
GeneralInfoRequest(vehicleId = vehicleId ?: GlobalData.driverInfoBean?.vehicleId,
driverId = userId ?: GlobalData.driverInfoBean?.userId,
deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity()))
RetrofitHelper.getDefaultService().generalInfo(generalInfoRequest)
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
@ -129,51 +127,27 @@ object CommonMethod {
override fun doSuccess(it : GeneralInfo?) {
if (it == null) {
failed("获取车辆信息失败")
LogUtil.print("getGenerateInfo", "获取车辆信息失败")
return
}
if (GlobalData.vehicleInfo == null) {
GlobalData.vehicleInfo = VehicleInfo(vehicleId = it.vehicleId,
vehicleName = it.vehicleName,
userName = it.userName,
userPhone = it.userPhone,
status = it.vehicleState,
plateNumber = it.plateNumber,
vehicleState = it.vehicleState,
supplierType = it.supplierType)
} else {
GlobalData.vehicleInfo =
GlobalData.vehicleInfo?.copy(vehicleId = it.vehicleId,
vehicleName = it.vehicleName,
userName = it.userName,
userPhone = it.userPhone,
status = it.vehicleState,
plateNumber = it.plateNumber,
vehicleState = it.vehicleState,
supplierType = it.supplierType)
}
val driverInfoBean = GlobalData.driverInfoBean
GlobalData.driverInfoBean = driverInfoBean?.copy(vehicleId = it.vehicleId,
vehicleName = it.vehicleName,
userName = it.userName,
userPhone = it.userPhone,
plateNumber = it.plateNumber,
vehicleState = it.vehicleState,
supplierType = it.supplierType,
userPortrait = it.userPortrait,
userId = it.userId,
supplierId = it.supplierId,
deviceId = it.deviceId,
supplierName = it.supplierName,
authStatus = it.authStatus,
serviceList = it.serviceList?.toString())
if (GlobalData.driverInfo == null) {
GlobalData.driverInfo = DriverInfo(userPortrait = it.userPortrait,
userName = it.userName,
userId = it.userId,
userPhone = it.userPhone,
supplierId = it.supplierId.toString(),
supplierName = it.supplierName,
authStatus = it.authStatus,
supplierType = it.supplierType,
serviceList = it.serviceList)
} else {
GlobalData.driverInfo =
GlobalData.driverInfo?.copy(userPortrait = it.userPortrait,
userName = it.userName,
userId = it.userId,
userPhone = it.userPhone,
supplierId = it.supplierId.toString(),
supplierName = it.supplierName,
authStatus = it.authStatus,
supplierType = it.supplierType,
serviceList = it.serviceList)
}
LogUtil.print("GlobalData.driverInfoBean",
"${GlobalData.driverInfoBean?.toJson()}}")
success(it)
}
@ -187,7 +161,7 @@ object CommonMethod {
}
fun getNewOrder(context : Context) {
val newOrderRequestBean = NewOrderRequestBean(GlobalData.vehicleInfo?.vehicleId)
val newOrderRequestBean = NewOrderRequestBean(GlobalData.driverInfoBean?.vehicleId)
RetrofitHelper.getDefaultService().getNewOrder(newOrderRequestBean)
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver<JpushBean>() {
@ -229,7 +203,7 @@ object CommonMethod {
success : (OrderInfo?, List<OrderInfo>?) -> Unit,
failed : (String?) -> Unit) {
RetrofitHelper.getDefaultService()
.queryOrderList(OrderListRequest(vehicleId = GlobalData.vehicleInfo?.vehicleId,
.queryOrderList(OrderListRequest(vehicleId = GlobalData.driverInfoBean?.vehicleId,
deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity())))
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver<List<OrderInfo>?>() {
@ -246,33 +220,6 @@ object CommonMethod {
val waitServiceOrders = it.filter { it.isCurrent == false }
if (inServicingOrder == null) {
context?.let { context ->
val order = it[0]
NewOrderActivity.goNewOrderActivity(context,
jpushBean = JpushBean(taskId = order.taskId,
taskCode = order.taskCode,
customerName = order.customerName,
customerPhone = order.customerPhone,
carBrand = order.carBrand,
carModel = order.carModel,
carNo = order.carNo,
taskState = order.taskState,
address = order.address,
addressProperty = order.addressProperty,
hotline = order.hotline,
expectArriveTime = order.expectArriveTime,
serviceTypeName = order.serviceTypeName,
dispatchTime = order.dispatchTime,
lat = order.lat,
lng = order.lng,
distLat = order.distLat,
distLng = order.distLng,
importantTip = order.importantTip,
hasReplaceBatteryCapable = order.hasReplaceBatteryCapable,
distAddress = order.distAddress,
distAddressRemark = order.distAddressRemark,
addressRemark = order.addressRemark))
}
success(null, waitServiceOrders)
return
}

View File

@ -2,6 +2,7 @@ package com.za.net
import android.util.Log
import com.za.base.AppConfig
import com.za.common.log.LogUtil
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
@ -12,72 +13,55 @@ import java.net.URLDecoder
import java.util.concurrent.TimeUnit
object RetrofitHelper {
private var retrofit: Retrofit? = null
private var apiService: ApiService? = null
private val loggerInterceptor = HttpLoggingInterceptor {
try {
private var retrofit : Retrofit? = null
private var apiService : ApiService? = null
private val loggerInterceptor = HttpLoggingInterceptor {
try {
if (it.contains("image/*") || it.contains("form-data; name=\"file\"")
|| it.startsWith("Content-Type")
|| it.startsWith("Content-Length")
|| it.startsWith("Server")
|| it.startsWith("Date")
|| it.startsWith("Transfer-Encoding")
|| it.startsWith("Connection")
|| it.startsWith("X-")
|| it.startsWith("token")
|| it.startsWith("Cache-Control")
|| it.startsWith("Expires")
|| it.startsWith("Accept")
|| it.startsWith("Vary")
|| it.isEmpty()
|| it.startsWith("Pragma")
) {
return@HttpLoggingInterceptor
}
if (it.contains("image/*") || it.contains("form-data; name=\"file\"") || it.startsWith("Content-Type") || it.startsWith(
"Content-Length") || it.startsWith("Server") || it.startsWith("Date") || it.startsWith(
"Transfer-Encoding") || it.startsWith("Connection") || it.startsWith("X-") || it.startsWith(
"token") || it.startsWith("Cache-Control") || it.startsWith("Expires") || it.startsWith(
"Accept") || it.startsWith("Vary") || it.isEmpty() || it.startsWith("Pragma")
) {
return@HttpLoggingInterceptor
}
if (it.contains("name=\"file\"; filename")) {
return@HttpLoggingInterceptor
}
Log.e(
"--network--",
URLDecoder.decode(it.replace(Regex("%(?![0-9a-fA-F]{2})"), ""), "utf-8")
)
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
}
if (it.contains("name=\"file\"; filename")) {
return@HttpLoggingInterceptor
}
LogUtil.print("--network--",
URLDecoder.decode(it.replace(Regex("%(?![0-9a-fA-F]{2})"), ""), "utf-8"))
} catch (e : UnsupportedEncodingException) {
e.printStackTrace()
}
}.setLevel(HttpLoggingInterceptor.Level.BODY)
}.setLevel(HttpLoggingInterceptor.Level.BODY)
fun getDefaultService(): ApiService {
return if (apiService == null) {
apiService = getDefaultRetrofit().create(ApiService::class.java)
apiService!!
} else {
apiService!!
}
}
fun getDefaultService() : ApiService {
return if (apiService == null) {
apiService = getDefaultRetrofit().create(ApiService::class.java)
apiService !!
} else {
apiService !!
}
}
private fun getDefaultRetrofit(): Retrofit {
return if (retrofit == null) {
retrofit = Retrofit.Builder().baseUrl(AppConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.client(getOkHttpClient())
.build()
retrofit!!
} else {
retrofit!!
}
}
private fun getDefaultRetrofit() : Retrofit {
return if (retrofit == null) {
retrofit = Retrofit.Builder().baseUrl(AppConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()).client(getOkHttpClient())
.build()
retrofit !!
} else {
retrofit !!
}
}
private fun getOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.addInterceptor(RequestEncryptInterceptor())
.addInterceptor(loggerInterceptor)
.build()
}
private fun getOkHttpClient() : OkHttpClient {
return OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS)
.addInterceptor(RequestEncryptInterceptor()).addInterceptor(loggerInterceptor).build()
}
}

View File

@ -176,7 +176,7 @@ object OfflineManager {
lng = offlineUpdateTaskBean.imageLng.toDouble(),
address = it,
time = offlineUpdateTaskBean.time,
driverName = GlobalData.driverInfo?.userName,
driverName = GlobalData.driverInfoBean?.userName,
taskCode = offlineUpdateTaskBean.taskCode)
val offlineTemp = offlineUpdateTaskBean.copy(imageAddress = it)
file = File(PhotoMarkerManager.addPhotoMarker(ActivityUtils.getTopActivity(),

View File

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

View File

@ -2,7 +2,6 @@ package com.za.room.db
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.za.bean.db.ChangeBatteryPhoto
import com.za.bean.db.NewPhotoTemplateBean
import com.za.bean.db.ele.EleCarDamagePhotoBean
@ -11,7 +10,6 @@ import com.za.bean.db.order.OrderInfo
import com.za.bean.db.order.PhotoTemplateInfo
import com.za.bean.db.water_marker.WaterMarkerItemBean
import com.za.bean.db.water_marker.WaterMarkerTemplateBean
import com.za.offline.InspectionConverter
import com.za.offline.OfflineDao
import com.za.offline.OfflineUpdateTaskBean
import com.za.room.RoomHelper
@ -20,30 +18,32 @@ import com.za.room.db.ele_work.EleWorkOrderDao
import com.za.room.db.order.ChangeBatteryDao
import com.za.room.db.order.OrderDao
import com.za.room.db.order.PhotoTemplateDao
import com.za.room.db.user.DriverInfoBean
import com.za.room.db.user.DriverInfoDao
import com.za.room.db.user.LocalResourceBean
import com.za.room.db.user.LocalResourceDao
import com.za.room.db.water_marker.WaterMarkerDao
@Database(entities = [EleWorkOrderBean::class,
EleCarDamagePhotoBean::class,
WaterMarkerTemplateBean::class,
WaterMarkerItemBean::class,
ChangeBatteryPhoto::class,
NewPhotoTemplateBean::class,
OrderInfo::class,
OfflineUpdateTaskBean::class,
PhotoTemplateInfo::class], version = RoomHelper.VERSION, exportSchema = false)
@Database(entities = [EleWorkOrderBean::class, EleCarDamagePhotoBean::class, LocalResourceBean::class, WaterMarkerTemplateBean::class, WaterMarkerItemBean::class, ChangeBatteryPhoto::class, NewPhotoTemplateBean::class, OrderInfo::class, OfflineUpdateTaskBean::class, DriverInfoBean::class, PhotoTemplateInfo::class],
version = RoomHelper.VERSION,
exportSchema = false)
abstract class GlobalRoom : RoomDatabase() {
abstract fun eleWorkOrderDao(): EleWorkOrderDao
abstract fun eleWorkOrderDao() : EleWorkOrderDao
abstract fun eleCarDamagePhotoDao(): EleCarDamagePhotoDao
abstract fun eleCarDamagePhotoDao() : EleCarDamagePhotoDao
abstract fun waterMarkerDao(): WaterMarkerDao
abstract fun waterMarkerDao() : WaterMarkerDao
abstract fun changeBatteryDao(): ChangeBatteryDao
abstract fun changeBatteryDao() : ChangeBatteryDao
abstract fun orderDao(): OrderDao
abstract fun orderDao() : OrderDao
abstract fun photoTemplateDao(): PhotoTemplateDao
abstract fun photoTemplateDao() : PhotoTemplateDao
abstract fun offlineTaskDao(): OfflineDao
abstract fun offlineTaskDao() : OfflineDao
abstract fun driverInfoDao() : DriverInfoDao
abstract fun localResourceDao() : LocalResourceDao
}

View File

@ -0,0 +1,26 @@
package com.za.room.db.user
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "driver_info")
data class DriverInfoBean(
@PrimaryKey(autoGenerate = false) val userId : Int? = null, //用户id
val userName : String? = null, //用户姓名
val userPhone : String? = null, //用户手机号
val userPortrait : String? = null, //用户头像
val rongyunToken : String? = null,
val logTime : String? = null,
val supplierId : Int? = null, //经销商id
val supplierName : String? = null, //经销商名称
val supplierType : Int? = null, //经销商类型 1子公司 2供应商
val loginLogId : Int? = null,
val serviceList : String? = null, //车辆服务列表
val assistUserCode : String? = null,
val authStatus : Int? = null, // 0 未认证 1 已认证
val vehicleId : Int? = null,
val vehicleName : String? = null,
val vehicleState : Int? = null, //车辆状态 0 空闲 1 忙碌
val plateNumber : String? = null, //车牌号
val deviceId : String? = null,
)

View File

@ -0,0 +1,40 @@
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

@ -0,0 +1,10 @@
package com.za.room.db.user
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "local_resource_bean")
data class LocalResourceBean(@PrimaryKey val resourceName : String,
val resourceType : Int = 0,
val resourceUrl : String? = null,
val resourceDescription : String? = null)

View File

@ -0,0 +1,32 @@
package com.za.room.db.user
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
@Dao
interface LocalResourceDao {
@Insert
fun insert(localResourceBean : LocalResourceBean)
@Update
fun update(localResourceBean : LocalResourceBean)
@Delete
fun delete(localResourceBean : LocalResourceBean)
@get:Query("SELECT * FROM local_resource_bean")
val allLocalResources : List<LocalResourceBean?>?
@Query("SELECT * FROM local_resource_bean WHERE resourceName = :resourceName")
fun getLocalResourceByName(resourceName : String?) : LocalResourceBean?
@Query("SELECT * FROM local_resource_bean WHERE resourceType = :resourceType")
fun getLocalResourcesByType(resourceType : Int) : List<LocalResourceBean>?
@Query("DELETE FROM local_resource_bean")
fun deleteAllLocalResources()
}

View File

@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import cn.jpush.android.api.JPushInterface
import com.za.common.GlobalData
import com.za.common.log.LogUtil
import com.za.service.ServiceManager
@ -11,28 +12,33 @@ import com.za.service.ServiceManager
* Created by zhangj on 2019/4/4.
*/
class JPushReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val bundle = intent.extras
LogUtil.print("JpushMessage ", "onReceive==" + "action:" + intent.action)
if (intent.action == null || bundle == null) { return }
when (intent.action) {
JPushInterface.ACTION_REGISTRATION_ID -> {
val regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID)
LogUtil.print("JpushMessage ", "Registration successful: $regId")
}
override fun onReceive(context : Context, intent : Intent) {
val bundle = intent.extras
LogUtil.print("JpushMessage ", "onReceive==" + "action:" + intent.action)
if (intent.action == null || bundle == null) {
return
}
when (intent.action) {
JPushInterface.ACTION_REGISTRATION_ID -> {
val regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID)
GlobalData.regid = regId
LogUtil.print("JpushMessage ", "Registration successful: $regId")
}
JPushInterface.ACTION_MESSAGE_RECEIVED -> {
val msg = bundle.getString(JPushInterface.EXTRA_MESSAGE)
if (msg.isNullOrBlank()) { return }
ServiceManager.handlerPushMsg(msg)
}
JPushInterface.ACTION_MESSAGE_RECEIVED -> {
val msg = bundle.getString(JPushInterface.EXTRA_MESSAGE)
if (msg.isNullOrBlank()) {
return
}
ServiceManager.handlerPushMsg(msg)
}
JPushInterface.ACTION_NOTIFICATION_RECEIVED -> {
val title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE)
LogUtil.print("JPushReceiver:", "ACTION_NOTIFICATION_RECEIVED title: $title")
}
JPushInterface.ACTION_NOTIFICATION_RECEIVED -> {
val title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE)
LogUtil.print("JPushReceiver:", "ACTION_NOTIFICATION_RECEIVED title: $title")
}
else -> {}
}
}
else -> {}
}
}
}

View File

@ -123,8 +123,8 @@ object ZdLocationManager : AMapLocationListener {
val request = UploadGpsRequest().apply {
lat = location.latitude
lng = location.longitude
userId = GlobalData.driverInfo?.userId
vehicleId = GlobalData.vehicleInfo?.vehicleId
userId = GlobalData.driverInfoBean?.userId
vehicleId = GlobalData.driverInfoBean?.vehicleId
working = GlobalData.currentOrder != null
direction = location.bearing.toDouble()
speed = location.speed.toDouble()

View File

@ -103,8 +103,8 @@ class CommonH5Activity : BaseActivity() {
append("/training/training.html")
append("?id=").append(articleId)
append("&source=driverApp")
append("&driverId=").append(GlobalData.driverInfo?.userId)
append("&userId=").append(GlobalData.driverInfo?.userId)
append("&driverId=").append(GlobalData.driverInfoBean?.userId)
append("&userId=").append(GlobalData.driverInfoBean?.userId)
}
override fun onDestroy() {

View File

@ -170,7 +170,6 @@ class ServiceLauncherActivity : BaseActivity() {
private fun navigateToNextScreen() {
if (GlobalData.isMaster) {
GlobalData.currentOrder?.goStatusPage(this)
finish()
return
}
val driverName = intent.getStringExtra("driverName")

View File

@ -81,7 +81,6 @@ private fun ServicingMainScreen(jobCode : String? = null,
}
} else {
GlobalData.currentOrder?.goStatusPage(ActivityUtils.getTopActivity())
context.finish()
}
}

View File

@ -86,9 +86,15 @@ class NewOrderActivity : BaseActivity() {
} else {
intent.getSerializableExtra("jpushBean")
}
GlobalData.isHandlerNewOrder = false
AcceptOrderScreen(jpushBean = jpushBean as JpushBean)
}
override fun onStop() {
super.onStop()
GlobalData.isHandlerNewOrder = true
}
companion object {
fun goNewOrderActivity(context : Context, jpushBean : JpushBean) {
val intent = Intent(context, NewOrderActivity::class.java)
@ -196,24 +202,24 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
topBar = { HeadViewNotBack(title = "新订单") },
sheetContent = {
Column(modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.background(Color.White)
.verticalScroll(rememberScrollState())) { // 滑动指示器
.fillMaxWidth()
.wrapContentHeight()
.background(Color.White)
.verticalScroll(rememberScrollState())) { // 滑动指示器
Box(modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.background(Color.White), contentAlignment = Alignment.Center) {
.fillMaxWidth()
.padding(vertical = 8.dp)
.background(Color.White), contentAlignment = Alignment.Center) {
Box(modifier = Modifier
.width(32.dp)
.height(4.dp)
.background(color = Color(0xFFE0E0E0), shape = RoundedCornerShape(2.dp)))
.width(32.dp)
.height(4.dp)
.background(color = Color(0xFFE0E0E0), shape = RoundedCornerShape(2.dp)))
}
// 滑动指示器和订单类型行
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) {
Text(text = uiState.value.jpushBean?.serviceTypeName ?: "",
@ -230,8 +236,8 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
// 添加距离和时间信息
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) {
Text(text = "预计到达: ${uiState.value.estimatedArrivalTime}",
@ -244,13 +250,13 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
}
HorizontalDivider(modifier = Modifier
.fillMaxWidth()
.alpha(0.1f))
.fillMaxWidth()
.alpha(0.1f))
// 订单信息
Column(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp)) { // 订单标签
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp)) { // 订单标签
Row(verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)) {
@ -338,13 +344,13 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
// 修改按钮状态
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)) { // 拒单按钮
Button(onClick = { vm.dispatch(NewOrderVm.Action.RefuseOrder) },
modifier = Modifier
.weight(1f)
.height(44.dp),
.weight(1f)
.height(44.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color.White,
contentColor = Color(0xFF666666)),
border = BorderStroke(1.dp, Color(0xFFE5E5E5)),
@ -355,8 +361,8 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
// 接单按钮
Button(onClick = { vm.dispatch(NewOrderVm.Action.AcceptOrder) },
modifier = Modifier
.weight(1f)
.height(44.dp),
.weight(1f)
.height(44.dp),
colors = ButtonDefaults.buttonColors(containerColor = headBgColor),
shape = RoundedCornerShape(8.dp)) {
Text(text = "接单",
@ -375,8 +381,8 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
sheetDragHandle = null,
sheetSwipeEnabled = true) { paddingValues ->
Box(modifier = Modifier
.fillMaxSize()
.padding(paddingValues)) {
.fillMaxSize()
.padding(paddingValues)) {
AndroidView(modifier = Modifier.fillMaxSize(), factory = {
AMapLocationClient.updatePrivacyShow(context, true, true)
AMapLocationClient.updatePrivacyAgree(context, true)
@ -423,7 +429,7 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
// 添加当前位置标记
currentLocation?.let {
mapView.map.addMarker(MarkerOptions().position(it).title("当前位置")
.icon(ImageUtil.vectorToBitmap(context,R.drawable.ic_current_location))
.icon(ImageUtil.vectorToBitmap(context, R.drawable.ic_current_location))
.anchor(0.5f, 0.5f).visible(true))
allPoints.add(it)
}
@ -477,14 +483,14 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
private fun OrderItemView(jpushBean : JpushBean?, remainingTime : Int = 50) {
val context = LocalContext.current
Column(modifier = Modifier
.fillMaxWidth()
.background(color = Color.White)
.padding(bottom = 16.dp)) { // 订单类型和倒计时
.fillMaxWidth()
.background(color = Color.White)
.padding(bottom = 16.dp)) { // 订单类型和倒计时
Row(modifier = Modifier
.fillMaxWidth()
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFFFEDE3),
Color.White)))
.padding(horizontal = 16.dp, vertical = 12.dp),
.fillMaxWidth()
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFFFEDE3),
Color.White)))
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) {
Text(text = jpushBean?.serviceTypeName ?: "",
@ -498,19 +504,19 @@ private fun OrderItemView(jpushBean : JpushBean?, remainingTime : Int = 50) {
}
HorizontalDivider(modifier = Modifier
.padding(horizontal = 16.dp)
.alpha(0.08f))
.padding(horizontal = 16.dp)
.alpha(0.08f))
// 订单标签
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(modifier = Modifier
.background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp))
.padding(horizontal = 6.dp, vertical = 2.dp)) {
.background(Color(0xFF9BA1B2), RoundedCornerShape(4.dp))
.padding(horizontal = 6.dp, vertical = 2.dp)) {
Text(text = "月结", color = Color.White, fontSize = 12.sp)
}
Spacer(modifier = Modifier.width(8.dp))
@ -524,9 +530,9 @@ private fun OrderItemView(jpushBean : JpushBean?, remainingTime : Int = 50) {
// 订单号
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.clickable { jpushBean?.taskCode?.copy(context) },
.fillMaxWidth()
.padding(horizontal = 16.dp)
.clickable { jpushBean?.taskCode?.copy(context) },
verticalAlignment = Alignment.CenterVertically) {
Text(text = "单号", color = Color(0xFF999999), fontSize = 13.sp)
Spacer(modifier = Modifier.width(8.dp))
@ -544,8 +550,8 @@ private fun OrderItemView(jpushBean : JpushBean?, remainingTime : Int = 50) {
// 救援地址
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.Top) {
AsyncImage(model = R.drawable.sv_rescuing,
contentDescription = "rescue",
@ -561,12 +567,12 @@ private fun OrderItemView(jpushBean : JpushBean?, remainingTime : Int = 50) {
if (! jpushBean?.distAddress.isNullOrBlank()) {
Spacer(modifier = Modifier.height(16.dp))
HorizontalDivider(modifier = Modifier
.padding(horizontal = 24.dp)
.alpha(0.1f))
.padding(horizontal = 24.dp)
.alpha(0.1f))
Spacer(modifier = Modifier.height(16.dp))
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.Top) {
AsyncImage(model = R.drawable.sv_dist,
contentDescription = "destination",

View File

@ -93,8 +93,8 @@ class NewOrderVm : BaseVm<NewOrderVm.Action, NewOrderVm.UiState>() {
val orderInfo = uiState.value.jpushBean
val acceptOrderRequest = AcceptOrderRequest()
acceptOrderRequest.taskId = orderInfo?.taskId
acceptOrderRequest.vehicleId = GlobalData.vehicleInfo?.vehicleId
acceptOrderRequest.userId = GlobalData.driverInfo?.userId
acceptOrderRequest.vehicleId = GlobalData.driverInfoBean?.vehicleId
acceptOrderRequest.userId = GlobalData.driverInfoBean?.userId
acceptOrderRequest.taskCode = orderInfo?.taskCode
acceptOrderRequest.deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity())
acceptOrderRequest.lat = it.latitude
@ -123,9 +123,9 @@ class NewOrderVm : BaseVm<NewOrderVm.Action, NewOrderVm.UiState>() {
private fun refuseOrder() {
LoadingManager.showLoading()
RetrofitHelper.getDefaultService().refuseOrder(RefuseOrderRequest(taskId = uiState.value.jpushBean?.taskId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
taskCode = uiState.value.jpushBean?.taskCode,
userId = GlobalData.driverInfo?.userId))
userId = GlobalData.driverInfoBean?.userId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BaseObserver<String>() {
@ -147,7 +147,7 @@ class NewOrderVm : BaseVm<NewOrderVm.Action, NewOrderVm.UiState>() {
timerJob?.cancel()
timerJob = viewModelScope.launch {
try {
var timeLeft = 50
var timeLeft = 120
while (timeLeft > 0 && isActive) {
delay(1000)
timeLeft--

View File

@ -108,7 +108,7 @@ private fun handlerInServicingPhoto(
lng = localPhotoTemplateInfo.lng?.toDouble(),
address = localPhotoTemplateInfo.address,
time = localPhotoTemplateInfo.time,
driverName = GlobalData.driverInfo?.userName,
driverName = GlobalData.driverInfoBean?.userName,
taskCode = localPhotoTemplateInfo.taskCode)
File(PhotoMarkerManager.addPhotoMarker(context = context, photoMarkerInfo))
} else {
@ -188,7 +188,7 @@ private fun handlerChangeBatteryPhoto(context : Context,
lng = localPhotoTemplateInfo.lng?.toDouble(),
address = localPhotoTemplateInfo.address,
time = localPhotoTemplateInfo.time,
driverName = GlobalData.driverInfo?.userName,
driverName = GlobalData.driverInfoBean?.userName,
taskCode = localPhotoTemplateInfo.taskCode)
File(PhotoMarkerManager.addPhotoMarker(context = context, photoMarkerInfo))
} else {
@ -270,7 +270,7 @@ private fun handlerNormalPhoto(context : Context,
lng = localPhotoTemplateInfo.lng?.toDouble(),
address = localPhotoTemplateInfo.address,
time = localPhotoTemplateInfo.time,
driverName = GlobalData.driverInfo?.userName,
driverName = GlobalData.driverInfoBean?.userName,
taskCode = localPhotoTemplateInfo.taskCode)
File(PhotoMarkerManager.addPhotoMarker(context = context, photoMarkerInfo))
} else {

View File

@ -42,7 +42,6 @@ fun CheckVehicleScreen(vm: CheckVehicleVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -97,8 +97,8 @@ class CheckVehicleVm : IServicingVm<CheckVehicleVm.Action, CheckVehicleVm.UiStat
private fun doUploadOfflineTask(it : AMapLocation?, tempPhotoList : ArrayList<String?>) {
val taskRequest = UpdateTaskRequest(type = "CHECK_VEHICLE",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "EXAMINE",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
@ -197,8 +197,8 @@ class CheckVehicleVm : IServicingVm<CheckVehicleVm.Action, CheckVehicleVm.UiStat
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "CHECK_VEHICLE",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "EXAMINE",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),

View File

@ -42,7 +42,6 @@ fun DeparturePhotoScreen(vm : DeparturePhotoVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -91,8 +91,8 @@ class DeparturePhotoVm : IServicingVm<DeparturePhotoVm.Action, DeparturePhotoVm.
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "START",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),

View File

@ -42,7 +42,6 @@ fun DestinationPhotoScreen(vm: DestinationPhotoVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -103,9 +103,9 @@ class DestinationPhotoVm : IServicingVm<DestinationPhotoVm.Action, DestinationPh
private fun doUploadOfflineTask(it: AMapLocation?, tempPhotoList: ArrayList<String?>) {
val taskRequest = UpdateTaskRequest(type = "DEST_PHOTO",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
userId = GlobalData.driverInfoBean?.userId,
flowType = GlobalData.currentOrder?.flowType,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "DESTPHOTO",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
@ -198,9 +198,9 @@ class DestinationPhotoVm : IServicingVm<DestinationPhotoVm.Action, DestinationPh
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "DEST_PHOTO",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
userId = GlobalData.driverInfoBean?.userId,
flowType = GlobalData.currentOrder?.flowType,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "DESTPHOTO",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),

View File

@ -87,7 +87,6 @@ fun EleSignCheckScreen(vm: EleSignCheckVm = viewModel()) {
if (uiState.value.goNextPage != null) {
uiState.value.orderInfo?.goStatusPage(context)
context.finish()
}
if (uiState.value.showCallPhoneDialog == true) {

View File

@ -107,7 +107,6 @@ fun GoAccidentSiteScreen(vm : GoAccidentSiteVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -59,8 +59,8 @@ class GoAccidentSiteVm : IServicingVm<GoAccidentSiteVm.Action, GoAccidentSiteVm.
LoadingManager.hideLoading()
val temp = taskRequest ?: UpdateTaskRequest(type = "VERIFY",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
@ -97,8 +97,8 @@ class GoAccidentSiteVm : IServicingVm<GoAccidentSiteVm.Action, GoAccidentSiteVm.
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "VERIFY",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = getCurrentOrder()?.taskState,
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),

View File

@ -39,7 +39,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
@ -131,7 +130,6 @@ fun GoToDestinationScreen(vm: GoToDestinationVm = viewModel()) {
// 对话框处理
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -60,8 +60,8 @@ class GoToDestinationVm : IServicingVm<GoToDestinationVm.Action, GoToDestination
val temp = taskRequest ?: UpdateTaskRequest(
type = "ARRIVE_DEST",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
flowType = GlobalData.currentOrder?.flowType,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,
@ -102,8 +102,8 @@ class GoToDestinationVm : IServicingVm<GoToDestinationVm.Action, GoToDestination
val taskRequest = UpdateTaskRequest(
type = "ARRIVE_DEST",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
flowType = GlobalData.currentOrder?.flowType,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,

View File

@ -34,7 +34,6 @@ fun InOperationScreen(vm: InOperationVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -104,9 +104,9 @@ class InOperationVm : IServicingVm<InOperationVm.Action, InOperationVm.UiState>(
private fun doUploadOfflineTask(it: AMapLocation?, tempPhotoList: ArrayList<String?>) {
val taskRequest = UpdateTaskRequest(type = "OPERATION",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
userId = GlobalData.driverInfoBean?.userId,
flowType = GlobalData.currentOrder?.flowType,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "OPERATION",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
@ -202,9 +202,9 @@ class InOperationVm : IServicingVm<InOperationVm.Action, InOperationVm.UiState>(
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "OPERATION",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
userId = GlobalData.driverInfoBean?.userId,
flowType = GlobalData.currentOrder?.flowType,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = "OPERATION",
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),

View File

@ -42,7 +42,6 @@ fun ChangeBatteryScreen(vm: ChangeBatteryVm = viewModel()) {
if (uiState.value.goNextPage != null) {
uiState.value.orderInfo?.goStatusPage(context)
context.finish()
}
Scaffold(topBar = {

View File

@ -78,10 +78,8 @@ fun ConfirmEleScreen(vm : ConfirmEleVm = viewModel()) {
}
}
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {

View File

@ -48,7 +48,6 @@ import com.za.base.view.CommonDialog
import com.za.base.view.HeadView
import com.za.base.view.LoadingState
import com.za.common.log.LogUtil
import com.za.ext.finish
import com.za.ext.getEleOrderH5Url
import com.za.ext.goStatusPage
import com.za.servicing.R
@ -115,7 +114,6 @@ fun ConfirmH5SuccessScreen(vm : ConfirmH5SuccessVm = viewModel()) {
if (uiState.value.goNextPage == true) {
uiState.value.orderInfo?.goStatusPage(context)
context.finish()
}
if (uiState.value.showSignDialog != null) {

View File

@ -82,401 +82,339 @@ val primaryColor = Color(0xFF3B82F6)
val gradientColors = listOf(Color(0xFF3B82F6), Color(0xFF60A5FA))
class InputMoneyActivity : BaseActivity() {
@Composable
override fun ContentView() {
InputMoneyScreen(userOrderId = intent.getIntExtra("userOrderId", 0), taskId = intent.getIntExtra("taskId", 0))
}
@Composable
override fun ContentView() {
InputMoneyScreen(userOrderId = intent.getIntExtra("userOrderId", 0),
taskId = intent.getIntExtra("taskId", 0))
}
companion object {
fun goInputMoney(context: Context, userOrderId: Int, taskId: Int) {
context.startActivity(Intent(context, InputMoneyActivity::class.java).apply {
putExtra("userOrderId", userOrderId)
putExtra("taskId", taskId)
})
}
}
companion object {
fun goInputMoney(context : Context, userOrderId : Int, taskId : Int) {
context.startActivity(Intent(context, InputMoneyActivity::class.java).apply {
putExtra("userOrderId", userOrderId)
putExtra("taskId", taskId)
})
}
}
}
@Preview(showBackground = true)
@Composable
fun PreviewInputMoneyScreen() {
InputMoneyScreen(userOrderId = 1, taskId = 1)
InputMoneyScreen(userOrderId = 1, taskId = 1)
}
@Composable
fun InputMoneyScreen(userOrderId: Int, taskId: Int,
vm: InputMoneyVm = viewModel()) {
val context = LocalContext.current
val uiState = vm.uiState.collectAsStateWithLifecycle()
var showSuccessDialog by remember { mutableStateOf(false) }
fun InputMoneyScreen(userOrderId : Int, taskId : Int, vm : InputMoneyVm = viewModel()) {
val context = LocalContext.current
val uiState = vm.uiState.collectAsStateWithLifecycle()
var showSuccessDialog by remember { mutableStateOf(false) }
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(key1 = lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) {
vm.dispatch(action = InputMoneyVm.Action.Init(userOrderId, taskId))
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(key1 = lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) {
vm.dispatch(action = InputMoneyVm.Action.Init(userOrderId, taskId))
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
if (showSuccessDialog) {
SuccessDialog(
amount = "${uiState.value.paymentInfoBean?.amount ?: 0.00}",
onDismiss = {
showSuccessDialog = false
context.finish()
}
)
}
if (showSuccessDialog) {
SuccessDialog(amount = "${uiState.value.paymentInfoBean?.amount ?: 0.00}", onDismiss = {
showSuccessDialog = false
context.finish()
})
}
if (uiState.value.payState == 3) {
CommonDialog(title = "收款成功", message = "收款成功", cancelEnable = false,
confirm = {
goNextPage(GlobalData.currentOrder?.taskState, context)
context.finish()
}, dismiss = {
goNextPage(GlobalData.currentOrder?.taskState, context)
context.finish()
})
}
if (uiState.value.payState == 3) {
CommonDialog(title = "收款成功", message = "收款成功", cancelEnable = false, confirm = {
goNextPage(GlobalData.currentOrder?.taskState, context)
}, dismiss = {
goNextPage(GlobalData.currentOrder?.taskState, context)
})
}
Scaffold(
topBar = { HeadView(title = "客户收款", onBack = { context.finish() }) },
bottomBar = {
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
tonalElevation = 8.dp,
shadowElevation = 8.dp,
color = backgroundColor,
shape = RoundedCornerShape(24.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
Button(
onClick = {
goNextPage(GlobalData.currentOrder?.taskState, context)
context.finish()
},
modifier = Modifier
.weight(1f)
.height(48.dp)
.animateContentSize(),
shape = RoundedCornerShape(24.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF64748B),
contentColor = Color.White
),
elevation = ButtonDefaults.buttonElevation(4.dp),
interactionSource = remember { MutableInteractionSource() }
) {
Text("无须收款", fontSize = 12.sp, fontWeight = FontWeight.Medium)
}
Scaffold(topBar = { HeadView(title = "客户收款", onBack = { context.finish() }) }, bottomBar = {
Surface(modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
tonalElevation = 8.dp,
shadowElevation = 8.dp,
color = backgroundColor,
shape = RoundedCornerShape(24.dp)) {
Row(modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)) {
Button(onClick = {
goNextPage(GlobalData.currentOrder?.taskState, context)
},
modifier = Modifier
.weight(1f)
.height(48.dp)
.animateContentSize(),
shape = RoundedCornerShape(24.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF64748B),
contentColor = Color.White),
elevation = ButtonDefaults.buttonElevation(4.dp),
interactionSource = remember { MutableInteractionSource() }) {
Text("无须收款", fontSize = 12.sp, fontWeight = FontWeight.Medium)
}
Button(
onClick = {
if (uiState.value.receiveMoney == null || uiState.value.receiveMoney == 0f) {
ToastUtils.showLong("请输入收款金额")
return@Button
}
if (uiState.value.isOnSite == 2 && uiState.value.userPhone.isNullOrEmpty()) {
ToastUtils.showLong("请输入客户手机号")
return@Button
}
vm.dispatch(InputMoneyVm.Action.Save)
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.weight(1f),
shape = RoundedCornerShape(24.dp),
colors = ButtonDefaults.buttonColors(
containerColor = primaryColor
),
elevation = ButtonDefaults.buttonElevation(4.dp)
) {
Text("发送短信链接".takeIf { uiState.value.isOnSite != 1 }
?: "生成收款二维码", fontSize = 12.sp, fontWeight = FontWeight.Medium)
}
}
}
},
containerColor = backgroundColor
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(it)
.verticalScroll(rememberScrollState())
.padding(16.dp)
) {
Column(modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(12.dp))
Text("收款金额",
color = Color.Gray,
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
modifier = Modifier.padding(bottom = 16.dp)
)
Button(onClick = {
if (uiState.value.receiveMoney == null || uiState.value.receiveMoney == 0f) {
ToastUtils.showLong("请输入收款金额")
return@Button
}
if (uiState.value.isOnSite == 2 && uiState.value.userPhone.isNullOrEmpty()) {
ToastUtils.showLong("请输入客户手机号")
return@Button
}
vm.dispatch(InputMoneyVm.Action.Save)
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.weight(1f),
shape = RoundedCornerShape(24.dp),
colors = ButtonDefaults.buttonColors(containerColor = primaryColor),
elevation = ButtonDefaults.buttonElevation(4.dp)) {
Text("发送短信链接".takeIf { uiState.value.isOnSite != 1 } ?: "生成收款二维码",
fontSize = 12.sp,
fontWeight = FontWeight.Medium)
}
}
}
}, containerColor = backgroundColor) {
Column(modifier = Modifier
.fillMaxSize()
.padding(it)
.verticalScroll(rememberScrollState())
.padding(16.dp)) {
Column(modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally) {
Spacer(modifier = Modifier.height(12.dp))
Text("收款金额",
color = Color.Gray,
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
modifier = Modifier.padding(bottom = 16.dp))
OutlinedTextField(
value = uiState.value.receiveMoneyText ?: "",
onValueChange = { newValue ->
vm.updateState(uiState.value.copy(receiveMoney = newValue.toFloatOrNull(), receiveMoneyText = newValue))
},
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
prefix = { Text("¥") },
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = primaryColor,
unfocusedBorderColor = Color.Gray.copy(alpha = 0.5f),
focusedLabelColor = primaryColor,
unfocusedLabelColor = Color.Gray
)
)
}
OutlinedTextField(value = uiState.value.receiveMoneyText ?: "",
onValueChange = { newValue ->
vm.updateState(uiState.value.copy(receiveMoney = newValue.toFloatOrNull(),
receiveMoneyText = newValue))
},
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
prefix = { Text("¥") },
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(focusedBorderColor = primaryColor,
unfocusedBorderColor = Color.Gray.copy(alpha = 0.5f),
focusedLabelColor = primaryColor,
unfocusedLabelColor = Color.Gray))
}
Spacer(modifier = Modifier.height(15.dp))
// Action Buttons
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
Row(
modifier = if (uiState.value.isOnSite == 1) {
Modifier
.weight(1f)
.background(
brush = Brush.linearGradient(gradientColors),
shape = RoundedCornerShape(12.dp)
)
.padding(vertical = 16.dp)
} else {
Modifier
.weight(1f)
.noDoubleClick { vm.dispatch(InputMoneyVm.Action.ChangeOnSite(1)) }
.border(1.dp, Color.Gray.copy(alpha = 0.5f), RoundedCornerShape(12.dp))
.padding(vertical = 16.dp)
},
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
if (uiState.value.isOnSite == 1) {
Icon(imageVector = Icons.Default.LocationOn, contentDescription = null, tint = Color.White)
Text(text = "在现场", color = Color.White)
} else {
Icon(imageVector = Icons.Default.LocationOn, contentDescription = null, tint = Color.Gray)
Text(text = "在现场", color = Color.Gray)
}
}
Spacer(modifier = Modifier.height(15.dp)) // Action Buttons
Row(modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(16.dp)) {
Row(modifier = if (uiState.value.isOnSite == 1) {
Modifier
.weight(1f)
.background(brush = Brush.linearGradient(gradientColors),
shape = RoundedCornerShape(12.dp))
.padding(vertical = 16.dp)
} else {
Modifier
.weight(1f)
.noDoubleClick { vm.dispatch(InputMoneyVm.Action.ChangeOnSite(1)) }
.border(1.dp, Color.Gray.copy(alpha = 0.5f), RoundedCornerShape(12.dp))
.padding(vertical = 16.dp)
},
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically) {
if (uiState.value.isOnSite == 1) {
Icon(imageVector = Icons.Default.LocationOn,
contentDescription = null,
tint = Color.White)
Text(text = "在现场", color = Color.White)
} else {
Icon(imageVector = Icons.Default.LocationOn,
contentDescription = null,
tint = Color.Gray)
Text(text = "在现场", color = Color.Gray)
}
}
Row(
modifier = if (uiState.value.isOnSite == 2) {
Modifier
.weight(1f)
.background(color = primaryColor, shape = RoundedCornerShape(3.dp))
.padding(vertical = 15.dp)
} else {
Modifier
.weight(1f)
.noDoubleClick {
vm.dispatch(InputMoneyVm.Action.ChangeOnSite(2))
}
.border(1.dp, color = Color.Gray, shape = RoundedCornerShape(3.dp))
.padding(vertical = 15.dp)
},
horizontalArrangement = Arrangement.Center
) {
if (uiState.value.isOnSite == 2) {
Icon(imageVector = Icons.Default.Notifications, contentDescription = null, tint = Color.White)
Text(text = "不在现场", color = Color.White)
} else {
Icon(imageVector = Icons.Default.Notifications, contentDescription = null, tint = Color.Gray)
Text(text = "不在现场", color = Color.Gray)
}
}
}
Row(modifier = if (uiState.value.isOnSite == 2) {
Modifier
.weight(1f)
.background(color = primaryColor, shape = RoundedCornerShape(3.dp))
.padding(vertical = 15.dp)
} else {
Modifier
.weight(1f)
.noDoubleClick {
vm.dispatch(InputMoneyVm.Action.ChangeOnSite(2))
}
.border(1.dp, color = Color.Gray, shape = RoundedCornerShape(3.dp))
.padding(vertical = 15.dp)
}, horizontalArrangement = Arrangement.Center) {
if (uiState.value.isOnSite == 2) {
Icon(imageVector = Icons.Default.Notifications,
contentDescription = null,
tint = Color.White)
Text(text = "不在现场", color = Color.White)
} else {
Icon(imageVector = Icons.Default.Notifications,
contentDescription = null,
tint = Color.Gray)
Text(text = "不在现场", color = Color.Gray)
}
}
}
AnimatedVisibility(visible = uiState.value.isOnSite == 1) {
QRCodeSection(uiState.value.qrCode
?: "", createPayment = { vm.dispatch(InputMoneyVm.Action.CreatePaymentInfo) })
}
AnimatedVisibility(visible = uiState.value.isOnSite == 1) {
QRCodeSection(uiState.value.qrCode ?: "",
createPayment = { vm.dispatch(InputMoneyVm.Action.CreatePaymentInfo) })
}
AnimatedVisibility(visible = uiState.value.isOnSite == 2) {
Box(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp, vertical = 15.dp)) {
OutlinedTextField(
value = uiState.value.userPhone ?: "",
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Phone),
onValueChange = { vm.updateState(uiState.value.copy(userPhone = it)) },
label = { Text("请输入客户手机号") },
leadingIcon = {
Icon(
imageVector = Icons.Rounded.Phone,
contentDescription = null,
tint = primaryColor
)
},
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = primaryColor,
unfocusedBorderColor = Color.Gray,
focusedLabelColor = primaryColor,
unfocusedLabelColor = Color.Gray),
singleLine = true
)
}
}
AnimatedVisibility(visible = uiState.value.isOnSite == 2) {
Box(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp, vertical = 15.dp)) {
OutlinedTextField(value = uiState.value.userPhone ?: "",
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Phone),
onValueChange = { vm.updateState(uiState.value.copy(userPhone = it)) },
label = { Text("请输入客户手机号") },
leadingIcon = {
Icon(imageVector = Icons.Rounded.Phone,
contentDescription = null,
tint = primaryColor)
},
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(focusedBorderColor = primaryColor,
unfocusedBorderColor = Color.Gray,
focusedLabelColor = primaryColor,
unfocusedLabelColor = Color.Gray),
singleLine = true)
}
}
if (uiState.value.payState == 1) {
Column {
Spacer(modifier = Modifier.height(15.dp))
CountdownRing { vm.updateState(uiState.value.copy(payState = 4, qrCode = null, qrCodeOutTime = true)) }
}
}
}
}
if (uiState.value.payState == 1) {
Column {
Spacer(modifier = Modifier.height(15.dp))
CountdownRing {
vm.updateState(uiState.value.copy(payState = 4,
qrCode = null,
qrCodeOutTime = true))
}
}
}
}
}
}
@Composable
private fun QRCodeSection(qrCode: String? = null, isOutTime: Boolean? = null, createPayment: () -> Unit = {}) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
if (!qrCode.isNullOrEmpty()) {
Surface(modifier = Modifier
.size(200.dp)
.border(2.dp, primaryColor.copy(alpha = 0.1f), RoundedCornerShape(16.dp)),
color = backgroundColor,
shape = RoundedCornerShape(16.dp)
) {
Box(modifier = Modifier
.fillMaxSize()
.padding(16.dp),
contentAlignment = Alignment.Center
) {
AsyncImage(
model = qrCode,
contentDescription = null,
modifier = Modifier.fillMaxSize(0.8f)
)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text(
"请顾客扫码支付",
color = Color.Gray,
fontSize = 16.sp,
fontWeight = FontWeight.Medium
)
}
private fun QRCodeSection(qrCode : String? = null,
isOutTime : Boolean? = null,
createPayment : () -> Unit = {}) {
Column(modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalAlignment = Alignment.CenterHorizontally) {
if (! qrCode.isNullOrEmpty()) {
Surface(modifier = Modifier
.size(200.dp)
.border(2.dp, primaryColor.copy(alpha = 0.1f), RoundedCornerShape(16.dp)),
color = backgroundColor,
shape = RoundedCornerShape(16.dp)) {
Box(modifier = Modifier
.fillMaxSize()
.padding(16.dp),
contentAlignment = Alignment.Center) {
AsyncImage(model = qrCode,
contentDescription = null,
modifier = Modifier.fillMaxSize(0.8f))
}
}
Spacer(modifier = Modifier.height(16.dp))
Text("请顾客扫码支付",
color = Color.Gray,
fontSize = 16.sp,
fontWeight = FontWeight.Medium)
}
if (isOutTime == true) {
LoadError(message = "收款码失效", onRetry = { createPayment() })
}
if (isOutTime == true) {
LoadError(message = "收款码失效", onRetry = { createPayment() })
}
}
}
}
@Composable
private fun CountdownRing(outTime: () -> Unit) {
var countdown by remember { mutableIntStateOf(5 * 60) }
val progress by animateFloatAsState(
targetValue = (countdown / 5 * 60) * 360f,
animationSpec = remember { androidx.compose.animation.core.tween(1000) }
)
private fun CountdownRing(outTime : () -> Unit) {
var countdown by remember { mutableIntStateOf(5 * 60) }
val progress by animateFloatAsState(targetValue = (countdown / 5 * 60) * 360f,
animationSpec = remember { androidx.compose.animation.core.tween(1000) })
LaunchedEffect(Unit) {
while (countdown > 0) {
delay(1000)
countdown--
if (countdown == 0) {
outTime()
}
}
}
LaunchedEffect(Unit) {
while (countdown > 0) {
delay(1000)
countdown --
if (countdown == 0) {
outTime()
}
}
}
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
Box(modifier = Modifier.size(50.dp), contentAlignment = Alignment.Center) {
Canvas(modifier = Modifier.fillMaxSize()) {
drawArc(
brush = Brush.sweepGradient(
0f to primaryColor,
1f to Color.LightGray
),
startAngle = -90f,
sweepAngle = progress,
useCenter = false,
style = Stroke(width = 8.dp.toPx(), cap = StrokeCap.Round)
)
}
Surface(
color = Color.White,
shape = CircleShape,
modifier = Modifier.size(50.dp)) {}
Text(
text = countdown.toString(),
fontSize = 20.sp,
color = black90,
fontWeight = FontWeight.Medium
)
}
}
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
Box(modifier = Modifier.size(50.dp), contentAlignment = Alignment.Center) {
Canvas(modifier = Modifier.fillMaxSize()) {
drawArc(brush = Brush.sweepGradient(0f to primaryColor, 1f to Color.LightGray),
startAngle = - 90f,
sweepAngle = progress,
useCenter = false,
style = Stroke(width = 8.dp.toPx(), cap = StrokeCap.Round))
}
Surface(color = Color.White, shape = CircleShape, modifier = Modifier.size(50.dp)) {}
Text(text = countdown.toString(),
fontSize = 20.sp,
color = black90,
fontWeight = FontWeight.Medium)
}
}
}
@Composable
private fun SuccessDialog(amount: String, onDismiss: () -> Unit) {
Dialog(onDismissRequest = onDismiss) {
Surface(
shape = RoundedCornerShape(16.dp),
color = Color.White
) {
Column(
modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(64.dp)
.background(primaryColor.copy(alpha = 0.1f), CircleShape)
.clip(CircleShape),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Default.Check,
contentDescription = null,
tint = primaryColor,
modifier = Modifier.size(32.dp)
)
}
Spacer(modifier = Modifier.height(16.dp))
Text("收款成功", fontWeight = FontWeight.Medium, fontSize = 18.sp)
Text("已收款 ¥$amount", color = Color.Gray, fontSize = 14.sp)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = onDismiss,
modifier = Modifier.fillMaxWidth()
) {
Text("完成")
}
}
}
}
private fun SuccessDialog(amount : String, onDismiss : () -> Unit) {
Dialog(onDismissRequest = onDismiss) {
Surface(shape = RoundedCornerShape(16.dp), color = Color.White) {
Column(modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally) {
Box(modifier = Modifier
.size(64.dp)
.background(primaryColor.copy(alpha = 0.1f), CircleShape)
.clip(CircleShape),
contentAlignment = Alignment.Center) {
Icon(Icons.Default.Check,
contentDescription = null,
tint = primaryColor,
modifier = Modifier.size(32.dp))
}
Spacer(modifier = Modifier.height(16.dp))
Text("收款成功", fontWeight = FontWeight.Medium, fontSize = 18.sp)
Text("已收款 ¥$amount", color = Color.Gray, fontSize = 14.sp)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = onDismiss, modifier = Modifier.fillMaxWidth()) {
Text("完成")
}
}
}
}
}

View File

@ -133,7 +133,7 @@ fun BaseFeeView(flowType : Int,
.fillMaxWidth()
.padding(vertical = 5.dp),
color = black5)
if (GlobalData.driverInfo?.supplierType == Const.CHILD_COMPANY) {
if (GlobalData.driverInfoBean?.supplierType == Const.CHILD_COMPANY) {
Spacer(modifier = Modifier.height(5.dp))
OrderConfirmEditView(title = "起步价", value = "${startPrice ?: ""}", onValueChanged = {
dispatch(OrderConfirmVm.Action.UpdateStartPrice(it.toIntOrNull() ?: 0))
@ -204,7 +204,7 @@ fun AuxiliaryFeeView(dilemmaFee : Int?,
color = black5,
thickness = 0.5.dp)
if (GlobalData.driverInfo?.supplierType == Const.CHILD_COMPANY) {
if (GlobalData.driverInfoBean?.supplierType == Const.CHILD_COMPANY) {
Column(modifier = Modifier
.fillMaxWidth()
.padding(bottom = 12.dp),

View File

@ -82,7 +82,7 @@ class OrderConfirmVm : IServicingVm<OrderConfirmVm.Action, OrderConfirmVm.UiStat
}
}
if (GlobalData.driverInfo?.supplierType != Const.CHILD_COMPANY) {
if (GlobalData.driverInfoBean?.supplierType != Const.CHILD_COMPANY) {
// AB段不为0 BC段拖车流程不为0
if (uiState.value.abKm == null || uiState.value.abKm == 0) {
@ -118,11 +118,11 @@ class OrderConfirmVm : IServicingVm<OrderConfirmVm.Action, OrderConfirmVm.UiStat
LoadingManager.hideLoading()
val orderConfirmTaskRequest = UpdateOrderConfirmTaskRequest(type = "SETTLEMENT",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = uiState.value.orderInfo?.taskState,
operateTime = System.currentTimeMillis().toString(),
supplierType = GlobalData.driverInfo?.supplierType,
supplierType = GlobalData.driverInfoBean?.supplierType,
settleType = GlobalData.currentOrder?.settleType,
carryMileage = uiState.value.bcKm,
startMileage = uiState.value.abKm,
@ -130,10 +130,10 @@ class OrderConfirmVm : IServicingVm<OrderConfirmVm.Action, OrderConfirmVm.UiStat
carryRoadFee = uiState.value.bcRoadFee,
dilemmaFee = uiState.value.dilemmaFee,
basementFee = uiState.value.basementFee,
basePrice = if (GlobalData.driverInfo?.supplierType == Const.CHILD_COMPANY) {
basePrice = if (GlobalData.driverInfoBean?.supplierType == Const.CHILD_COMPANY) {
computerBaseFee()
} else null,
assistFee = if (GlobalData.driverInfo?.supplierType == Const.CHILD_COMPANY) {
assistFee = if (GlobalData.driverInfoBean?.supplierType == Const.CHILD_COMPANY) {
computerAssistantsFee()
} else null,
totalFee = computerTotalFee(),

View File

@ -125,10 +125,8 @@ fun ReceiveMoneyScreen(userOrderId: Int,
CommonDialog(title = "收款成功", message = "收款成功", cancelEnable = false,
confirm = {
goNextPage(GlobalData.currentOrder?.taskState, context)
context.finish()
}, dismiss = {
goNextPage(GlobalData.currentOrder?.taskState, context)
context.finish()
})
}

View File

@ -164,8 +164,8 @@ class OrderGiveUpVm : BaseVm<OrderGiveUpVm.Action, OrderGiveUpVm.UiState>() {
LoadingManager.hideLoading()
val taskRequest = GiveUpTaskRequest(
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
lat = it.latitude,
address = it.address,
pushGiveUpFlag = 1,
@ -215,8 +215,8 @@ class OrderGiveUpVm : BaseVm<OrderGiveUpVm.Action, OrderGiveUpVm.UiState>() {
LoadingManager.hideLoading()
val taskRequest = GiveUpTaskRequest(
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
lat = it.latitude,
address = it.address,
lng = it.longitude,

View File

@ -80,7 +80,6 @@ fun VerifyOrderScreen(vm: VerifyOrderVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.showCallPhoneDialog == true) {

View File

@ -59,8 +59,8 @@ class VerifyOrderVm : IServicingVm<VerifyOrderVm.Action, VerifyOrderVm.UiState>(
val temp = UpdateTaskRequest(
type = "VERIFY",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,
newCarCode = if (uiState.value.orderInfo?.verifyType == 5) {
@ -113,8 +113,8 @@ class VerifyOrderVm : IServicingVm<VerifyOrderVm.Action, VerifyOrderVm.UiState>(
val taskRequest = UpdateTaskRequest(
type = "VERIFY",
taskId = GlobalData.currentOrder?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = GlobalData.currentOrder?.taskState,
offlineMode = 0,
newCarCode = if (uiState.value.orderInfo?.verifyType == 5) {

View File

@ -115,7 +115,6 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
if (uiState.value.goNextPage != null) {
goNextPage(uiState.value.goNextPage?.nextState, context)
context.finish()
}
if (uiState.value.isGoNextPageDialog == true) {
@ -188,7 +187,7 @@ fun WaitToStartScreen(vm: WaitToStartVm = viewModel()) {
Text(
text = if (uiState.value.remainingDistance > 0)
"总里程: %.1fkm".format(uiState.value.remainingDistance / 1000f)
"距离救援地: %.1fkm".format(uiState.value.remainingDistance / 1000f)
else
"计算中...",
color = Color(0xFFFF4D4F),

View File

@ -30,244 +30,211 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.Calendar
import java.util.Locale
class WaitToStartVm : IServicingVm<WaitToStartVm.Action, WaitToStartVm.UiState>() {
private val _uiState = MutableStateFlow(UiState())
val uiState get() = _uiState
override fun updateState(uiState: UiState) {
_uiState.value = uiState
}
private val _uiState = MutableStateFlow(UiState())
val uiState get() = _uiState
override fun updateState(uiState : UiState) {
_uiState.value = uiState
}
override fun dispatch(action: Action) {
when (action) {
is Action.Init -> init()
is Action.UpdateTask -> updateTask()
is Action.UpdateState -> updateState(action.uiState)
is Action.StartTimer -> startTimer()
is Action.UpdateTimer -> updateTimer()
}
}
override fun dispatch(action : Action) {
when (action) {
is Action.Init -> init()
is Action.UpdateTask -> updateTask()
is Action.UpdateState -> updateState(action.uiState)
is Action.StartTimer -> startTimer()
is Action.UpdateTimer -> updateTimer()
}
}
private fun updateTask() {
LoadingManager.showLoading()
ZdLocationManager.getSingleLocation(success = {
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(
type = "START",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfo?.userId,
vehicleId = GlobalData.vehicleInfo?.vehicleId,
currentState = getCurrentOrder()?.taskState,
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
lat = it.latitude,
lng = it.longitude)
doUploadTask(request = taskRequest)
}, failed = {
LoadingManager.hideLoading()
ToastUtils.showShort(it)
})
}
private fun updateTask() {
LoadingManager.showLoading()
ZdLocationManager.getSingleLocation(success = {
LoadingManager.hideLoading()
val taskRequest = UpdateTaskRequest(type = "START",
taskId = getCurrentOrder()?.taskId,
userId = GlobalData.driverInfoBean?.userId,
vehicleId = GlobalData.driverInfoBean?.vehicleId,
currentState = getCurrentOrder()?.taskState,
offlineMode = 0,
operateTime = System.currentTimeMillis().toString(),
lat = it.latitude,
lng = it.longitude)
doUploadTask(request = taskRequest)
}, failed = {
LoadingManager.hideLoading()
ToastUtils.showShort(it)
})
}
private fun doUploadTask(request: UpdateTaskRequest) {
LoadingManager.showLoading()
CommonMethod.updateTask(request, success = { data ->
LoadingManager.hideLoading()
updateOrder(getCurrentOrder()?.copy(taskState = data?.nextState))
updateState(uiState.value.copy(goNextPage = data, orderInfo = getCurrentOrder()))
}, failed = { msg, _ ->
LoadingManager.hideLoading()
ToastUtils.showShort(msg)
LogUtil.print("$tag doUploadTask", "状态更新失败==${request.toJson()} msg==$msg")
})
}
private fun doUploadTask(request : UpdateTaskRequest) {
LoadingManager.showLoading()
CommonMethod.updateTask(request, success = { data ->
LoadingManager.hideLoading()
updateOrder(getCurrentOrder()?.copy(taskState = data?.nextState))
updateState(uiState.value.copy(goNextPage = data, orderInfo = getCurrentOrder()))
}, failed = { msg, _ ->
LoadingManager.hideLoading()
ToastUtils.showShort(msg)
LogUtil.print("$tag doUploadTask", "状态更新失败==${request.toJson()} msg==$msg")
})
}
private fun init() {
val order = getCurrentOrder()
updateState(uiState = uiState.value.copy(orderInfo = order))
buildMarkers(order)
searchDrivingRoute(order)
dispatch(Action.StartTimer)
}
private fun init() {
val order = getCurrentOrder()
updateState(uiState = uiState.value.copy(orderInfo = order))
buildMarkers(order)
searchDrivingRoute(order)
dispatch(Action.StartTimer)
}
private fun buildMarkers(orderInfo: OrderInfo?) {
val markers = arrayListOf<MarkerOptions>()
private fun buildMarkers(orderInfo : OrderInfo?) {
val markers = arrayListOf<MarkerOptions>()
// 添加救援地点标记
if (orderInfo?.lat != null && orderInfo.lat != 0.0 &&
orderInfo.lng != null && orderInfo.lng != 0.0
) {
// 添加救援地点标记
if (orderInfo?.lat != null && orderInfo.lat != 0.0 && orderInfo.lng != null && orderInfo.lng != 0.0) {
val startMarker = MarkerOptions()
.position(LatLng(orderInfo.lat!!, orderInfo.lng!!))
.title(orderInfo.address)
.snippet("救援地点")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map))
.anchor(0.5f, 0.5f)
.zIndex(2f)
.visible(true)
val startMarker = MarkerOptions().position(LatLng(orderInfo.lat !!, orderInfo.lng !!))
.title(orderInfo.address).snippet("救援地点")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map))
.anchor(0.5f, 0.5f).zIndex(2f).visible(true)
markers.add(startMarker)
}
markers.add(startMarker)
}
// 添加目的地标记
if (orderInfo?.distLat != null && orderInfo.distLat != 0.0 &&
orderInfo.distLng != null && orderInfo.distLng != 0.0
) {
// 添加目的地标记
if (orderInfo?.distLat != null && orderInfo.distLat != 0.0 && orderInfo.distLng != null && orderInfo.distLng != 0.0) {
val destMarker = MarkerOptions()
.position(LatLng(orderInfo.distLat!!, orderInfo.distLng!!))
.title(orderInfo.distAddress)
.snippet("目的地")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map))
.anchor(0.5f, 0.5f)
.zIndex(2f)
.visible(true)
val destMarker =
MarkerOptions().position(LatLng(orderInfo.distLat !!, orderInfo.distLng !!))
.title(orderInfo.distAddress).snippet("目的地")
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_dist_map))
.anchor(0.5f, 0.5f).zIndex(2f).visible(true)
markers.add(destMarker)
}
markers.add(destMarker)
}
updateState(uiState.value.copy(markers = markers))
}
updateState(uiState.value.copy(markers = markers))
}
private fun searchDrivingRoute(orderInfo: OrderInfo?) {
// 如果没有当前位置,则不进行路径规划
if (GlobalData.currentLocation == null) return
private fun searchDrivingRoute(orderInfo : OrderInfo?) { // 如果没有当前位置,则不进行路径规划
if (GlobalData.currentLocation == null) return
val startPoint = LatLonPoint(
GlobalData.currentLocation?.latitude ?: 0.0,
GlobalData.currentLocation?.longitude ?: 0.0
)
val startPoint = LatLonPoint(GlobalData.currentLocation?.latitude ?: 0.0,
GlobalData.currentLocation?.longitude ?: 0.0)
// 确定终点:如果有目的地,否则用救援地点
val endPoint = when {
// 优先使用目的地
orderInfo?.distLat != null && orderInfo.distLat != 0.0 &&
orderInfo.distLng != null && orderInfo.distLng != 0.0 -> {
LatLonPoint(orderInfo.distLat!!, orderInfo.distLng!!)
}
// 其次使用救援地点
orderInfo?.lat != null && orderInfo.lat != 0.0 &&
orderInfo.lng != null && orderInfo.lng != 0.0 -> {
LatLonPoint(orderInfo.lat!!, orderInfo.lng!!)
}
// 获取救援地点坐标
val rescuePoint =
if (orderInfo?.lat != null && orderInfo.lat != 0.0 && orderInfo.lng != null && orderInfo.lng != 0.0) {
LatLonPoint(orderInfo.lat !!, orderInfo.lng !!)
} else null
else -> null
}
// 如果没有救援地点,则不进行规划
if (rescuePoint == null) {
LogUtil.print("searchDrivingRoute", "没有有效的终点")
return
}
if (endPoint == null) return
// 使用 Application Context
RouteSearch(GlobalData.application).apply {
setRouteSearchListener(object : RouteSearch.OnRouteSearchListener {
override fun onDriveRouteSearched(result : DriveRouteResult?, errorCode : Int) {
if (errorCode == 1000 && result != null && result.paths.isNotEmpty()) {
val path = result.paths[0]
val points = path.steps.flatMap { step ->
step.polyline.map { LatLng(it.latitude, it.longitude) }
}
updateState(uiState.value.copy(routePoints = points))
} else {
LogUtil.print("searchDrivingRoute", "路径规划失败: errorCode=$errorCode")
}
}
val fromAndTo = RouteSearch.FromAndTo(startPoint, endPoint)
val query = RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, null, null, "")
override fun onBusRouteSearched(p0 : BusRouteResult?, p1 : Int) {}
override fun onWalkRouteSearched(p0 : WalkRouteResult?, p1 : Int) {}
override fun onRideRouteSearched(p0 : RideRouteResult?, p1 : Int) {}
})
// 使用 Application Context
RouteSearch(GlobalData.application).apply {
setRouteSearchListener(object : RouteSearch.OnRouteSearchListener {
override fun onDriveRouteSearched(result: DriveRouteResult?, errorCode: Int) {
if (errorCode == 1000 && result != null && result.paths.isNotEmpty()) {
val path = result.paths[0]
val points = path.steps.flatMap { step ->
step.polyline.map { LatLng(it.latitude, it.longitude) }
}
updateState(uiState.value.copy(routePoints = points))
} else {
LogUtil.print("searchDrivingRoute", "路径规划失败: errorCode=$errorCode")
}
}
val fromAndTo = RouteSearch.FromAndTo(startPoint, rescuePoint)
val query =
RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, null, null, "")
calculateDriveRouteAsyn(query)
}
}
override fun onBusRouteSearched(p0: BusRouteResult?, p1: Int) {}
override fun onWalkRouteSearched(p0: WalkRouteResult?, p1: Int) {}
override fun onRideRouteSearched(p0: RideRouteResult?, p1: Int) {}
})
calculateDriveRouteAsyn(query)
}
}
private var timerJob : Job? = null
private var timerJob: Job? = null
private fun startTimer() {
timerJob?.cancel()
timerJob = viewModelScope.launch {
while (isActive) { // 计算从当前位置到目标点的距离和到达时间
val (distance, arrivalTime) = calculateRemainingDistance()
_uiState.update {
it.copy(remainingDistance = distance, estimatedArrivalTime = arrivalTime)
}
delay(1000) // 每秒更新一次
}
}
}
private fun startTimer() {
timerJob?.cancel()
timerJob = viewModelScope.launch {
while (isActive) {
// 计算从当前位置到目标点的距离和到达时间
val (distance, arrivalTime) = calculateRemainingDistance()
_uiState.update {
it.copy(
remainingDistance = distance,
estimatedArrivalTime = arrivalTime
)
}
delay(1000) // 每秒更新一次
}
}
}
private fun calculateRemainingDistance() : Pair<Float, String> {
val currentLocation = GlobalData.currentLocation ?: return Pair(0f, "")
val orderInfo = _uiState.value.orderInfo ?: return Pair(0f, "")
private fun calculateRemainingDistance(): Pair<Float, String> {
val currentLocation = GlobalData.currentLocation ?: return Pair(0f, "")
val orderInfo = _uiState.value.orderInfo ?: return Pair(0f, "")
// 计算到救援地点的距离
val rescueDistance = if (orderInfo.lat != null && orderInfo.lng != null) {
AMapUtils.calculateLineDistance(LatLng(currentLocation.latitude,
currentLocation.longitude), LatLng(orderInfo.lat !!, orderInfo.lng !!))
} else 0f
// 计算到救援地点的距离
val rescueDistance = if (orderInfo.lat != null && orderInfo.lng != null) {
AMapUtils.calculateLineDistance(
LatLng(currentLocation.latitude, currentLocation.longitude),
LatLng(orderInfo.lat!!, orderInfo.lng!!)
)
} else 0f
// 计算到目的地的距离
val destDistance = if (orderInfo.distLat != null && orderInfo.distLng != null) {
AMapUtils.calculateLineDistance(LatLng(currentLocation.latitude,
currentLocation.longitude), LatLng(orderInfo.distLat !!, orderInfo.distLng !!))
} else 0f
// 计算到目的地的距离
val destDistance = if (orderInfo.distLat != null && orderInfo.distLng != null) {
AMapUtils.calculateLineDistance(
LatLng(currentLocation.latitude, currentLocation.longitude),
LatLng(orderInfo.distLat!!, orderInfo.distLng!!)
)
} else 0f
// 取较短的距离
val shortestDistance = minOf(rescueDistance.takeIf { it > 0f } ?: Float.MAX_VALUE,
destDistance.takeIf { it > 0f } ?: Float.MAX_VALUE)
// 取较短的距离
val shortestDistance = minOf(
rescueDistance.takeIf { it > 0f } ?: Float.MAX_VALUE,
destDistance.takeIf { it > 0f } ?: Float.MAX_VALUE
)
if (shortestDistance == Float.MAX_VALUE) {
return Pair(0f, "")
}
if (shortestDistance == Float.MAX_VALUE) {
return Pair(0f, "")
}
// 计算预计到达时间假设平均速度40km/h
val timeInSeconds = ((shortestDistance / 1000.0 * 60.0 / 40.0) * 60).toInt()
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, timeInSeconds)
val arrivalTime = SimpleDateFormat("HH:mm", Locale.getDefault()).format(calendar.time)
// 计算预计到达时间假设平均速度40km/h
val timeInSeconds = ((shortestDistance / 1000.0 * 60.0 / 40.0) * 60).toInt()
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, timeInSeconds)
val arrivalTime = SimpleDateFormat("HH:mm", Locale.getDefault()).format(calendar.time)
return Pair(shortestDistance, arrivalTime)
}
return Pair(shortestDistance, arrivalTime)
}
private fun updateTimer() { // 在这里处理倒计时更新逻辑
}
private fun updateTimer() {
// 在这里处理倒计时更新逻辑
}
override fun onCleared() {
super.onCleared()
timerJob?.cancel()
}
override fun onCleared() {
super.onCleared()
timerJob?.cancel()
}
sealed class Action {
data object Init : Action()
data object UpdateTask : Action()
data class UpdateState(val uiState : UiState) : Action()
data object StartTimer : Action()
data object UpdateTimer : Action()
}
sealed class Action {
data object Init : Action()
data object UpdateTask : Action()
data class UpdateState(val uiState: UiState) : Action()
data object StartTimer : Action()
data object UpdateTimer : Action()
}
data class UiState(
val orderInfo: OrderInfo? = null,
val showCallPhoneDialog: Boolean? = false,
val markers: ArrayList<MarkerOptions>? = null,
val goNextPage: UpdateTaskBean? = null,
val isGoNextPageDialog: Boolean? = null,
val routePoints: List<LatLng>? = null,
val remainingDistance: Float = 0f,
val estimatedArrivalTime: String = ""
)
data class UiState(val orderInfo : OrderInfo? = null,
val showCallPhoneDialog : Boolean? = false,
val markers : ArrayList<MarkerOptions>? = null,
val goNextPage : UpdateTaskBean? = null,
val isGoNextPageDialog : Boolean? = null,
val routePoints : List<LatLng>? = null,
val remainingDistance : Float = 0f,
val estimatedArrivalTime : String = "")
}