feat(network): 优化网络异常处理和环境切换
- 新增网络异常统一处理逻辑 - 实现环境切换功能 - 更新 API接口 - 重构部分代码以提高可维护性
This commit is contained in:
@ -27,7 +27,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.clickable {
|
.clickable {
|
||||||
val uri =
|
val uri =
|
||||||
"zd.assist://app?taskCode=ZD250512100030&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri()
|
"zd.assist://app?taskCode=ZD240823100724&driverName=宋志领&driverPhone=17630035658&rescueVehicle=沪88888".toUri()
|
||||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ fastjson = "1.2.69"
|
|||||||
glide = "4.16.0"
|
glide = "4.16.0"
|
||||||
gson = "2.11.0"
|
gson = "2.11.0"
|
||||||
jcore = "3.3.2"
|
jcore = "3.3.2"
|
||||||
|
faceDetection = "16.1.7"
|
||||||
jpush = "4.8.1"
|
jpush = "4.8.1"
|
||||||
location = "5.6.1"
|
location = "5.6.1"
|
||||||
loggingInterceptor = "4.11.0"
|
loggingInterceptor = "4.11.0"
|
||||||
@ -100,6 +101,7 @@ utilcodex = { module = "com.blankj:utilcodex", version.ref = "utilcodex" }
|
|||||||
xdmap = { module = "com.amap.api:3dmap", version.ref = "xdmap" }
|
xdmap = { module = "com.amap.api:3dmap", version.ref = "xdmap" }
|
||||||
xz = { module = "org.tukaani:xz", version.ref = "xz" }
|
xz = { module = "org.tukaani:xz", version.ref = "xz" }
|
||||||
androidx-exifinterface = { group = "androidx.exifinterface", name = "exifinterface", version.ref = "exifinterface" }
|
androidx-exifinterface = { group = "androidx.exifinterface", name = "exifinterface", version.ref = "exifinterface" }
|
||||||
|
face-detection = { module = "com.google.mlkit:face-detection", version.ref = "faceDetection" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
@ -73,7 +73,7 @@ publishing {
|
|||||||
release(MavenPublication) {
|
release(MavenPublication) {
|
||||||
groupId = 'io.github.szl9'
|
groupId = 'io.github.szl9'
|
||||||
artifactId = 'zd_servicing'
|
artifactId = 'zd_servicing'
|
||||||
version = "1.0.1.9.9.68"
|
version = "1.0.1.9.9.100"
|
||||||
|
|
||||||
pom {
|
pom {
|
||||||
packaging = "aar"
|
packaging = "aar"
|
||||||
@ -219,5 +219,7 @@ dependencies {
|
|||||||
|
|
||||||
api libs.org.eclipse.paho.client.mqttv3
|
api libs.org.eclipse.paho.client.mqttv3
|
||||||
api libs.org.eclipse.paho.android.service
|
api libs.org.eclipse.paho.android.service
|
||||||
|
|
||||||
|
api libs.face.detection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,10 +77,19 @@
|
|||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:targetApi="24">
|
tools:targetApi="24">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.za.base.NetworkRouteSelectionActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:theme="@style/Theme.Dealer" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.za.ui.camera.ServicePeopleRealActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:theme="@style/Theme.Dealer" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.za.ui.servicing.inservice_people_confirm.ServicePeopleConfirmActivity"
|
android:name="com.za.ui.servicing.inservice_people_confirm.ServicePeopleConfirmActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -1,98 +1,152 @@
|
|||||||
package com.za.base
|
package com.za.base
|
||||||
|
|
||||||
import com.za.common.GlobalData
|
import com.za.common.GlobalData
|
||||||
|
import com.za.net.RetrofitHelper
|
||||||
|
|
||||||
object AppConfig {
|
object AppConfig {
|
||||||
var isRelease = false
|
var isRelease = false
|
||||||
|
|
||||||
// API 相关地址
|
// API 相关地址
|
||||||
lateinit var BASE_URL: String // API 主地址
|
lateinit var BASE_URL : String // API 主地址
|
||||||
lateinit var IMG_BASE_URL: String // 图片服务器地址
|
lateinit var IMG_BASE_URL : String // 图片服务器地址
|
||||||
lateinit var Resource_URL: String // 资源服务器地址
|
lateinit var Resource_URL : String // 资源服务器地址
|
||||||
|
|
||||||
// H5 相关地址
|
|
||||||
lateinit var TRAIN_URL: String // 培训文档地址
|
|
||||||
lateinit var DOCMENT_URL: String // 中道资料地址
|
|
||||||
|
|
||||||
/**
|
// H5 相关地址
|
||||||
* 正式环境配置
|
lateinit var trainUrl : String // 培训文档地址
|
||||||
*/
|
lateinit var documentUrl : String // 中道资料地址
|
||||||
fun release() {
|
lateinit var newDriverTrainUrl : String // 新司机培训地址
|
||||||
isRelease = true
|
|
||||||
|
|
||||||
// API 配置
|
|
||||||
BASE_URL = "https://api.sinoassist.com"
|
|
||||||
IMG_BASE_URL = "https://api.sinoassist.com"
|
|
||||||
Resource_URL = "https://www.sinoassist.com/res"
|
|
||||||
|
|
||||||
// H5 配置
|
fun init(isRelease : Boolean? = false) {
|
||||||
TRAIN_URL = "https://www.sinoassist.com/h5/supplier/dispatch/diverTrainDocment"
|
val envType = GlobalData.networkEnv
|
||||||
DOCMENT_URL = "https://www.sinoassist.com/h5/supplier/dispatch/docmentList"
|
if (isRelease == true) {
|
||||||
}
|
when (envType) {
|
||||||
|
Const.NetEnv.Main -> release()
|
||||||
|
Const.NetEnv.Review -> review()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when (envType) {
|
||||||
|
Const.NetEnv.CRM1 -> crm1()
|
||||||
|
Const.NetEnv.CRM2 -> crm2()
|
||||||
|
Const.NetEnv.UAT -> uat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
fun changeEnv(envType : Int) {
|
||||||
* 审核环境配置
|
GlobalData.networkEnv = envType
|
||||||
*/
|
when (envType) {
|
||||||
fun review() {
|
Const.NetEnv.Main -> release()
|
||||||
isRelease = true
|
Const.NetEnv.Review -> review()
|
||||||
|
Const.NetEnv.CRM1 -> crm1()
|
||||||
|
Const.NetEnv.CRM2 -> crm2()
|
||||||
|
Const.NetEnv.UAT -> uat()
|
||||||
|
}
|
||||||
|
RetrofitHelper.reset()
|
||||||
|
}
|
||||||
|
|
||||||
// API 配置
|
|
||||||
BASE_URL = "http://interface.review.sino-assist.com"
|
|
||||||
IMG_BASE_URL = "http://interface.review.sino-assist.com"
|
|
||||||
Resource_URL = "https://www.sinoassist.com/res"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
fun release() {
|
||||||
* CRM1 环境配置
|
isRelease = true // API 配置
|
||||||
*/
|
GlobalData.networkEnv = Const.NetEnv.Main
|
||||||
fun crm1() {
|
BASE_URL = "https://api.sinoassist.com"
|
||||||
isRelease = false
|
IMG_BASE_URL = "https://api.sinoassist.com"
|
||||||
|
Resource_URL = "https://www.sinoassist.com/res"
|
||||||
|
|
||||||
// API 配置
|
// H5 配置
|
||||||
BASE_URL = "https://api1.sino-assist.com"
|
trainUrl = "https://www.sinoassist.com/h5/supplier/dispatch/diverTrainDocment"
|
||||||
IMG_BASE_URL = "https://api1.sino-assist.com"
|
documentUrl = "https://www.sinoassist.com/h5/supplier/dispatch/docmentList"
|
||||||
Resource_URL = "https://crm1.sino-assist.com/res"
|
newDriverTrainUrl = "https://www.sinoassist.com/h5/supplier/dispatch/driverTrainingList";
|
||||||
|
}
|
||||||
|
|
||||||
// H5 配置
|
|
||||||
TRAIN_URL = "https://crm1.sino-assist.com/h5/supplier/dispatch/diverTrainDocment"
|
|
||||||
DOCMENT_URL = "https://crm1.sino-assist.com/h5/supplier/dispatch/docmentList"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CRM2 环境配置
|
* 审核环境配置
|
||||||
*/
|
*/
|
||||||
fun crm2() {
|
private fun review() {
|
||||||
isRelease = false
|
isRelease = true // API 配置
|
||||||
|
GlobalData.networkEnv = Const.NetEnv.Review
|
||||||
|
|
||||||
// API 配置
|
// API 配置
|
||||||
BASE_URL = "https://api2.sino-assist.com"
|
BASE_URL = "http://interface.review.sino-assist.com"
|
||||||
IMG_BASE_URL = "https://api2.sino-assist.com"
|
IMG_BASE_URL = "http://interface.review.sino-assist.com"
|
||||||
Resource_URL = "https://crm2.sino-assist.com/res"
|
Resource_URL = "https://www.sinoassist.com/res"
|
||||||
}
|
documentUrl = "http://interface.review.sino-assist.com/h5/supplier/dispatch/docmentList"
|
||||||
|
trainUrl = "http://interface.review.sino-assist.com/h5/supplier/dispatch/diverTrainDocment"
|
||||||
|
newDriverTrainUrl =
|
||||||
|
"http://interface.review.sino-assist.com/h5/supplier/dispatch/driverTrainingList"
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取培训文档完整地址
|
* CRM1 环境配置
|
||||||
* @param driverId 司机ID
|
*/
|
||||||
* @param keyword 关键字
|
fun crm1() {
|
||||||
* @return 完整的培训文档URL
|
isRelease = false
|
||||||
*/
|
GlobalData.networkEnv = Const.NetEnv.CRM1
|
||||||
fun getTrainUrl(keyWord: String = ""): String {
|
|
||||||
if (keyWord.isEmpty()) {
|
|
||||||
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
|
|
||||||
}
|
|
||||||
return TRAIN_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// API 配置
|
||||||
* 获取中道资料完整地址
|
BASE_URL = "https://api1.sino-assist.com"
|
||||||
* @param driverId 司机ID
|
IMG_BASE_URL = "https://api1.sino-assist.com"
|
||||||
* @param keyword 关键字
|
Resource_URL = "https://crm1.sino-assist.com/res"
|
||||||
* @return 完整的中道资料URL
|
|
||||||
*/
|
documentUrl = "https://crm1.sino-assist.com/h5/supplier/dispatch/docmentList";
|
||||||
fun getDocmentUrl(keyWord: String = ""): String {
|
trainUrl = "https://crm1.sino-assist.com/h5/supplier/dispatch/diverTrainDocment";
|
||||||
if (keyWord.isEmpty()) {
|
newDriverTrainUrl = "https://crm1.sino-assist.com/h5/supplier/dispatch/driverTrainingList";
|
||||||
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
|
}
|
||||||
}
|
|
||||||
return DOCMENT_URL + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
|
/**
|
||||||
}
|
* CRM2 环境配置
|
||||||
}
|
*/
|
||||||
|
fun crm2() {
|
||||||
|
isRelease = false
|
||||||
|
GlobalData.networkEnv = Const.NetEnv.CRM2
|
||||||
|
|
||||||
|
// API 配置
|
||||||
|
BASE_URL = "https://api2.sino-assist.com"
|
||||||
|
IMG_BASE_URL = "https://api2.sino-assist.com"
|
||||||
|
Resource_URL = "https://crm2.sino-assist.com/res"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun uat() {
|
||||||
|
isRelease = false
|
||||||
|
GlobalData.networkEnv = Const.NetEnv.UAT
|
||||||
|
|
||||||
|
BASE_URL = "https://api-uat.sino-assist.com" //crm2
|
||||||
|
IMG_BASE_URL = "https://api-uat.sino-assist.com"
|
||||||
|
Resource_URL = "https://uat.sino-assist.com/res"
|
||||||
|
documentUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/docmentList"
|
||||||
|
trainUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/diverTrainDocment"
|
||||||
|
newDriverTrainUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/driverTrainingList"
|
||||||
|
documentUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/docmentList";
|
||||||
|
trainUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/diverTrainDocment";
|
||||||
|
newDriverTrainUrl = "https://uat.sino-assist.com/h5/supplier/dispatch/driverTrainingList";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取培训文档完整地址
|
||||||
|
* @param driverId 司机ID
|
||||||
|
* @param keyword 关键字
|
||||||
|
* @return 完整的培训文档URL
|
||||||
|
*/
|
||||||
|
fun getTrainUrl(keyWord : String = "") : String {
|
||||||
|
if (keyWord.isEmpty()) {
|
||||||
|
return trainUrl + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
|
||||||
|
}
|
||||||
|
return trainUrl + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取中道资料完整地址
|
||||||
|
* @param driverId 司机ID
|
||||||
|
* @param keyword 关键字
|
||||||
|
* @return 完整的中道资料URL
|
||||||
|
*/
|
||||||
|
fun getDocmentUrl(keyWord : String = "") : String {
|
||||||
|
if (keyWord.isEmpty()) {
|
||||||
|
return documentUrl + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}"
|
||||||
|
}
|
||||||
|
return documentUrl + "?token=${GlobalData.token}&driverId=${GlobalData.driverInfoBean?.userId}&keyword=$keyWord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -42,4 +42,12 @@ object Const {
|
|||||||
const val ORDER_DETAIL = 2 //案件详情
|
const val ORDER_DETAIL = 2 //案件详情
|
||||||
const val ORDER_GIVE_UP = 3 //订单放弃
|
const val ORDER_GIVE_UP = 3 //订单放弃
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object NetEnv {
|
||||||
|
const val Main = 0 //正线
|
||||||
|
const val Review = 1 //正线
|
||||||
|
const val CRM1 = 2 //测试环境
|
||||||
|
const val CRM2 = 3 //测试环境
|
||||||
|
const val UAT = 4 //测试环境
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,442 @@
|
|||||||
|
package com.za.base
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.os.Build
|
||||||
|
import android.telephony.PhoneStateListener
|
||||||
|
import android.telephony.SignalStrength
|
||||||
|
import android.telephony.TelephonyCallback
|
||||||
|
import android.telephony.TelephonyManager
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import com.blankj.utilcode.util.AppUtils
|
||||||
|
import com.za.base.theme.bgColor
|
||||||
|
import com.za.base.view.HeadView
|
||||||
|
import com.za.bean.BaseResponse
|
||||||
|
import com.za.bean.UpdateVersionBean
|
||||||
|
import com.za.bean.UpdateVersionRequest
|
||||||
|
import com.za.common.GlobalData
|
||||||
|
import com.za.common.log.LogUtil
|
||||||
|
import com.za.ext.finish
|
||||||
|
import com.za.net.BaseObserver
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.core.Observable
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.POST
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
data class Route(val name : String,
|
||||||
|
val url : String,
|
||||||
|
val id : String = name,
|
||||||
|
val type : Int) // 添加id字段用于唯一标识
|
||||||
|
|
||||||
|
// 定义所有可用线路
|
||||||
|
val availableRoutes = if (AppConfig.isRelease) {
|
||||||
|
listOf(
|
||||||
|
Route("主线路", "https://api.sinoassist.com", "main", type = Const.NetEnv.Main),
|
||||||
|
Route("备用线路",
|
||||||
|
"http://interface.review.sino-assist.com",
|
||||||
|
"review",
|
||||||
|
type = Const.NetEnv.Review),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listOf(Route("CRM1", "https://api1.sino-assist.com", "crm1", type = Const.NetEnv.CRM1),
|
||||||
|
Route("CRM2", "https://api2.sino-assist.com", "crm2", type = Const.NetEnv.CRM2),
|
||||||
|
Route("UAT", "https://api-uat.sino-assist.com", "uat", type = Const.NetEnv.UAT))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义检测状态枚举
|
||||||
|
enum class DetectionStatus {
|
||||||
|
UNKNOWN, // 未检测
|
||||||
|
CHECKING, // 检测中
|
||||||
|
NORMAL, // 正常
|
||||||
|
ABNORMAL // 异常
|
||||||
|
}
|
||||||
|
|
||||||
|
class NetworkRouteSelectionActivity : BaseActivity() {
|
||||||
|
@Composable
|
||||||
|
override fun ContentView() {
|
||||||
|
NetworkRouteScreen(telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager,
|
||||||
|
connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NetworkInfo(telephonyManager : TelephonyManager, connectivityManager : ConnectivityManager) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
var networkType by remember { mutableStateOf("") }
|
||||||
|
var signalStrength by remember { mutableIntStateOf(- 1) }
|
||||||
|
var operatorName by remember { mutableStateOf("") }
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
// 更新网络信息
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
if (ActivityCompat.checkSelfPermission(context,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) { // 获取运营商名称
|
||||||
|
operatorName = telephonyManager.networkOperatorName
|
||||||
|
|
||||||
|
// 使用新的 API 获取网络类型
|
||||||
|
val networkCapabilities =
|
||||||
|
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
|
||||||
|
|
||||||
|
networkType = when {
|
||||||
|
networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true -> "WiFi"
|
||||||
|
networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == true -> {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
when (telephonyManager.dataNetworkType) {
|
||||||
|
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
|
||||||
|
TelephonyManager.NETWORK_TYPE_NR -> "5G"
|
||||||
|
TelephonyManager.NETWORK_TYPE_UMTS -> "3G"
|
||||||
|
TelephonyManager.NETWORK_TYPE_EDGE -> "2G"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"未知"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> "无网络"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用新的 TelephonyCallback API 监听信号强度变化
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
val callback =
|
||||||
|
object : TelephonyCallback(), TelephonyCallback.SignalStrengthsListener {
|
||||||
|
override fun onSignalStrengthsChanged(signalStrengths : SignalStrength) {
|
||||||
|
scope.launch(Dispatchers.Main) {
|
||||||
|
signalStrength = signalStrengths.level
|
||||||
|
LogUtil.print("NetworkInfo", "signalStrength: $signalStrength")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
telephonyManager.registerTelephonyCallback(context.mainExecutor, callback)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION") telephonyManager.listen(object : PhoneStateListener() {
|
||||||
|
override fun onSignalStrengthsChanged(signalStrengths : SignalStrength) {
|
||||||
|
super.onSignalStrengthsChanged(signalStrengths)
|
||||||
|
scope.launch(Dispatchers.Main) {
|
||||||
|
signalStrength = signalStrengths.level
|
||||||
|
LogUtil.print("NetworkInfo", "signalStrength: $signalStrength")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Card(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 16.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
elevation = CardDefaults.elevatedCardElevation(4.dp)) {
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
Text(text = "当前手机网络",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = Color(0xFF2E7D32))
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Column {
|
||||||
|
Text("运营商:$operatorName", fontSize = 16.sp)
|
||||||
|
Text("网络类型:$networkType", fontSize = 16.sp)
|
||||||
|
Text(text = "信号强度:${
|
||||||
|
when (signalStrength) {
|
||||||
|
0 -> "无信号"
|
||||||
|
1 -> "弱"
|
||||||
|
2 -> "一般"
|
||||||
|
3 -> "良好"
|
||||||
|
4 -> "极好"
|
||||||
|
else -> "未知"
|
||||||
|
}
|
||||||
|
}", fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RouteItem(
|
||||||
|
route : Route,
|
||||||
|
isSelected : Boolean,
|
||||||
|
onSelect : () -> Unit,
|
||||||
|
) {
|
||||||
|
var detectionStatus by remember { mutableStateOf(DetectionStatus.UNKNOWN) }
|
||||||
|
var errorMessage by remember { mutableStateOf<String?>(null) }
|
||||||
|
var isDetecting by remember { mutableStateOf(false) }
|
||||||
|
var detectionTime by remember { mutableStateOf(0L) }
|
||||||
|
|
||||||
|
// 检测函数
|
||||||
|
fun detectRoute() {
|
||||||
|
if (isDetecting) return
|
||||||
|
|
||||||
|
isDetecting = true
|
||||||
|
detectionStatus = DetectionStatus.CHECKING
|
||||||
|
val startTime = System.currentTimeMillis()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val request = UpdateVersionRequest(appVersion = AppUtils.getAppVersionName())
|
||||||
|
NetWorkRetrofit.getDefaultService(route.url).checkConnection(request)
|
||||||
|
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : BaseObserver<UpdateVersionBean>() {
|
||||||
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
|
detectionTime = System.currentTimeMillis() - startTime
|
||||||
|
if (code == 999) {
|
||||||
|
detectionStatus = DetectionStatus.ABNORMAL
|
||||||
|
errorMessage = msg
|
||||||
|
} else {
|
||||||
|
detectionStatus = DetectionStatus.NORMAL
|
||||||
|
}
|
||||||
|
isDetecting = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doSuccess(it : UpdateVersionBean?) {
|
||||||
|
detectionTime = System.currentTimeMillis() - startTime
|
||||||
|
detectionStatus = DetectionStatus.NORMAL
|
||||||
|
isDetecting = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e : Exception) {
|
||||||
|
detectionTime = System.currentTimeMillis() - startTime
|
||||||
|
detectionStatus = DetectionStatus.ABNORMAL
|
||||||
|
errorMessage = e.message ?: "连接失败"
|
||||||
|
isDetecting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始检测
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
detectRoute()
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onSelect() }
|
||||||
|
.padding(vertical = 5.dp)
|
||||||
|
.border(width = if (isSelected) 1.dp else 0.dp,
|
||||||
|
color = if (isSelected) MaterialTheme.colorScheme.primary else Color.Transparent,
|
||||||
|
shape = RoundedCornerShape(4.dp))
|
||||||
|
.padding(8.dp)) {
|
||||||
|
RadioButton(selected = isSelected, onClick = { onSelect() })
|
||||||
|
|
||||||
|
Text(text = route.name,
|
||||||
|
fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
|
||||||
|
modifier = Modifier.padding(start = 8.dp))
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
|
||||||
|
if (isDetecting) {
|
||||||
|
CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 2.dp)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
val statusText = when (detectionStatus) {
|
||||||
|
DetectionStatus.NORMAL -> "正常 (${detectionTime}ms)"
|
||||||
|
DetectionStatus.ABNORMAL -> "异常 (${detectionTime}ms)"
|
||||||
|
DetectionStatus.CHECKING -> "检测中..."
|
||||||
|
DetectionStatus.UNKNOWN -> ""
|
||||||
|
}
|
||||||
|
|
||||||
|
val statusColor = when (detectionStatus) {
|
||||||
|
DetectionStatus.NORMAL -> Color(0xFF2E7D32)
|
||||||
|
DetectionStatus.ABNORMAL -> Color(0xFFC62828)
|
||||||
|
DetectionStatus.CHECKING -> Color(0xFF1565C0)
|
||||||
|
DetectionStatus.UNKNOWN -> Color.Gray
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(text = statusText,
|
||||||
|
color = statusColor,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp))
|
||||||
|
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.clickable(enabled = ! isDetecting) { detectRoute() }
|
||||||
|
.background(color = MaterialTheme.colorScheme.primary,
|
||||||
|
shape = RoundedCornerShape(5.dp))
|
||||||
|
.padding(vertical = 5.dp, horizontal = 10.dp)) {
|
||||||
|
Text("检测", fontSize = 12.sp, color = Color.White)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示错误信息(如果有)
|
||||||
|
if (detectionStatus == DetectionStatus.ABNORMAL && errorMessage != null) {
|
||||||
|
Text(text = "错误: $errorMessage",
|
||||||
|
color = Color(0xFFC62828),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
modifier = Modifier.padding(start = 40.dp, bottom = 8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NetworkRouteScreen(telephonyManager : TelephonyManager,
|
||||||
|
connectivityManager : ConnectivityManager) {
|
||||||
|
|
||||||
|
|
||||||
|
// 原有的线路选择部分
|
||||||
|
val context = LocalContext.current
|
||||||
|
var selectedRoute by remember { mutableStateOf(availableRoutes.find { GlobalData.networkEnv == it.type }) }
|
||||||
|
var showApplyDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
// 应用当前选中的线路
|
||||||
|
fun applySelectedRoute() {
|
||||||
|
selectedRoute?.let {
|
||||||
|
showApplyDialog = false
|
||||||
|
GlobalData.networkEnv = it.type
|
||||||
|
AppConfig.changeEnv(it.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示确认对话框
|
||||||
|
if (showApplyDialog) {
|
||||||
|
AlertDialog(onDismissRequest = { showApplyDialog = false },
|
||||||
|
title = { Text("确认应用线路") },
|
||||||
|
text = { Text("确定要将当前线路切换为 ${selectedRoute?.name} 吗?") },
|
||||||
|
confirmButton = {
|
||||||
|
Button(onClick = { applySelectedRoute() }) {
|
||||||
|
Text("确定")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
OutlinedButton(onClick = { showApplyDialog = false }) {
|
||||||
|
Text("取消")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(topBar = { HeadView(title = "线路选择", onBack = { context.finish() }) }) {
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(state = rememberScrollState())
|
||||||
|
.padding(it)
|
||||||
|
.background(color = bgColor)
|
||||||
|
.padding(20.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally) { // 标题卡片
|
||||||
|
NetworkInfo(telephonyManager, connectivityManager)
|
||||||
|
|
||||||
|
// 线路选择区域
|
||||||
|
Card(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 16.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
|
elevation = CardDefaults.elevatedCardElevation(4.dp)) {
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
Text("选择线路",
|
||||||
|
fontSize = 18.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(bottom = 8.dp))
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
availableRoutes.forEachIndexed { index, route ->
|
||||||
|
RouteItem(route = route,
|
||||||
|
isSelected = route == selectedRoute,
|
||||||
|
onSelect = { selectedRoute = route })
|
||||||
|
|
||||||
|
if (index < availableRoutes.size - 1) {
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用按钮
|
||||||
|
Button(onClick = { showApplyDialog = true },
|
||||||
|
enabled = selectedRoute != null,
|
||||||
|
modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Icon(Icons.Default.Check, contentDescription = null)
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
Text("应用选中线路")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义API接口
|
||||||
|
private interface RouteCheckApi {
|
||||||
|
@POST("/driverApp/base/appVersion")
|
||||||
|
fun checkConnection(@Body versionRequest : UpdateVersionRequest) : Observable<BaseResponse<UpdateVersionBean>>
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在类的外部定义Retrofit管理器
|
||||||
|
private object NetWorkRetrofit {
|
||||||
|
private val client =
|
||||||
|
OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private val retrofitMap = mutableMapOf<String, Retrofit>()
|
||||||
|
|
||||||
|
private fun getRetrofit(baseUrl : String) : Retrofit {
|
||||||
|
return retrofitMap.getOrPut(baseUrl) {
|
||||||
|
Retrofit.Builder().baseUrl(baseUrl).client(client)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create()) // Add this line
|
||||||
|
.addCallAdapterFactory(RxJava3CallAdapterFactory.create()).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultService(baseUrl : String) : RouteCheckApi {
|
||||||
|
return getRetrofit(baseUrl).create(RouteCheckApi::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCache() {
|
||||||
|
retrofitMap.clear()
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
@ -31,21 +30,14 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.withStyle
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.za.base.NetworkRouteSelectionActivity
|
||||||
import com.za.base.theme.headBgColor
|
import com.za.base.theme.headBgColor
|
||||||
import com.za.base.theme.white95
|
|
||||||
import com.za.bean.request.ReadTrainingCountRequest
|
|
||||||
import com.za.common.GlobalData
|
import com.za.common.GlobalData
|
||||||
import com.za.common.log.LogUtil
|
import com.za.ext.navigationActivity
|
||||||
import com.za.net.BaseObserver
|
|
||||||
import com.za.net.RetrofitHelper
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
|
||||||
|
|
||||||
|
|
||||||
val warnBean = mutableStateOf<IWarnBean?>(null)
|
val warnBean = mutableStateOf<IWarnBean?>(null)
|
||||||
@ -60,59 +52,19 @@ fun AppTipsView() {
|
|||||||
|
|
||||||
when (warnBean) {
|
when (warnBean) {
|
||||||
is NetWarnBean -> {
|
is NetWarnBean -> {
|
||||||
// NetTipView(warnBean as NetWarnBean)
|
NetworkWeakView(warnBean as NetWarnBean)
|
||||||
}
|
|
||||||
|
|
||||||
is ReadTrainingCountBean -> {
|
|
||||||
// TrainingDocView(warnBean as ReadTrainingCountBean)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NetTipView(tipsBean : NetWarnBean) {
|
|
||||||
Row(modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(20.dp)
|
|
||||||
.background(color = Color.Yellow)
|
|
||||||
.padding(top = 20.dp, start = 20.dp, end = 20.dp, bottom = 5.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center) {
|
|
||||||
Text(tipsBean.message, color = white95)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TrainingDocView(readTrainingCountBean : ReadTrainingCountBean) {
|
fun NetworkWeakView(netWarnBean : NetWarnBean) {
|
||||||
val showTrainingDialog = remember { mutableStateOf(false) }
|
val context = LocalContext.current
|
||||||
|
|
||||||
if (showTrainingDialog.value) {
|
AnimatedVisibility(context !is NetworkRouteSelectionActivity,
|
||||||
CommonDialog(title = "培训提醒",
|
|
||||||
message = buildAnnotatedString {
|
|
||||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, fontSize = 16.sp)) {
|
|
||||||
append("重要提示:\n")
|
|
||||||
}
|
|
||||||
withStyle(style = SpanStyle(fontSize = 14.sp)) {
|
|
||||||
append("您有未完成的培训任务,为确保工作顺利开展,请尽快完成培训。\n\n")
|
|
||||||
}
|
|
||||||
withStyle(style = SpanStyle(color = Color(0xFFE65100),
|
|
||||||
fontSize = 15.sp,
|
|
||||||
fontWeight = FontWeight.Medium)) {
|
|
||||||
append("剩余培训任务:${readTrainingCountBean.mustReadTrainingCount ?: 0} 个")
|
|
||||||
}
|
|
||||||
}.toString(),
|
|
||||||
confirmText = "立即前往",
|
|
||||||
cancelText = "稍后提醒",
|
|
||||||
cancelEnable = true,
|
|
||||||
confirm = {
|
|
||||||
showTrainingDialog.value = false
|
|
||||||
},
|
|
||||||
dismiss = { showTrainingDialog.value = false })
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedVisibility(visible = true,
|
|
||||||
modifier = Modifier.background(color = headBgColor),
|
modifier = Modifier.background(color = headBgColor),
|
||||||
enter = fadeIn(animationSpec = tween(300)) + expandVertically(animationSpec = tween(300),
|
enter = fadeIn(animationSpec = tween(300)) + expandVertically(animationSpec = tween(300),
|
||||||
expandFrom = Alignment.Top),
|
expandFrom = Alignment.Top),
|
||||||
@ -138,11 +90,12 @@ fun TrainingDocView(readTrainingCountBean : ReadTrainingCountBean) {
|
|||||||
modifier = Modifier.size(24.dp))
|
modifier = Modifier.size(24.dp))
|
||||||
}
|
}
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||||
Text(text = "培训提醒",
|
Text(text = "提醒",
|
||||||
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
|
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
|
||||||
color = Color(0xFF424242),
|
color = Color(0xFF424242),
|
||||||
fontSize = 14.sp)
|
fontSize = 14.sp)
|
||||||
Text(text = "您有 ${readTrainingCountBean.mustReadTrainingCount ?: 0} 个培训任务待完成",
|
|
||||||
|
Text(text = "当前线路异常,是否前往切换线路",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Color(0xFF757575),
|
color = Color(0xFF757575),
|
||||||
fontSize = 12.sp)
|
fontSize = 12.sp)
|
||||||
@ -150,18 +103,20 @@ fun TrainingDocView(readTrainingCountBean : ReadTrainingCountBean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.clickable {}
|
.clickable {
|
||||||
|
context.navigationActivity(NetworkRouteSelectionActivity::class.java)
|
||||||
|
}
|
||||||
.background(color = Color(0xFFFF9800), shape = RoundedCornerShape(5.dp))
|
.background(color = Color(0xFFFF9800), shape = RoundedCornerShape(5.dp))
|
||||||
.padding(horizontal = 10.dp, vertical = 5.dp),
|
.padding(horizontal = 10.dp, vertical = 5.dp),
|
||||||
contentAlignment = Alignment.Center) {
|
contentAlignment = Alignment.Center) {
|
||||||
Text("去完成", color = Color.White, style = MaterialTheme.typography.labelLarge)
|
Text("去完成", color = Color.White, style = MaterialTheme.typography.labelLarge)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun fetchAppTipsData() {
|
private fun fetchAppTipsData() {
|
||||||
if (GlobalData.currentOrder != null) {
|
if (GlobalData.currentOrder != null) {
|
||||||
return
|
return
|
||||||
@ -169,20 +124,6 @@ private fun fetchAppTipsData() {
|
|||||||
if (GlobalData.token == null) {
|
if (GlobalData.token == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val request = ReadTrainingCountRequest(driverId = GlobalData.driverInfoBean?.userId?.toInt(),
|
|
||||||
userId = GlobalData.driverInfoBean?.userId,
|
|
||||||
supplierId = GlobalData.driverInfoBean?.supplierId.toString())
|
|
||||||
RetrofitHelper.getDefaultService().getReadTrainingCount(request).subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : BaseObserver<ReadTrainingCountBean>() {
|
|
||||||
override fun doSuccess(it : ReadTrainingCountBean?) {
|
|
||||||
warnBean.value = it
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doFailure(code : Int, msg : String?) {
|
|
||||||
LogUtil.print("fetchAppTipsData ", "doFailure==$msg")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class IWarnBean
|
abstract class IWarnBean
|
||||||
|
@ -33,188 +33,220 @@ import com.za.common.util.MapUtil
|
|||||||
import com.za.servicing.R
|
import com.za.servicing.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommonDialog(
|
fun CommonDialog(title : String? = null,
|
||||||
title: String? = null,
|
confirmText : String = "确定",
|
||||||
confirmText: String = "确定",
|
confirm : () -> Unit,
|
||||||
confirm: () -> Unit,
|
content : @Composable () -> Unit = {},
|
||||||
content: @Composable () -> Unit = {},
|
message : String? = null,
|
||||||
message: String? = null,
|
cancelText : String? = "取消",
|
||||||
cancelText: String? = "取消",
|
cancelEnable : Boolean = true,
|
||||||
cancelEnable: Boolean = true,
|
cancel : () -> Unit = {},
|
||||||
cancel: () -> Unit = {},
|
dismiss : () -> Unit) {
|
||||||
dismiss: () -> Unit
|
Dialog(onDismissRequest = { dismiss() },
|
||||||
) {
|
properties = DialogProperties(dismissOnBackPress = cancelEnable,
|
||||||
Dialog(onDismissRequest = { dismiss() },
|
dismissOnClickOutside = cancelEnable)) {
|
||||||
properties = DialogProperties(
|
Box(modifier = Modifier.background(color = Color.White,
|
||||||
dismissOnBackPress = cancelEnable,
|
shape = RoundedCornerShape(13.dp))) {
|
||||||
dismissOnClickOutside = cancelEnable)) {
|
Spacer(modifier = Modifier
|
||||||
Box(modifier = Modifier
|
.fillMaxWidth()
|
||||||
.background(color = Color.White, shape = RoundedCornerShape(13.dp))) {
|
.height(105.dp)
|
||||||
Spacer(modifier = Modifier
|
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFDAE8FF),
|
||||||
.fillMaxWidth()
|
Color(0x00DAE8FF))),
|
||||||
.height(105.dp)
|
shape = RoundedCornerShape(topStart = 13.dp, topEnd = 13.dp)))
|
||||||
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFDAE8FF),
|
Column(modifier = Modifier
|
||||||
Color(0x00DAE8FF))),
|
.fillMaxWidth()
|
||||||
shape = RoundedCornerShape(topStart = 13.dp, topEnd = 13.dp)))
|
.padding(horizontal = 30.dp),
|
||||||
Column(modifier = Modifier
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
.fillMaxWidth()
|
verticalArrangement = Arrangement.Center) {
|
||||||
.padding(horizontal = 30.dp),
|
Spacer(modifier = Modifier.height(35.dp))
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
Text(text = "$title",
|
||||||
verticalArrangement = Arrangement.Center) {
|
fontSize = 16.sp,
|
||||||
Spacer(modifier = Modifier.height(35.dp))
|
fontWeight = FontWeight.Medium,
|
||||||
Text(text = "$title", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = Color(0xFF2A4054))
|
color = Color(0xFF2A4054))
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
content()
|
content()
|
||||||
} else {
|
} else {
|
||||||
Text(text = message, fontSize = 14.sp, color = Color(0xFF536475))
|
Text(text = message, fontSize = 14.sp, color = Color(0xFF536475))
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.width(202.dp)
|
.width(202.dp)
|
||||||
.clickable { confirm() }
|
.clickable { confirm() }
|
||||||
.background(color = Color(0xFF3A58B1), shape = RoundedCornerShape(23.dp))
|
.background(color = Color(0xFF3A58B1), shape = RoundedCornerShape(23.dp))
|
||||||
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
||||||
Text(text = confirmText, color = Color.White, fontSize = 15.sp, fontWeight = FontWeight.Medium)
|
Text(text = confirmText,
|
||||||
}
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
if (!cancelText.isNullOrBlank() && cancelEnable) {
|
if (! cancelText.isNullOrBlank() && cancelEnable) {
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { cancel() }, contentAlignment = Alignment.Center) {
|
.clickable { cancel() },
|
||||||
Text(text = cancelText, fontSize = 15.sp, fontWeight = FontWeight.Medium, color = black90)
|
contentAlignment = Alignment.Center) {
|
||||||
}
|
Text(text = cancelText,
|
||||||
}
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = black90)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReTakePhotoDialog(
|
fun ReTakePhotoDialog(title : String? = null,
|
||||||
title: String? = null,
|
confirm : () -> Unit,
|
||||||
confirm: () -> Unit,
|
againSubmit : () -> Unit,
|
||||||
againSubmit: () -> Unit,
|
path : String? = null,
|
||||||
path: String? = null,
|
showAgain : Boolean = false,
|
||||||
showAgain: Boolean = false,
|
cancel : () -> Unit = {},
|
||||||
cancel: () -> Unit = {},
|
dismiss : () -> Unit) {
|
||||||
dismiss: () -> Unit
|
Dialog(onDismissRequest = { dismiss() },
|
||||||
) {
|
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true)) {
|
||||||
Dialog(onDismissRequest = { dismiss() },
|
Box(modifier = Modifier.background(color = Color.White,
|
||||||
properties = DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true)) {
|
shape = RoundedCornerShape(13.dp))) {
|
||||||
Box(modifier = Modifier
|
Spacer(modifier = Modifier
|
||||||
.background(color = Color.White, shape = RoundedCornerShape(13.dp))) {
|
.fillMaxWidth()
|
||||||
Spacer(modifier = Modifier
|
.height(105.dp)
|
||||||
.fillMaxWidth()
|
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFDAE8FF),
|
||||||
.height(105.dp)
|
Color(0x00DAE8FF))),
|
||||||
.background(brush = Brush.verticalGradient(colors = arrayListOf(Color(0xFFDAE8FF),
|
shape = RoundedCornerShape(topStart = 13.dp, topEnd = 13.dp)))
|
||||||
Color(0x00DAE8FF))),
|
Column(modifier = Modifier
|
||||||
shape = RoundedCornerShape(topStart = 13.dp, topEnd = 13.dp)))
|
.fillMaxWidth()
|
||||||
Column(modifier = Modifier
|
.padding(horizontal = 30.dp),
|
||||||
.fillMaxWidth()
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
.padding(horizontal = 30.dp),
|
verticalArrangement = Arrangement.Center) {
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
Spacer(modifier = Modifier.height(35.dp))
|
||||||
verticalArrangement = Arrangement.Center) {
|
Text(text = "$title",
|
||||||
Spacer(modifier = Modifier.height(35.dp))
|
fontSize = 16.sp,
|
||||||
Text(text = "$title", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = Color(0xFF2A4054))
|
fontWeight = FontWeight.Medium,
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
color = Color(0xFF2A4054))
|
||||||
Box(modifier = Modifier
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
.fillMaxWidth()
|
Box(modifier = Modifier
|
||||||
.height(300.dp), contentAlignment = Alignment.Center) {
|
.fillMaxWidth()
|
||||||
AsyncImage(model = path,
|
.height(300.dp),
|
||||||
contentDescription = "",
|
contentAlignment = Alignment.Center) {
|
||||||
modifier = Modifier.fillMaxSize(),
|
AsyncImage(model = path,
|
||||||
contentScale = ContentScale.FillWidth)
|
contentDescription = "",
|
||||||
}
|
modifier = Modifier.fillMaxSize(),
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
contentScale = ContentScale.FillWidth)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.width(202.dp)
|
.width(202.dp)
|
||||||
.clickable { confirm() }
|
.clickable { confirm() }
|
||||||
.background(color = Color(0xFF3A58B1), shape = RoundedCornerShape(23.dp))
|
.background(color = Color(0xFF3A58B1), shape = RoundedCornerShape(23.dp))
|
||||||
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
||||||
Text(text = "重拍", color = Color.White, fontSize = 15.sp, fontWeight = FontWeight.Medium)
|
Text(text = "重拍",
|
||||||
}
|
color = Color.White,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
|
||||||
if (showAgain) {
|
if (showAgain) {
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.width(202.dp)
|
.width(202.dp)
|
||||||
.clickable { againSubmit() }
|
.clickable { againSubmit() }
|
||||||
.background(color = Color.Red, shape = RoundedCornerShape(23.dp))
|
.background(color = Color.Red, shape = RoundedCornerShape(23.dp))
|
||||||
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
.padding(vertical = 12.dp), contentAlignment = Alignment.Center) {
|
||||||
Text(text = "再次上传", color = Color.White, fontSize = 15.sp, fontWeight = FontWeight.Medium)
|
Text(text = "再次上传",
|
||||||
}
|
color = Color.White,
|
||||||
}
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(20.dp))
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { cancel() }, contentAlignment = Alignment.Center) {
|
.clickable { cancel() },
|
||||||
Text(text = "取消", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = black90)
|
contentAlignment = Alignment.Center) {
|
||||||
}
|
Text(text = "取消",
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = black90)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChoiceMapDialog(dismiss: () -> Unit,
|
fun ChoiceMapDialog(dismiss : () -> Unit, lat : Double?, lng : Double?, address : String?) {
|
||||||
lat: Double?,
|
val context = LocalContext.current
|
||||||
lng: Double?,
|
Dialog(onDismissRequest = { dismiss() }) {
|
||||||
address: String?) {
|
Row(modifier = Modifier
|
||||||
val context = LocalContext.current
|
.fillMaxWidth()
|
||||||
Dialog(onDismissRequest = { dismiss() }) {
|
.height(180.dp)
|
||||||
Row(modifier = Modifier
|
.background(color = Color.White, shape = RoundedCornerShape(8.dp))
|
||||||
.fillMaxWidth()
|
.padding(10.dp),
|
||||||
.height(180.dp)
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
.background(color = Color.White, shape = RoundedCornerShape(8.dp))
|
horizontalArrangement = Arrangement.SpaceAround) {
|
||||||
.padding(10.dp), verticalAlignment = Alignment.CenterVertically,
|
if (MapUtil.isGdMapInstalled(context)) {
|
||||||
horizontalArrangement = Arrangement.SpaceAround) {
|
Column(modifier = Modifier.clickable {
|
||||||
if (MapUtil.isGdMapInstalled(context)) {
|
MapUtil.startNavigationGd(context, lat = lat, lng = lng, address = address)
|
||||||
Column(modifier = Modifier.clickable {
|
dismiss()
|
||||||
MapUtil.startNavigationGd(context, lat = lat, lng = lng, address = address)
|
}) {
|
||||||
dismiss()
|
AsyncImage(model = R.drawable.sv_amap_icon,
|
||||||
}) {
|
contentDescription = "",
|
||||||
AsyncImage(model = R.drawable.sv_amap_icon, contentDescription = "", modifier = Modifier.size(60.dp))
|
modifier = Modifier.size(60.dp))
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
Text(text = "高德地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp)
|
Text(text = "高德地图",
|
||||||
}
|
color = Color.Black,
|
||||||
}
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MapUtil.isBaiduMapInstalled(context)) {
|
if (MapUtil.isBaiduMapInstalled(context)) {
|
||||||
Column(modifier = Modifier.clickable {
|
Column(modifier = Modifier.clickable {
|
||||||
MapUtil.startNavigationBd(context, lat = lat, lng = lng, address = address)
|
MapUtil.startNavigationBd(context, lat = lat, lng = lng, address = address)
|
||||||
dismiss()
|
dismiss()
|
||||||
}) {
|
}) {
|
||||||
AsyncImage(model = R.drawable.sv_baidu_icon, contentDescription = "", modifier = Modifier.size(60.dp))
|
AsyncImage(model = R.drawable.sv_baidu_icon,
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
contentDescription = "",
|
||||||
Text(text = "百度地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp)
|
modifier = Modifier.size(60.dp))
|
||||||
}
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
}
|
Text(text = "百度地图",
|
||||||
|
color = Color.Black,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MapUtil.isTencentInstalled(context)) {
|
if (MapUtil.isTencentInstalled(context)) {
|
||||||
Column(modifier = Modifier.clickable {
|
Column(modifier = Modifier.clickable {
|
||||||
MapUtil.startNavigationTencent(context, lat = lat, lng = lng, address = address)
|
MapUtil.startNavigationTencent(context, lat = lat, lng = lng, address = address)
|
||||||
dismiss()
|
dismiss()
|
||||||
}) {
|
}) {
|
||||||
AsyncImage(model = R.drawable.sv_tencent_icon, contentDescription = "", modifier = Modifier.size(60.dp))
|
AsyncImage(model = R.drawable.sv_tencent_icon,
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
contentDescription = "",
|
||||||
Text(text = "腾讯地图", color = Color.Black, fontWeight = FontWeight.Medium, fontSize = 14.sp)
|
modifier = Modifier.size(60.dp))
|
||||||
}
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
}
|
Text(text = "腾讯地图",
|
||||||
}
|
color = Color.Black,
|
||||||
}
|
fontWeight = FontWeight.Medium,
|
||||||
}
|
fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,7 +23,6 @@ import com.za.servicing.R
|
|||||||
@Composable
|
@Composable
|
||||||
fun HeadView(title : String,
|
fun HeadView(title : String,
|
||||||
onBack : () -> Unit = {},
|
onBack : () -> Unit = {},
|
||||||
warnType : WarnType = WarnType.NULL,
|
|
||||||
isCanBack : Boolean = true,
|
isCanBack : Boolean = true,
|
||||||
action : @Composable () -> Unit = {}) {
|
action : @Composable () -> Unit = {}) {
|
||||||
Column {
|
Column {
|
||||||
@ -43,9 +42,7 @@ fun HeadView(title : String,
|
|||||||
},
|
},
|
||||||
actions = { action() })
|
actions = { action() })
|
||||||
|
|
||||||
if (warnType != WarnType.NULL) {
|
AppTipsView()
|
||||||
AppTipsView()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,31 +16,31 @@ import com.za.servicing.R
|
|||||||
|
|
||||||
|
|
||||||
object LoadingManager {
|
object LoadingManager {
|
||||||
val showLoading = mutableStateOf(false)
|
val showLoading = mutableStateOf(false)
|
||||||
|
|
||||||
fun showLoading() {
|
fun showLoading() {
|
||||||
showLoading.value = true
|
showLoading.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideLoading() {
|
fun hideLoading() {
|
||||||
showLoading.value = false
|
showLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LoadingView() {
|
fun LoadingView() {
|
||||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
||||||
AsyncImage(model = ImageRequest.Builder(LocalContext.current)
|
AsyncImage(model = ImageRequest.Builder(LocalContext.current)
|
||||||
.data(R.drawable.gif_loading)
|
.data(R.drawable.gif_loading).decoderFactory(GifDecoder.Factory()).build(),
|
||||||
.decoderFactory(GifDecoder.Factory())
|
contentDescription = "加载中",
|
||||||
.build(), contentDescription = "加载中", modifier = Modifier
|
modifier = Modifier
|
||||||
.size(70.dp)
|
.size(70.dp)
|
||||||
.align(Alignment.Center))
|
.align(Alignment.Center))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class LoadingState {
|
open class LoadingState {
|
||||||
data object Loading : LoadingState()
|
data object Loading : LoadingState()
|
||||||
data object LoadingFailed : LoadingState()
|
data class LoadingFailed(val msg : String? = "加载失败") : LoadingState()
|
||||||
data object LoadingSuccess : LoadingState()
|
data object LoadingSuccess : LoadingState()
|
||||||
}
|
}
|
@ -25,3 +25,10 @@ data class ReportHistoryBean(val reportType : String? = null,
|
|||||||
val reportTemplate : String? = null,
|
val reportTemplate : String? = null,
|
||||||
val createTime : Long? = null,
|
val createTime : Long? = null,
|
||||||
val state : Int? = null)
|
val state : Int? = null)
|
||||||
|
|
||||||
|
data class TaskNotesBean(val taskNotes : String? = null, //救援要求
|
||||||
|
val feeStandard : String? = null, //收费标准
|
||||||
|
val customerNotes : String? = null, //客户提醒
|
||||||
|
val otherNotes : String? = null, //特殊提醒
|
||||||
|
val modelVinNo : String? = null, //车型
|
||||||
|
val contract : String? = null) //车型
|
@ -4,23 +4,23 @@ import androidx.room.Entity
|
|||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
@Entity(tableName = "ele_work_order")
|
@Entity(tableName = "ele_work_order")
|
||||||
data class EleWorkOrderBean(
|
data class EleWorkOrderBean(@PrimaryKey(autoGenerate = false) val orderId : Int,
|
||||||
@PrimaryKey(autoGenerate = false) val orderId: Int,
|
val userOrderId : Int? = null,
|
||||||
val userOrderId: Int? = null,
|
val date : String? = null, //日期 2023-10-20
|
||||||
val date: String? = null, //日期 2023-10-20
|
val serviceContent : String? = null, //服务须知内容
|
||||||
val serviceContent: String? = null, //服务须知内容
|
val orderWorkStatus : Int? = null, //电子工单状态 1车辆损伤照片 2 客户签名页面 3 服务完成 接车人签名和服务人员签名状态
|
||||||
val orderWorkStatus: Int? = null, //电子工单状态 1车辆损伤照片 2 客户签名页面 3 服务完成 接车人签名和服务人员签名状态
|
val hasBad : Boolean? = null, //车辆是否有损伤
|
||||||
val hasBad: Boolean? = null, //车辆是否有损伤
|
val carNO : String? = null, //车牌号
|
||||||
val carNO: String? = null,//车牌号
|
val carVin : String? = null, //车架号
|
||||||
val carVin: String? = null,//车架号
|
val orderType : String? = null, //救援类型
|
||||||
val orderType: String? = null, //救援类型
|
val isSuccess : Int? = null, //服务是否成功 1 成功 其他失败
|
||||||
val isSuccess: Int? = null, //服务是否成功 1 成功 其他失败
|
val localCustomSignPath : String? = null,
|
||||||
val localCustomSignPath: String? = null,
|
val localAcceptCarSignPath : String? = null, //接车人本地路径
|
||||||
val localAcceptCarSignPath: String? = null,//接车人本地路径
|
val localServicePeopleSignPath : String? = null, //服务人员签名
|
||||||
val localServicePeopleSignPath: String? = null, //服务人员签名
|
val serverCustomSignPath : String? = null,
|
||||||
val serverCustomSignPath: String? = null,
|
val serverAcceptCarSignPath : String? = null, //远程地址
|
||||||
val serverAcceptCarSignPath: String? = null, //远程地址
|
val serverServicePeopleSignPath : String? = null,
|
||||||
val serverServicePeopleSignPath: String? = null,
|
val hasCreatedEleWorkOrderPhoto : Boolean? = null, //是否已经生成电子工单照片
|
||||||
val hasCreatedEleWorkOrderPhoto: Boolean? = null, //是否已经生成电子工单照片
|
val changeBattery : Boolean? = null, //是否更换电瓶
|
||||||
val changeBattery: Boolean? = null //是否更换电瓶
|
var driverChoiceNoNeedReceiveMoney : Boolean? = null) //师傅是否选择了无需收款
|
||||||
)
|
|
||||||
|
@ -7,231 +7,230 @@ import androidx.room.PrimaryKey
|
|||||||
|
|
||||||
@Entity(tableName = "order_info")
|
@Entity(tableName = "order_info")
|
||||||
data class OrderInfo(
|
data class OrderInfo(
|
||||||
@PrimaryKey(autoGenerate = false) var taskId: Int? = null, //订单号 "taskId":5313005
|
@PrimaryKey(autoGenerate = false) var taskId : Int? = null, //订单号 "taskId":5313005
|
||||||
var userOrderId: Int? = null, //订单id
|
var userOrderId : Int? = null, //订单id
|
||||||
var taskCode: String? = null, //订单编码 "taskCode":"ZD20190308009965"
|
var taskCode : String? = null, //订单编码 "taskCode":"ZD20190308009965"
|
||||||
var customerName: String? = null, //客户姓名 "customerName":"越继安"
|
var customerName : String? = null, //客户姓名 "customerName":"越继安"
|
||||||
var customerPhone: String? = null,//客户电话 "customerPhone":"18078815268"
|
var customerPhone : String? = null, //客户电话 "customerPhone":"18078815268"
|
||||||
var carBrand: String? = null,//车辆品牌 "carBrand":""
|
var carBrand : String? = null, //车辆品牌 "carBrand":""
|
||||||
var modelVinNo: String? = null,
|
var modelVinNo : String? = null,
|
||||||
var carModel: String? = null, //车辆型号 "carModel":"秦"
|
var carModel : String? = null, //车辆型号 "carModel":"秦"
|
||||||
var carNo: String? = null, //客户车车牌号 "carNo":"粤AF53918"
|
var carNo : String? = null, //客户车车牌号 "carNo":"粤AF53918"
|
||||||
var carVin: String? = null,//客户车Vin码 "carVin":"LGXC76C30J0132942"
|
var carVin : String? = null, //客户车Vin码 "carVin":"LGXC76C30J0132942"
|
||||||
var taskState: String? = null, //订单状态 "taskState":"GOTO"
|
var taskState : String? = null, //订单状态 "taskState":"GOTO"
|
||||||
var nextState: String? = null,//下一步状态
|
var nextState : String? = null, //下一步状态
|
||||||
var electronOrderState: Int? = null, //电子工单状态:1检查损伤 2生成车辆检查表签字 3作业完成签字
|
var electronOrderState : Int? = null, //电子工单状态:1检查损伤 2生成车辆检查表签字 3作业完成签字
|
||||||
var address: String? = null, //任务地址 "address":"广东省广州市白云区107国道石井凰岗路342号(白云黄石、同德围地区近庆丰兴隆公园)美景大酒店"
|
var address : String? = null, //任务地址 "address":"广东省广州市白云区107国道石井凰岗路342号(白云黄石、同德围地区近庆丰兴隆公园)美景大酒店"
|
||||||
var addressProperty: String? = null, //任务地址类型 "addressProperty":"地面"
|
var addressProperty : String? = null, //任务地址类型 "addressProperty":"地面"
|
||||||
var addressRemark: String? = null, //事发地地址补充
|
var addressRemark : String? = null, //事发地地址补充
|
||||||
var distAddress: String? = null, //目的地地址 "distAddress":"广东省广州市白云区雅岗南大道"
|
var distAddress : String? = null, //目的地地址 "distAddress":"广东省广州市白云区雅岗南大道"
|
||||||
var distAddressRemark: String? = null,//目的地地址补充
|
var distAddressRemark : String? = null, //目的地地址补充
|
||||||
var expectArriveTime: String? = null, //预计到达时间 "expectArriveTime":"2019-03-08 05:11:07"
|
var expectArriveTime : String? = null, //预计到达时间 "expectArriveTime":"2019-03-08 05:11:07"
|
||||||
var serviceTypeName: String? = null, //服务类型 "serviceTypeName":"故障--平板拖车"
|
var serviceTypeName : String? = null, //服务类型 "serviceTypeName":"故障--平板拖车"
|
||||||
var orderSource: String? = null, // "orderSource":"中道救援-比亚迪道路救援项目"
|
var orderSource : String? = null, // "orderSource":"中道救援-比亚迪道路救援项目"
|
||||||
var flowType: Int? = null, //流程类型 0 综合服务 1小修 2拖车 3取送件 4在线技术解决 5组合服务 6拖车简化流程 7武汉交管服务
|
var flowType : Int? = null, //流程类型 0 综合服务 1小修 2拖车 3取送件 4在线技术解决 5组合服务 6拖车简化流程 7武汉交管服务
|
||||||
var settleType: Int? = null,//结算类型 1 月结 2 现金
|
var settleType : Int? = null, //结算类型 1 月结 2 现金
|
||||||
var settleTypeStr: String? = null, //结算类型
|
var settleTypeStr : String? = null, //结算类型
|
||||||
var supplierId: Int? = null,
|
var supplierId : Int? = null,
|
||||||
var startTime: String? = null,//发车时间
|
var startTime : String? = null, //发车时间
|
||||||
var operationTime: String? = null, //作业完成时间
|
var operationTime : String? = null, //作业完成时间
|
||||||
var dispatchTime: String? = null,//派单时间 "dispatchTime":"2019-03-08 04:26:07"
|
var dispatchTime : String? = null, //派单时间 "dispatchTime":"2019-03-08 04:26:07"
|
||||||
var verifyType: Int? = null,//验证类型 "verifyType": 0 跳过验证 1和2 车牌和车架号验证 5 新车验证
|
var verifyType : Int? = null, //验证类型 "verifyType": 0 跳过验证 1和2 车牌和车架号验证 5 新车验证
|
||||||
var verifyValue: String? = null,//验证内容 "verifyValue":"粤AF53918"
|
var verifyValue : String? = null, //验证内容 "verifyValue":"粤AF53918"
|
||||||
var holdon: Boolean? = null,//是否被挂起 "holdon":false
|
var holdon : Boolean? = null, //是否被挂起 "holdon":false
|
||||||
var isCurrent: Boolean? = null, //是否为正在做的任务
|
var isCurrent : Boolean? = null, //是否为正在做的任务
|
||||||
var flow: String? = null, //流程状态 "flow":"START,GOTO,VERIFY,EXAMINE,OPERATION,SENDTO,SETTLEMENT,FINISH"
|
var flow : String? = null, //流程状态 "flow":"START,GOTO,VERIFY,EXAMINE,OPERATION,SENDTO,SETTLEMENT,FINISH"
|
||||||
var externalCode: String? = null, //
|
var externalCode : String? = null, //
|
||||||
var plateNumber: String? = null,
|
var plateNumber : String? = null,
|
||||||
var distaddressProperty: String? = null,
|
var distaddressProperty : String? = null,
|
||||||
var vehiclePointRemark: String? = null,
|
var vehiclePointRemark : String? = null,
|
||||||
var destinationRemark: String? = null,
|
var destinationRemark : String? = null,
|
||||||
var lat: Double? = null,
|
var lat : Double? = null,
|
||||||
var lng: Double? = null,
|
var lng : Double? = null,
|
||||||
var distLat: Double? = null,
|
var distLat : Double? = null,
|
||||||
var distLng: Double? = null,
|
var distLng : Double? = null,
|
||||||
var hotline: String? = null,
|
var hotline : String? = null,
|
||||||
var createTime: String? = null,
|
var createTime : String? = null,
|
||||||
var acceptTime: String? = null,
|
var acceptTime : String? = null,
|
||||||
var arriveTime: String? = null,
|
var arriveTime : String? = null,
|
||||||
var arriveDestTime: String? = null,
|
var arriveDestTime : String? = null,
|
||||||
var needECDevice: Boolean? = null,
|
var needECDevice : Boolean? = null,
|
||||||
var needDestAddress: Boolean? = null,
|
var needDestAddress : Boolean? = null,
|
||||||
var linkToDocs: Boolean? = null,
|
var linkToDocs : Boolean? = null,
|
||||||
var linkToDaDianH5: Boolean? = null,
|
var linkToDaDianH5 : Boolean? = null,
|
||||||
var carFactory: Boolean? = null,
|
var carFactory : Boolean? = null,
|
||||||
var needWaterMarker: Boolean? = null,
|
var needWaterMarker : Boolean? = null,
|
||||||
var needShowPhoneBrand: Boolean? = null,
|
var needShowPhoneBrand : Boolean? = null,
|
||||||
var taskNotes: String? = null, //救援要求
|
var taskNotes : String? = null, //救援要求
|
||||||
var feeStandard: String? = null, //收费标准
|
var feeStandard : String? = null, //收费标准
|
||||||
var customerNotes: String? = null, //客户提醒
|
var customerNotes : String? = null, //客户提醒
|
||||||
var otherNotes: String? = null, //特殊提醒
|
var otherNotes : String? = null, //特殊提醒
|
||||||
var isNewCar: Boolean? = null, //是否新车
|
var isNewCar : Boolean? = null, //是否新车
|
||||||
var ECDeviceString: String? = null,//搭电设备照片提示
|
var ECDeviceString : String? = null, //搭电设备照片提示
|
||||||
var customerReportImgs: String? = null, //客户上报照片,多张照片用;分隔
|
var customerReportImgs : String? = null, //客户上报照片,多张照片用;分隔
|
||||||
var arriveRemind: String? = null,
|
var arriveRemind : String? = null,
|
||||||
var arriveRemindLink: String? = null,
|
var arriveRemindLink : String? = null,
|
||||||
var policyNo: String? = null, // 平安拖车责任险 保单号
|
var policyNo : String? = null, // 平安拖车责任险 保单号
|
||||||
var advanceTime: Long? = null,
|
var advanceTime : Long? = null,
|
||||||
var importantTip: String? = null,
|
var importantTip : String? = null,
|
||||||
var hasReplaceBatteryCapable: Int? = null, //是否有更换电瓶的能力 1 搭电可以更换电瓶 2搭电不可以更换电瓶 其他的不展示
|
var hasReplaceBatteryCapable : Int? = null, //是否有更换电瓶的能力 1 搭电可以更换电瓶 2搭电不可以更换电瓶 其他的不展示
|
||||||
var taskSuccessStatus: Int? = null, //作业是否完成 0 完成 1未完成 拖车默认完成
|
var taskSuccessStatus : Int? = null, //作业是否完成 0 完成 1未完成 拖车默认完成
|
||||||
var tyreNumber: Int? = null, //辅助费用
|
var tyreNumber : Int? = null, //辅助费用
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
constructor(parcel: Parcel) : this(
|
constructor(parcel : Parcel) : this(parcel.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
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.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
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.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readString(),
|
||||||
parcel.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.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Double::class.java.classLoader) as? Double,
|
||||||
parcel.readValue(Double::class.java.classLoader) as? Double,
|
parcel.readValue(Double::class.java.classLoader) as? Double,
|
||||||
parcel.readValue(Double::class.java.classLoader) as? Double,
|
parcel.readValue(Double::class.java.classLoader) as? Double,
|
||||||
parcel.readValue(Double::class.java.classLoader) as? Double,
|
parcel.readValue(Double::class.java.classLoader) as? Double,
|
||||||
parcel.readValue(Double::class.java.classLoader) as? Double,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
||||||
parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Long::class.java.classLoader) as? Long,
|
||||||
parcel.readValue(Long::class.java.classLoader) as? Long,
|
parcel.readString(),
|
||||||
parcel.readString(),
|
parcel.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readValue(Int::class.java.classLoader) as? Int,
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int,
|
parcel.readValue(Int::class.java.classLoader) as? Int) {
|
||||||
parcel.readValue(Int::class.java.classLoader) as? Int) {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
override fun writeToParcel(parcel : Parcel, flags : Int) {
|
||||||
parcel.writeValue(taskId)
|
parcel.writeValue(taskId)
|
||||||
parcel.writeValue(userOrderId)
|
parcel.writeValue(userOrderId)
|
||||||
parcel.writeString(taskCode)
|
parcel.writeString(taskCode)
|
||||||
parcel.writeString(customerName)
|
parcel.writeString(customerName)
|
||||||
parcel.writeString(customerPhone)
|
parcel.writeString(customerPhone)
|
||||||
parcel.writeString(carBrand)
|
parcel.writeString(carBrand)
|
||||||
parcel.writeString(modelVinNo)
|
parcel.writeString(modelVinNo)
|
||||||
parcel.writeString(carModel)
|
parcel.writeString(carModel)
|
||||||
parcel.writeString(carNo)
|
parcel.writeString(carNo)
|
||||||
parcel.writeString(carVin)
|
parcel.writeString(carVin)
|
||||||
parcel.writeString(taskState)
|
parcel.writeString(taskState)
|
||||||
parcel.writeString(nextState)
|
parcel.writeString(nextState)
|
||||||
parcel.writeValue(electronOrderState)
|
parcel.writeValue(electronOrderState)
|
||||||
parcel.writeString(address)
|
parcel.writeString(address)
|
||||||
parcel.writeString(addressProperty)
|
parcel.writeString(addressProperty)
|
||||||
parcel.writeString(addressRemark)
|
parcel.writeString(addressRemark)
|
||||||
parcel.writeString(distAddress)
|
parcel.writeString(distAddress)
|
||||||
parcel.writeString(distAddressRemark)
|
parcel.writeString(distAddressRemark)
|
||||||
parcel.writeString(expectArriveTime)
|
parcel.writeString(expectArriveTime)
|
||||||
parcel.writeString(serviceTypeName)
|
parcel.writeString(serviceTypeName)
|
||||||
parcel.writeString(orderSource)
|
parcel.writeString(orderSource)
|
||||||
parcel.writeValue(flowType)
|
parcel.writeValue(flowType)
|
||||||
parcel.writeValue(settleType)
|
parcel.writeValue(settleType)
|
||||||
parcel.writeString(settleTypeStr)
|
parcel.writeString(settleTypeStr)
|
||||||
parcel.writeValue(supplierId)
|
parcel.writeValue(supplierId)
|
||||||
parcel.writeString(startTime)
|
parcel.writeString(startTime)
|
||||||
parcel.writeString(operationTime)
|
parcel.writeString(operationTime)
|
||||||
parcel.writeString(dispatchTime)
|
parcel.writeString(dispatchTime)
|
||||||
parcel.writeValue(verifyType)
|
parcel.writeValue(verifyType)
|
||||||
parcel.writeString(verifyValue)
|
parcel.writeString(verifyValue)
|
||||||
parcel.writeValue(holdon)
|
parcel.writeValue(holdon)
|
||||||
parcel.writeValue(isCurrent)
|
parcel.writeValue(isCurrent)
|
||||||
parcel.writeString(flow)
|
parcel.writeString(flow)
|
||||||
parcel.writeString(externalCode)
|
parcel.writeString(externalCode)
|
||||||
parcel.writeString(plateNumber)
|
parcel.writeString(plateNumber)
|
||||||
parcel.writeString(distaddressProperty)
|
parcel.writeString(distaddressProperty)
|
||||||
parcel.writeString(vehiclePointRemark)
|
parcel.writeString(vehiclePointRemark)
|
||||||
parcel.writeString(destinationRemark)
|
parcel.writeString(destinationRemark)
|
||||||
parcel.writeValue(lat)
|
parcel.writeValue(lat)
|
||||||
parcel.writeValue(lng)
|
parcel.writeValue(lng)
|
||||||
parcel.writeValue(distLat)
|
parcel.writeValue(distLat)
|
||||||
parcel.writeValue(distLng)
|
parcel.writeValue(distLng)
|
||||||
parcel.writeString(hotline)
|
parcel.writeString(hotline)
|
||||||
parcel.writeString(createTime)
|
parcel.writeString(createTime)
|
||||||
parcel.writeString(acceptTime)
|
parcel.writeString(acceptTime)
|
||||||
parcel.writeString(arriveTime)
|
parcel.writeString(arriveTime)
|
||||||
parcel.writeString(arriveDestTime)
|
parcel.writeString(arriveDestTime)
|
||||||
parcel.writeValue(needECDevice)
|
parcel.writeValue(needECDevice)
|
||||||
parcel.writeValue(needDestAddress)
|
parcel.writeValue(needDestAddress)
|
||||||
parcel.writeValue(linkToDocs)
|
parcel.writeValue(linkToDocs)
|
||||||
parcel.writeValue(linkToDaDianH5)
|
parcel.writeValue(linkToDaDianH5)
|
||||||
parcel.writeValue(carFactory)
|
parcel.writeValue(carFactory)
|
||||||
parcel.writeValue(needWaterMarker)
|
parcel.writeValue(needWaterMarker)
|
||||||
parcel.writeValue(needShowPhoneBrand)
|
parcel.writeValue(needShowPhoneBrand)
|
||||||
parcel.writeString(taskNotes)
|
parcel.writeString(taskNotes)
|
||||||
parcel.writeString(feeStandard)
|
parcel.writeString(feeStandard)
|
||||||
parcel.writeString(customerNotes)
|
parcel.writeString(customerNotes)
|
||||||
parcel.writeString(otherNotes)
|
parcel.writeString(otherNotes)
|
||||||
parcel.writeValue(isNewCar)
|
parcel.writeValue(isNewCar)
|
||||||
parcel.writeString(ECDeviceString)
|
parcel.writeString(ECDeviceString)
|
||||||
parcel.writeString(customerReportImgs)
|
parcel.writeString(customerReportImgs)
|
||||||
parcel.writeString(arriveRemind)
|
parcel.writeString(arriveRemind)
|
||||||
parcel.writeString(arriveRemindLink)
|
parcel.writeString(arriveRemindLink)
|
||||||
parcel.writeString(policyNo)
|
parcel.writeString(policyNo)
|
||||||
parcel.writeValue(advanceTime)
|
parcel.writeValue(advanceTime)
|
||||||
parcel.writeString(importantTip)
|
parcel.writeString(importantTip)
|
||||||
parcel.writeValue(hasReplaceBatteryCapable)
|
parcel.writeValue(hasReplaceBatteryCapable)
|
||||||
parcel.writeValue(taskSuccessStatus)
|
parcel.writeValue(taskSuccessStatus)
|
||||||
parcel.writeValue(tyreNumber)
|
parcel.writeValue(tyreNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun describeContents(): Int {
|
override fun describeContents() : Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object CREATOR : Parcelable.Creator<OrderInfo> {
|
companion object CREATOR : Parcelable.Creator<OrderInfo> {
|
||||||
override fun createFromParcel(parcel: Parcel): OrderInfo {
|
override fun createFromParcel(parcel : Parcel) : OrderInfo {
|
||||||
return OrderInfo(parcel)
|
return OrderInfo(parcel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newArray(size: Int): Array<OrderInfo?> {
|
override fun newArray(size : Int) : Array<OrderInfo?> {
|
||||||
return arrayOfNulls(size)
|
return arrayOfNulls(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,56 +1,55 @@
|
|||||||
package com.za.bean.request
|
package com.za.bean.request
|
||||||
|
|
||||||
data class OrderListRequest(
|
data class OrderListRequest(
|
||||||
val vehicleId: Int? = null,
|
val vehicleId : Int? = null,
|
||||||
val deviceId: String? = null,
|
val deviceId : String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 照片模版请求数据
|
* 照片模版请求数据
|
||||||
*/
|
*/
|
||||||
data class PhotoTemplateRequest(val userOrderId: Int? = null)
|
data class PhotoTemplateRequest(val userOrderId : Int? = null)
|
||||||
|
|
||||||
|
|
||||||
//照片识别
|
//照片识别
|
||||||
data class OrderPhotoOcrRecognizeRequest(
|
data class OrderPhotoOcrRecognizeRequest(
|
||||||
val userOrderId: Int? = null,
|
val userOrderId : Int? = null,
|
||||||
val recognizeType: Int? = null,
|
val recognizeType : Int? = null,
|
||||||
val imgUrl: String? = null,
|
val imgUrl : String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class TaskFinishRequest(
|
data class TaskFinishRequest(val userOrderId : Int? = null,
|
||||||
val userOrderId: Int? = null,
|
val lat : Double? = null,
|
||||||
val lat: Double? = null,
|
val lng : Double? = null,
|
||||||
val lng: Double? = null,
|
val operateTime : Long? = null)
|
||||||
val operateTime: Long? = null)
|
|
||||||
|
|
||||||
data class GiveUpTaskRequest(
|
data class GiveUpTaskRequest(
|
||||||
val taskId: Int? = null, //任务id
|
val taskId : Int? = null, //任务id
|
||||||
val userId: Int? = null, //用户id
|
val userId : Int? = null, //用户id
|
||||||
val vehicleId: Int? = null, //车辆id
|
val vehicleId : Int? = null, //车辆id
|
||||||
val lat: Double? = null,
|
val lat : Double? = null,
|
||||||
val lng: Double? = null,
|
val lng : Double? = null,
|
||||||
val address: String? = null,
|
val address : String? = null,
|
||||||
val templatePhotoInfoList: List<String?>? = null, //照片数据
|
val templatePhotoInfoList : List<String?>? = null, //照片数据
|
||||||
val pushGiveUpFlag: Int? = null, //1 是 0否
|
val pushGiveUpFlag : Int? = null, //1 是 0否
|
||||||
)
|
)
|
||||||
|
|
||||||
data class UpdatePhotoRequest(
|
data class UpdatePhotoRequest(val taskId : Int? = null,
|
||||||
val taskId: Int? = null,
|
val taskState : String? = null,
|
||||||
val taskState: String? = null,
|
val picturePosition : Int? = null, //图片位置
|
||||||
val picturePosition: Int? = null, //图片位置
|
val picturePath : String? = null, //图片路径
|
||||||
val picturePath: String? = null,//图片路径
|
val imgInfo : String? = null)
|
||||||
val imgInfo: String? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
data class SwitchTaskRequest(val currentTaskId: Int? = null,
|
data class SwitchTaskRequest(val currentTaskId : Int? = null,
|
||||||
val nextTaskId: Int? = null,
|
val nextTaskId : Int? = null,
|
||||||
val userId: Int? = null,
|
val userId : Int? = null,
|
||||||
val vehicleId: Int? = null)
|
val vehicleId : Int? = null)
|
||||||
|
|
||||||
data class HistoryTasksRequest(val userId: Int? = null, val vehicleId: Int? = null)
|
data class HistoryTasksRequest(val userId : Int? = null, val vehicleId : Int? = null)
|
||||||
|
|
||||||
data class HistoryPhotoTemplateRequest(val taskId: Int? = null)
|
data class HistoryPhotoTemplateRequest(val taskId : Int? = null)
|
||||||
|
|
||||||
data class HistoryDetailRequest(val taskId: Int? = null)
|
data class HistoryDetailRequest(val taskId : Int? = null)
|
||||||
|
|
||||||
|
data class TaskNotesRequest(val taskId : Int? = null)
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ import android.app.Application
|
|||||||
import com.amap.api.location.AMapLocation
|
import com.amap.api.location.AMapLocation
|
||||||
import com.blankj.utilcode.util.AppUtils
|
import com.blankj.utilcode.util.AppUtils
|
||||||
import com.tencent.mmkv.MMKV
|
import com.tencent.mmkv.MMKV
|
||||||
|
import com.za.base.AppConfig
|
||||||
|
import com.za.base.Const
|
||||||
import com.za.bean.db.order.OrderInfo
|
import com.za.bean.db.order.OrderInfo
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
import com.za.room.RoomHelper
|
import com.za.room.RoomHelper
|
||||||
@ -112,6 +114,18 @@ object GlobalData : GlobalLocalData() {
|
|||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var networkEnv : Int
|
||||||
|
get() {
|
||||||
|
return if (AppConfig.isRelease) {
|
||||||
|
mmkv.decodeInt("isReviewEnv", Const.NetEnv.Main)
|
||||||
|
} else {
|
||||||
|
mmkv.decodeInt("isReviewEnv", Const.NetEnv.CRM1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
mmkv.encode("isReviewEnv", value)
|
||||||
|
}
|
||||||
|
|
||||||
fun clearUserCache() {
|
fun clearUserCache() {
|
||||||
token = null
|
token = null
|
||||||
aesKey = null
|
aesKey = null
|
||||||
@ -119,6 +133,16 @@ object GlobalData : GlobalLocalData() {
|
|||||||
driverInfoBean = null
|
driverInfoBean = null
|
||||||
loginTime = null
|
loginTime = null
|
||||||
isLoginRecognition = null
|
isLoginRecognition = null
|
||||||
|
|
||||||
|
if (AppConfig.isRelease) {
|
||||||
|
networkEnv = if (AppConfig.isRelease) {
|
||||||
|
Const.NetEnv.Main
|
||||||
|
} else {
|
||||||
|
Const.NetEnv.CRM1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearAllOrderCache() {
|
fun clearAllOrderCache() {
|
||||||
|
@ -18,13 +18,9 @@ object ZDManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun thirdSdkInit(isRelease : Boolean = false) {
|
private fun thirdSdkInit(isRelease : Boolean = false) {
|
||||||
if (isRelease) {
|
|
||||||
AppConfig.release()
|
|
||||||
} else {
|
|
||||||
AppConfig.crm1()
|
|
||||||
}
|
|
||||||
GlobalData.application = application // 在 Application 中初始化 MMKV,所有进程共享同一存储路径
|
GlobalData.application = application // 在 Application 中初始化 MMKV,所有进程共享同一存储路径
|
||||||
MMKV.initialize(application)
|
MMKV.initialize(application)
|
||||||
|
AppConfig.init(isRelease)
|
||||||
Bugly.init(application, "6972a6b56d", true)
|
Bugly.init(application, "6972a6b56d", true)
|
||||||
LogUtil.init(application)
|
LogUtil.init(application)
|
||||||
RoomHelper.init(application)
|
RoomHelper.init(application)
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.za.common.util
|
||||||
|
|
||||||
|
class PermissionUtil {
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,7 @@ import com.za.bean.ReportHistoryRequest
|
|||||||
import com.za.bean.ReportInfoRequest
|
import com.za.bean.ReportInfoRequest
|
||||||
import com.za.bean.ReportItem
|
import com.za.bean.ReportItem
|
||||||
import com.za.bean.SettleInfoRequest
|
import com.za.bean.SettleInfoRequest
|
||||||
|
import com.za.bean.TaskNotesBean
|
||||||
import com.za.bean.TaskSettlementAndTraceBean
|
import com.za.bean.TaskSettlementAndTraceBean
|
||||||
import com.za.bean.UpdateVersionBean
|
import com.za.bean.UpdateVersionBean
|
||||||
import com.za.bean.UpdateVersionRequest
|
import com.za.bean.UpdateVersionRequest
|
||||||
@ -61,6 +62,7 @@ import com.za.bean.request.SaveEleOrderRequest
|
|||||||
import com.za.bean.request.SwitchTaskRequest
|
import com.za.bean.request.SwitchTaskRequest
|
||||||
import com.za.bean.request.TaskFinishRequest
|
import com.za.bean.request.TaskFinishRequest
|
||||||
import com.za.bean.request.TaskFinishResponse
|
import com.za.bean.request.TaskFinishResponse
|
||||||
|
import com.za.bean.request.TaskNotesRequest
|
||||||
import com.za.bean.request.TodayMaintainRequest
|
import com.za.bean.request.TodayMaintainRequest
|
||||||
import com.za.bean.request.TodayMaintainUploadRequest
|
import com.za.bean.request.TodayMaintainUploadRequest
|
||||||
import com.za.bean.request.TodayMaintainbean
|
import com.za.bean.request.TodayMaintainbean
|
||||||
@ -284,4 +286,7 @@ interface ApiService {
|
|||||||
|
|
||||||
@POST("driverApp/supplier/iaiCompareFace")
|
@POST("driverApp/supplier/iaiCompareFace")
|
||||||
fun iaiCompareFace(@Body info : DriverFaceCompareRequest) : Observable<BaseResponse<IaiCompareFaceBean>>
|
fun iaiCompareFace(@Body info : DriverFaceCompareRequest) : Observable<BaseResponse<IaiCompareFaceBean>>
|
||||||
|
|
||||||
|
@POST("driverApp/task/getTaskNotes")
|
||||||
|
fun getTaskNotes(@Body request : TaskNotesRequest) : Observable<BaseResponse<TaskNotesBean>>
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import com.blankj.utilcode.util.ThreadUtils
|
|||||||
import com.blankj.utilcode.util.ToastUtils
|
import com.blankj.utilcode.util.ToastUtils
|
||||||
import com.google.gson.JsonParseException
|
import com.google.gson.JsonParseException
|
||||||
import com.za.base.Const
|
import com.za.base.Const
|
||||||
|
import com.za.base.view.NetWarnBean
|
||||||
|
import com.za.base.view.warnBean
|
||||||
import com.za.bean.BaseResponse
|
import com.za.bean.BaseResponse
|
||||||
import com.za.common.GlobalData
|
import com.za.common.GlobalData
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
@ -32,6 +34,11 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
|
|||||||
override fun onNext(tBaseResponse : BaseResponse<T>) {
|
override fun onNext(tBaseResponse : BaseResponse<T>) {
|
||||||
if (tBaseResponse.isOk) {
|
if (tBaseResponse.isOk) {
|
||||||
doSuccess(tBaseResponse.result)
|
doSuccess(tBaseResponse.result)
|
||||||
|
ThreadUtils.runOnUiThread {
|
||||||
|
if (warnBean.value != null && warnBean.value is NetWarnBean) {
|
||||||
|
warnBean.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
when (tBaseResponse.code) {
|
when (tBaseResponse.code) {
|
||||||
3, 401 -> handlerTokenExpired()
|
3, 401 -> handlerTokenExpired()
|
||||||
@ -67,15 +74,18 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
|
|||||||
|
|
||||||
is ConnectException -> {
|
is ConnectException -> {
|
||||||
doFailure(Const.NetWorkException, "与服务器断开连接")
|
doFailure(Const.NetWorkException, "与服务器断开连接")
|
||||||
|
handlerNetError()
|
||||||
}
|
}
|
||||||
|
|
||||||
is UnknownHostException -> {
|
is UnknownHostException -> {
|
||||||
doFailure(Const.NetWorkException, "与服务器断开连接")
|
doFailure(Const.NetWorkException, "与服务器断开连接")
|
||||||
|
handlerNetError()
|
||||||
}
|
}
|
||||||
|
|
||||||
is SSLHandshakeException -> {
|
is SSLHandshakeException -> {
|
||||||
doFailure(1, "证书验证失败")
|
doFailure(1, "证书验证失败")
|
||||||
LogUtil.print("SSLHandshakeException", e)
|
LogUtil.print("SSLHandshakeException", e)
|
||||||
|
handlerNetError()
|
||||||
}
|
}
|
||||||
|
|
||||||
is TimeoutException -> {
|
is TimeoutException -> {
|
||||||
@ -86,6 +96,7 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
|
|||||||
is SocketTimeoutException -> {
|
is SocketTimeoutException -> {
|
||||||
doFailure(Const.NetWorkException, "网络连接超时2")
|
doFailure(Const.NetWorkException, "网络连接超时2")
|
||||||
LogUtil.print("SocketTimeoutException2", e)
|
LogUtil.print("SocketTimeoutException2", e)
|
||||||
|
handlerNetError()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
@ -102,6 +113,15 @@ abstract class BaseObserver<T> : Observer<BaseResponse<T>> {
|
|||||||
|
|
||||||
abstract fun doFailure(code : Int, msg : String?)
|
abstract fun doFailure(code : Int, msg : String?)
|
||||||
|
|
||||||
|
private fun handlerNetError() {
|
||||||
|
ThreadUtils.runOnUiThread {
|
||||||
|
if (warnBean.value == null) {
|
||||||
|
warnBean.value = NetWarnBean("当前网络异常")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private fun handlerTokenExpired() {
|
private fun handlerTokenExpired() {
|
||||||
ThreadUtils.runOnUiThread {
|
ThreadUtils.runOnUiThread {
|
||||||
try {
|
try {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.za.net
|
package com.za.net
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.za.base.AppConfig
|
import com.za.base.AppConfig
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@ -38,6 +37,11 @@ object RetrofitHelper {
|
|||||||
|
|
||||||
}.setLevel(HttpLoggingInterceptor.Level.BODY)
|
}.setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
apiService = null
|
||||||
|
retrofit = null
|
||||||
|
}
|
||||||
|
|
||||||
fun getDefaultService() : ApiService {
|
fun getDefaultService() : ApiService {
|
||||||
return if (apiService == null) {
|
return if (apiService == null) {
|
||||||
apiService = getDefaultRetrofit().create(ApiService::class.java)
|
apiService = getDefaultRetrofit().create(ApiService::class.java)
|
||||||
|
@ -11,7 +11,7 @@ import com.za.room.db.GlobalRoom
|
|||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
object RoomHelper {
|
object RoomHelper {
|
||||||
const val VERSION: Int = 40
|
const val VERSION: Int = 41
|
||||||
private lateinit var mContext: Context
|
private lateinit var mContext: Context
|
||||||
var db: GlobalRoom? = null
|
var db: GlobalRoom? = null
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.za.service.mqtt
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.za.common.GlobalData
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
import com.za.service.ServiceManager
|
import com.za.service.ServiceManager
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -59,7 +60,7 @@ object MyMqttClient {
|
|||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
val message = String(mqttMessage.payload)
|
val message = String(mqttMessage.payload)
|
||||||
LogUtil.print("MyMqttClient ", "Message arrived: $message")
|
LogUtil.print("MyMqttClient ", "Message arrived: $message")
|
||||||
ServiceManager.handlerPushMsg(message) // Pass the message to ServiceManager for processing
|
ServiceManager.handlerPushMsg(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +97,11 @@ object MyMqttClient {
|
|||||||
//检测mqtt连接状态
|
//检测mqtt连接状态
|
||||||
fun publishMessage() {
|
fun publishMessage() {
|
||||||
if (mqttClient.isConnected) {
|
if (mqttClient.isConnected) {
|
||||||
LogUtil.print("MyMqttClient ", "publishMessage success")
|
LogUtil.print("MyMqttClient ", "mqttClient.hasConnected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
connect()
|
LogUtil.print("MyMqttClient ", "mqttClient 断开重新初始化")
|
||||||
|
ServiceManager.initialize(GlobalData.application)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeTopic() {
|
private fun subscribeTopic() {
|
||||||
|
@ -7,7 +7,6 @@ import android.content.res.Configuration;
|
|||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.BaseBundle;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
@ -84,7 +84,6 @@ public class HandWriteEditView extends AppCompatEditText {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置行高
|
* 设置行高
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void setLineHeight(float lineHeight) {
|
public void setLineHeight(float lineHeight) {
|
||||||
this.lineHeight = lineHeight;
|
this.lineHeight = lineHeight;
|
||||||
@ -102,7 +101,7 @@ public class HandWriteEditView extends AppCompatEditText {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SpannableString mSpan = new SpannableString("1");
|
SpannableString mSpan = new SpannableString("1");
|
||||||
mSpan.setSpan(new ImageSpan(getContext(), srcBitmap), mSpan.length() - 1, mSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
mSpan.setSpan(new ImageSpan(getContext(), srcBitmap, ImageSpan.ALIGN_BASELINE), mSpan.length() - 1, mSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
Editable editable = getText();
|
Editable editable = getText();
|
||||||
//获取光标所在位置
|
//获取光标所在位置
|
||||||
|
@ -0,0 +1,461 @@
|
|||||||
|
package com.za.ui.camera
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Bitmap.CompressFormat
|
||||||
|
import android.graphics.Matrix
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.camera.core.CameraSelector
|
||||||
|
import androidx.camera.core.ExperimentalGetImage
|
||||||
|
import androidx.camera.core.ImageAnalysis
|
||||||
|
import androidx.camera.core.ImageCapture
|
||||||
|
import androidx.camera.core.ImageCaptureException
|
||||||
|
import androidx.camera.core.ImageProxy
|
||||||
|
import androidx.camera.view.LifecycleCameraController
|
||||||
|
import androidx.camera.view.PreviewView
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.blankj.utilcode.util.ImageUtils
|
||||||
|
import com.blankj.utilcode.util.ToastUtils
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.google.mlkit.vision.common.InputImage
|
||||||
|
import com.google.mlkit.vision.face.Face
|
||||||
|
import com.google.mlkit.vision.face.FaceDetection
|
||||||
|
import com.google.mlkit.vision.face.FaceDetectorOptions
|
||||||
|
import com.za.bean.request.DriverFaceCompareBean
|
||||||
|
import com.za.bean.request.DriverFaceCompareRequest
|
||||||
|
import com.za.common.GlobalData
|
||||||
|
import com.za.common.log.LogUtil
|
||||||
|
import com.za.common.speech.SpeechManager
|
||||||
|
import com.za.net.BaseObserver
|
||||||
|
import com.za.net.CommonMethod
|
||||||
|
import com.za.net.RetrofitHelper
|
||||||
|
import com.za.servicing.R
|
||||||
|
import com.za.signature.view.CircleImageView
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
class ServicePeopleRealActivity : AppCompatActivity() {
|
||||||
|
private lateinit var lifecycleCameraController : LifecycleCameraController
|
||||||
|
private lateinit var cameraExecutor : ExecutorService
|
||||||
|
private var avatarBitmap : Bitmap? = null
|
||||||
|
private var isActivityActive = true
|
||||||
|
|
||||||
|
private var currentStep = 0
|
||||||
|
private val steps = listOf("请保持面部居中", "请向左转头", "请向右转头", "请保持面部居中")
|
||||||
|
|
||||||
|
private var isStepCompleted = false
|
||||||
|
private lateinit var viewFinder : PreviewView
|
||||||
|
private lateinit var stepText : TextView
|
||||||
|
private lateinit var confirmationLayout : FrameLayout
|
||||||
|
private lateinit var previewImage : CircleImageView
|
||||||
|
private lateinit var retryButton : Button
|
||||||
|
private lateinit var confirmButton : Button
|
||||||
|
|
||||||
|
private val faceDetector = FaceDetection.getClient(FaceDetectorOptions.Builder()
|
||||||
|
.setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
|
||||||
|
.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
|
||||||
|
.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL).build())
|
||||||
|
|
||||||
|
private var loadingDialog : AlertDialog? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState : Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_service_people_real) // 初始化控制器
|
||||||
|
lifecycleCameraController = LifecycleCameraController(this).apply {
|
||||||
|
cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
|
||||||
|
setEnabledUseCases(LifecycleCameraController.IMAGE_CAPTURE or LifecycleCameraController.IMAGE_ANALYSIS)
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeViews()
|
||||||
|
setupClickListeners()
|
||||||
|
|
||||||
|
if (allPermissionsGranted()) {
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
updateStepUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeViews() {
|
||||||
|
viewFinder = findViewById(R.id.viewFinder)
|
||||||
|
viewFinder.controller = lifecycleCameraController // 将控制器与生命周期绑定
|
||||||
|
lifecycleCameraController.bindToLifecycle(this)
|
||||||
|
|
||||||
|
stepText = findViewById(R.id.stepText)
|
||||||
|
confirmationLayout = findViewById(R.id.confirmationLayout)
|
||||||
|
previewImage = findViewById(R.id.previewImage)
|
||||||
|
retryButton = findViewById(R.id.retryButton)
|
||||||
|
confirmButton = findViewById(R.id.confirmButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupClickListeners() {
|
||||||
|
retryButton.setOnClickListener {
|
||||||
|
resetDetection()
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmButton.setOnClickListener {
|
||||||
|
returnPhotoResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun captureImage() {
|
||||||
|
lifecycleCameraController.takePicture(ContextCompat.getMainExecutor(this),
|
||||||
|
object : ImageCapture.OnImageCapturedCallback() {
|
||||||
|
@OptIn(ExperimentalGetImage::class)
|
||||||
|
override fun onCaptureSuccess(image : ImageProxy) {
|
||||||
|
|
||||||
|
val mediaImage = image.image
|
||||||
|
LogUtil.print("拍照成功", image.imageInfo.toString())
|
||||||
|
if (mediaImage != null) {
|
||||||
|
val inputImage =
|
||||||
|
InputImage.fromMediaImage(mediaImage, image.imageInfo.rotationDegrees)
|
||||||
|
|
||||||
|
faceDetector.process(inputImage).addOnSuccessListener { faces ->
|
||||||
|
when {
|
||||||
|
faces.isEmpty() -> {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this@ServicePeopleRealActivity,
|
||||||
|
"未检测到人脸",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
faces.size > 1 -> {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this@ServicePeopleRealActivity,
|
||||||
|
"检测到多个人脸,请确保画面中只有一个人脸",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
LogUtil.print("人脸检测成功", faces[0].toString())
|
||||||
|
avatarBitmap = handlerBitmap(image.toBitmap(), image.imageInfo.rotationDegrees)
|
||||||
|
LogUtil.print("人脸认证通过", faces[0].toString())
|
||||||
|
runOnUiThread {
|
||||||
|
showConfirmation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.addOnFailureListener { e ->
|
||||||
|
LogUtil.print("人脸检测失败", e)
|
||||||
|
if (isActivityActive) {
|
||||||
|
Toast.makeText(this@ServicePeopleRealActivity,
|
||||||
|
"人脸检测失败",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}.addOnCompleteListener {
|
||||||
|
image.close()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
image.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(exc : ImageCaptureException) {
|
||||||
|
LogUtil.print("拍照失败", exc)
|
||||||
|
if (isActivityActive) {
|
||||||
|
Toast.makeText(this@ServicePeopleRealActivity,
|
||||||
|
"拍照失败",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isValidFace(face : Face, imageWidth : Int, imageHeight : Int) : Boolean {
|
||||||
|
val faceBounds = face.boundingBox
|
||||||
|
val faceCenterX = faceBounds.centerX()
|
||||||
|
val faceCenterY = faceBounds.centerY()
|
||||||
|
val imageCenterX = imageWidth / 2
|
||||||
|
val imageCenterY = imageHeight / 2
|
||||||
|
|
||||||
|
// 计算人脸框占图片的比例
|
||||||
|
val faceWidthRatio = faceBounds.width().toFloat() / imageWidth
|
||||||
|
val faceHeightRatio = faceBounds.height().toFloat() / imageHeight
|
||||||
|
|
||||||
|
// 检查人脸是否居中(允许30%的偏移)
|
||||||
|
val centerThreshold = imageWidth * 0.8f
|
||||||
|
val isCentered =
|
||||||
|
abs(faceCenterX - imageCenterX) < centerThreshold && abs(faceCenterY - imageCenterY) < centerThreshold
|
||||||
|
|
||||||
|
// 检查人脸大小是否合适(建议占据图片30%-70%的区域)
|
||||||
|
val isProperSize = faceWidthRatio in 0.6f .. 0.7f && faceHeightRatio in 0.6f .. 0.7f
|
||||||
|
|
||||||
|
// 检查是否是正面人脸且睁眼
|
||||||
|
val isFrontalFace = abs(face.headEulerAngleY) < 15 && // 左右角度
|
||||||
|
abs(face.headEulerAngleX) < 15 && // 上下角度
|
||||||
|
abs(face.headEulerAngleZ) < 15 && // 倾斜角度
|
||||||
|
face.rightEyeOpenProbability != null && face.leftEyeOpenProbability != null && face.rightEyeOpenProbability !! > 0.8 && face.leftEyeOpenProbability !! > 0.8
|
||||||
|
|
||||||
|
return isCentered && isProperSize && isFrontalFace
|
||||||
|
}
|
||||||
|
|
||||||
|
//校正图片,解决图片可能翻转的问题
|
||||||
|
private val rotationMatrix = Matrix()
|
||||||
|
private fun handlerBitmap(bitmap : Bitmap, degrees : Int?) : Bitmap {
|
||||||
|
if (degrees == null || degrees == 0) return bitmap
|
||||||
|
rotationMatrix.reset()
|
||||||
|
rotationMatrix.postRotate(degrees.toFloat())
|
||||||
|
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, rotationMatrix, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetDetection() {
|
||||||
|
currentStep = 0
|
||||||
|
isStepCompleted = false
|
||||||
|
avatarBitmap = null
|
||||||
|
confirmationLayout.visibility = View.GONE
|
||||||
|
stepText.visibility = View.VISIBLE
|
||||||
|
updateStepUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startCamera() {
|
||||||
|
lifecycleCameraController.setImageAnalysisAnalyzer(ContextCompat.getMainExecutor(this@ServicePeopleRealActivity),
|
||||||
|
FaceAnalyzer { handleFaceDetection(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleFaceDetection(eulerY : Float) {
|
||||||
|
if (! isActivityActive) return
|
||||||
|
|
||||||
|
when (currentStep) {
|
||||||
|
0 -> {
|
||||||
|
if (abs(eulerY) < 15) {
|
||||||
|
if (! isStepCompleted) {
|
||||||
|
isStepCompleted = true
|
||||||
|
proceedToNextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
if (eulerY > 15) {
|
||||||
|
if (! isStepCompleted) {
|
||||||
|
isStepCompleted = true
|
||||||
|
proceedToNextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
if (eulerY < - 15) {
|
||||||
|
if (! isStepCompleted) {
|
||||||
|
isStepCompleted = true
|
||||||
|
proceedToNextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
3 -> {
|
||||||
|
if (abs(eulerY) < 15) {
|
||||||
|
if (! isStepCompleted) {
|
||||||
|
isStepCompleted = true
|
||||||
|
runOnUiThread {
|
||||||
|
captureImage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showConfirmation() {
|
||||||
|
avatarBitmap?.let { bitmap ->
|
||||||
|
Glide.with(previewImage).load(bitmap).into(previewImage)
|
||||||
|
confirmationLayout.visibility = View.VISIBLE
|
||||||
|
stepText.visibility = View.GONE
|
||||||
|
} ?: run {
|
||||||
|
AlertDialog.Builder(this).setTitle("提示")
|
||||||
|
.setMessage("未检测到有效的人脸照片,是否重新开始检测?")
|
||||||
|
.setPositiveButton("重新检测") { dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
resetDetectionProcess()
|
||||||
|
}.setNegativeButton("取消") { dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}.setCancelable(false).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetDetectionProcess() {
|
||||||
|
currentStep = 0
|
||||||
|
isStepCompleted = false
|
||||||
|
avatarBitmap = null
|
||||||
|
|
||||||
|
confirmationLayout.visibility = View.GONE
|
||||||
|
stepText.visibility = View.VISIBLE
|
||||||
|
stepText.text = steps[currentStep]
|
||||||
|
|
||||||
|
startCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proceedToNextStep() {
|
||||||
|
currentStep ++
|
||||||
|
isStepCompleted = false
|
||||||
|
if (currentStep < steps.size) {
|
||||||
|
updateStepUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateStepUI() {
|
||||||
|
stepText.visibility = View.VISIBLE
|
||||||
|
stepText.text = steps[currentStep]
|
||||||
|
|
||||||
|
SpeechManager.releaseMediaPlayer()
|
||||||
|
when (currentStep) {
|
||||||
|
0 -> SpeechManager.playFaceCenter()
|
||||||
|
1 -> SpeechManager.playFaceLeft()
|
||||||
|
2 -> SpeechManager.playFaceRight()
|
||||||
|
3 -> SpeechManager.playFaceCenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun returnPhotoResult() {
|
||||||
|
avatarBitmap?.let { bitmap -> // 保存图片到临时文件
|
||||||
|
val file = ImageUtils.save2Album(bitmap, CompressFormat.JPEG, 100)
|
||||||
|
if (file?.exists() == true) { // 创建返回结果
|
||||||
|
val resultIntent = Intent()
|
||||||
|
resultIntent.putExtra("path", file.absolutePath)
|
||||||
|
setResult(RESULT_OK, resultIntent)
|
||||||
|
finish()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "照片保存失败,请重试", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
Toast.makeText(this, "未获取到有效的人脸照片,请重试", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dismissLoadingDialog() {
|
||||||
|
loadingDialog?.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUploadFailedDialog() {
|
||||||
|
AlertDialog.Builder(this).setTitle("上传失败").setMessage("人脸照片上传失败,请重新识别")
|
||||||
|
.setPositiveButton("重新识别") { dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
resetDetection()
|
||||||
|
}.setNegativeButton("取消") { dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}.setCancelable(false).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private fun doUploadImg(file : File) {
|
||||||
|
CommonMethod.uploadImage(file, success = {
|
||||||
|
if (it.isNullOrBlank()) {
|
||||||
|
ToastUtils.showLong("上传失败")
|
||||||
|
return@uploadImage
|
||||||
|
}
|
||||||
|
doUpload(it)
|
||||||
|
}, failed = {
|
||||||
|
dismissLoadingDialog()
|
||||||
|
showUploadFailedDialog()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doUpload(url : String) {
|
||||||
|
val request = DriverFaceCompareRequest(vehicleId = GlobalData.driverInfoBean?.vehicleId,
|
||||||
|
driverId = GlobalData.driverInfoBean?.userId,
|
||||||
|
photoUrl = url)
|
||||||
|
RetrofitHelper.getDefaultService().driverFaceCompare(request).subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : BaseObserver<DriverFaceCompareBean>() {
|
||||||
|
override fun doSuccess(it : DriverFaceCompareBean?) {
|
||||||
|
ToastUtils.showLong("头像上传成功!")
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
|
LogUtil.print("doUpload addRealAvatarActivity failed",
|
||||||
|
"code==$msg request==$request")
|
||||||
|
showUploadFailedDialog()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
|
||||||
|
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode : Int,
|
||||||
|
permissions : Array<String>,
|
||||||
|
grantResults : IntArray) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
if (requestCode == REQUEST_CODE_PERMISSIONS) {
|
||||||
|
if (allPermissionsGranted()) {
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "需要相机权限", Toast.LENGTH_SHORT).show()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
isActivityActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
isActivityActive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
isActivityActive = false
|
||||||
|
cameraExecutor.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FaceAnalyzer(private val listener : (Float) -> Unit) : ImageAnalysis.Analyzer {
|
||||||
|
private val detector = FaceDetection.getClient(FaceDetectorOptions.Builder()
|
||||||
|
.setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
|
||||||
|
.setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_NONE)
|
||||||
|
.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_NONE).build())
|
||||||
|
|
||||||
|
@ExperimentalGetImage
|
||||||
|
override fun analyze(imageProxy : ImageProxy) {
|
||||||
|
val mediaImage = imageProxy.image
|
||||||
|
if (mediaImage != null) {
|
||||||
|
val image =
|
||||||
|
InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
|
||||||
|
|
||||||
|
detector.process(image).addOnSuccessListener { faces ->
|
||||||
|
if (faces.isNotEmpty()) {
|
||||||
|
listener(faces[0].headEulerAngleY)
|
||||||
|
}
|
||||||
|
}.addOnCompleteListener {
|
||||||
|
imageProxy.close()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
imageProxy.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val REQUEST_CODE_PERMISSIONS = 10
|
||||||
|
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,10 @@ import android.view.ViewGroup
|
|||||||
import android.webkit.JavascriptInterface
|
import android.webkit.JavascriptInterface
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -33,7 +31,6 @@ import com.tencent.smtt.sdk.WebView.setWebContentsDebuggingEnabled
|
|||||||
import com.tencent.smtt.sdk.WebViewClient
|
import com.tencent.smtt.sdk.WebViewClient
|
||||||
import com.za.base.AppConfig
|
import com.za.base.AppConfig
|
||||||
import com.za.base.BaseActivity
|
import com.za.base.BaseActivity
|
||||||
import com.za.base.theme.headPadding
|
|
||||||
import com.za.base.view.HeadView
|
import com.za.base.view.HeadView
|
||||||
import com.za.common.GlobalData
|
import com.za.common.GlobalData
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
@ -168,11 +165,6 @@ private fun CommonH5Screen(url : String,
|
|||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
if (title.isNotBlank()) {
|
if (title.isNotBlank()) {
|
||||||
HeadView(title = title, onBack = { handleBackPress(context, webView) })
|
HeadView(title = title, onBack = { handleBackPress(context, webView) })
|
||||||
} else {
|
|
||||||
Spacer(modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.statusBarsPadding()
|
|
||||||
.padding(vertical = headPadding))
|
|
||||||
}
|
}
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
|
@ -42,7 +42,6 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.toArgb
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -76,6 +75,7 @@ import com.za.ext.callPhone
|
|||||||
import com.za.ext.copy
|
import com.za.ext.copy
|
||||||
import com.za.ext.finish
|
import com.za.ext.finish
|
||||||
import com.za.servicing.R
|
import com.za.servicing.R
|
||||||
|
import com.za.ui.servicing.in_servicing_setting.OrderTaskNotesDialog
|
||||||
|
|
||||||
class NewOrderActivity : BaseActivity() {
|
class NewOrderActivity : BaseActivity() {
|
||||||
|
|
||||||
@ -198,6 +198,28 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uiState.value.acceptOrderDialog == true) {
|
||||||
|
CommonDialog(title = "请确认是否接受该任务!",
|
||||||
|
confirmText = "确认接单",
|
||||||
|
cancelText = "再想想",
|
||||||
|
cancelEnable = false,
|
||||||
|
confirm = {
|
||||||
|
vm.updateState(uiState.value.copy(acceptOrderDialog = false))
|
||||||
|
vm.dispatch(NewOrderVm.Action.ShowTaskNotes)
|
||||||
|
},
|
||||||
|
cancel = {},
|
||||||
|
dismiss = {})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uiState.value.showTaskNotesDialog == true) {
|
||||||
|
OrderTaskNotesDialog(uiState.value.taskNotesBean,
|
||||||
|
uiState.value.jpushBean?.hasReplaceBatteryCapable == 2,
|
||||||
|
dismiss = {},
|
||||||
|
confirm = {
|
||||||
|
vm.dispatch(NewOrderVm.Action.AcceptOrder)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
BottomSheetScaffold(scaffoldState = scaffoldState,
|
BottomSheetScaffold(scaffoldState = scaffoldState,
|
||||||
topBar = { HeadViewNotBack(title = "新订单") },
|
topBar = { HeadViewNotBack(title = "新订单") },
|
||||||
sheetContent = {
|
sheetContent = {
|
||||||
@ -377,7 +399,7 @@ private fun AcceptOrderScreen(jpushBean : JpushBean?, vm : NewOrderVm = viewMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 接单按钮
|
// 接单按钮
|
||||||
Button(onClick = { vm.dispatch(NewOrderVm.Action.AcceptOrder) },
|
Button(onClick = { vm.dispatch(NewOrderVm.Action.ShowTaskNotes) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.height(44.dp),
|
.height(44.dp),
|
||||||
|
@ -15,8 +15,10 @@ import com.blankj.utilcode.util.ToastUtils
|
|||||||
import com.za.base.BaseVm
|
import com.za.base.BaseVm
|
||||||
import com.za.base.view.LoadingManager
|
import com.za.base.view.LoadingManager
|
||||||
import com.za.bean.JpushBean
|
import com.za.bean.JpushBean
|
||||||
|
import com.za.bean.TaskNotesBean
|
||||||
import com.za.bean.request.AcceptOrderRequest
|
import com.za.bean.request.AcceptOrderRequest
|
||||||
import com.za.bean.request.RefuseOrderRequest
|
import com.za.bean.request.RefuseOrderRequest
|
||||||
|
import com.za.bean.request.TaskNotesRequest
|
||||||
import com.za.common.GlobalData
|
import com.za.common.GlobalData
|
||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
import com.za.common.util.DeviceUtil
|
import com.za.common.util.DeviceUtil
|
||||||
@ -37,237 +39,272 @@ import java.util.Date
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class NewOrderVm : BaseVm<NewOrderVm.Action, NewOrderVm.UiState>() {
|
class NewOrderVm : BaseVm<NewOrderVm.Action, NewOrderVm.UiState>() {
|
||||||
private val _uiState = MutableStateFlow(UiState())
|
private val _uiState = MutableStateFlow(UiState())
|
||||||
val uiState get() = _uiState
|
val uiState get() = _uiState
|
||||||
|
|
||||||
private var timerJob: Job? = null
|
private var timerJob : Job? = null
|
||||||
|
|
||||||
override fun dispatch(action: Action) {
|
override fun dispatch(action : Action) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is Action.Init -> init(action.jpushBean)
|
is Action.Init -> init(action.jpushBean)
|
||||||
is Action.AcceptOrder -> acceptOrder()
|
is Action.AcceptOrder -> acceptOrder()
|
||||||
is Action.RefuseOrder -> refuseOrder()
|
is Action.RefuseOrder -> refuseOrder()
|
||||||
is Action.StartTimer -> startTimer()
|
is Action.StartTimer -> startTimer()
|
||||||
is Action.UpdateTimer -> updateTimer(action.remainingTime)
|
is Action.ShowTaskNotes -> showTaskNotes()
|
||||||
else -> {}
|
is Action.UpdateTimer -> updateTimer(action.remainingTime)
|
||||||
}
|
else -> {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun updateState(uiState: UiState) {
|
override fun updateState(uiState : UiState) {
|
||||||
_uiState.value = uiState
|
_uiState.value = uiState
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun init(jpushBean: JpushBean?) {
|
private fun init(jpushBean : JpushBean?) {
|
||||||
updateState(uiState.value.copy(jpushBean = jpushBean))
|
updateState(uiState.value.copy(jpushBean = jpushBean))
|
||||||
buildMarkers(jpushBean)
|
buildMarkers(jpushBean)
|
||||||
searchDrivingRoute(jpushBean)
|
searchDrivingRoute(jpushBean)
|
||||||
startTimer()
|
startTimer()
|
||||||
}
|
getTaskNote()
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildMarkers(jpushBean: JpushBean?) {
|
private fun getTaskNote() {
|
||||||
val markers = arrayListOf<MarkerOptions>()
|
val taskNotesRequest = TaskNotesRequest(taskId = uiState.value.jpushBean?.taskId)
|
||||||
if (jpushBean?.lat != null && jpushBean.lat != 0.0 && jpushBean.lng != null && jpushBean.lng != 0.0) {
|
RetrofitHelper.getDefaultService().getTaskNotes(taskNotesRequest)
|
||||||
val startMarkers = MarkerOptions()
|
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map))
|
.subscribe(object : BaseObserver<TaskNotesBean>() {
|
||||||
.position(LatLng(jpushBean.lat, jpushBean.lng))
|
override fun doSuccess(it : TaskNotesBean?) {
|
||||||
.title(jpushBean.address)
|
updateState(uiState.value.copy(taskNotesBean = it))
|
||||||
.snippet("救援地点")
|
}
|
||||||
.visible(true)
|
|
||||||
markers.add(startMarkers)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jpushBean?.distLat != null && jpushBean.distLat != 0.0 && jpushBean.distLng != null && jpushBean.distLng != 0.0) {
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
val startMarkers = MarkerOptions()
|
LogUtil.print("获取任务备注失败", "request=$taskNotesRequest msg=$msg")
|
||||||
.icon(ImageUtil.vectorToBitmap(ActivityUtils.getTopActivity(), R.drawable.sv_map_dist))
|
}
|
||||||
.position(LatLng(jpushBean.distLat, jpushBean.distLng))
|
})
|
||||||
.title(jpushBean.distAddress)
|
}
|
||||||
.snippet("目的地")
|
|
||||||
.visible(true)
|
|
||||||
markers.add(startMarkers)
|
|
||||||
}
|
|
||||||
updateState(uiState.value.copy(markers = markers))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun acceptOrder() {
|
private fun buildMarkers(jpushBean : JpushBean?) {
|
||||||
LoadingManager.showLoading()
|
val markers = arrayListOf<MarkerOptions>()
|
||||||
ZdLocationManager.getSingleLocation(success = {
|
if (jpushBean?.lat != null && jpushBean.lat != 0.0 && jpushBean.lng != null && jpushBean.lng != 0.0) {
|
||||||
val orderInfo = uiState.value.jpushBean
|
val startMarkers =
|
||||||
val acceptOrderRequest = AcceptOrderRequest()
|
MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.mipmap.sv_rescuing_map))
|
||||||
acceptOrderRequest.taskId = orderInfo?.taskId
|
.position(LatLng(jpushBean.lat, jpushBean.lng)).title(jpushBean.address)
|
||||||
acceptOrderRequest.vehicleId = GlobalData.driverInfoBean?.vehicleId
|
.snippet("救援地点").visible(true)
|
||||||
acceptOrderRequest.userId = GlobalData.driverInfoBean?.userId
|
markers.add(startMarkers)
|
||||||
acceptOrderRequest.taskCode = orderInfo?.taskCode
|
}
|
||||||
acceptOrderRequest.deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity())
|
|
||||||
acceptOrderRequest.lat = it.latitude
|
|
||||||
acceptOrderRequest.lng = it.longitude
|
|
||||||
RetrofitHelper.getDefaultService().acceptOrder(acceptOrderRequest)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : BaseObserver<String>() {
|
|
||||||
override fun doSuccess(it: String?) {
|
|
||||||
LoadingManager.hideLoading()
|
|
||||||
LogUtil.print("接单成功", "request=$acceptOrderRequest")
|
|
||||||
updateState(uiState.value.copy(showCallPhoneDialog = orderInfo?.isNeedCallCustomPhone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doFailure(code: Int, msg: String?) {
|
if (jpushBean?.distLat != null && jpushBean.distLat != 0.0 && jpushBean.distLng != null && jpushBean.distLng != 0.0) {
|
||||||
LoadingManager.hideLoading()
|
val startMarkers =
|
||||||
LogUtil.print("接单失败", "request=$acceptOrderRequest msg=$msg")
|
MarkerOptions().icon(ImageUtil.vectorToBitmap(ActivityUtils.getTopActivity(),
|
||||||
}
|
R.drawable.sv_map_dist)).position(LatLng(jpushBean.distLat, jpushBean.distLng))
|
||||||
})
|
.title(jpushBean.distAddress).snippet("目的地").visible(true)
|
||||||
}, failed = {
|
markers.add(startMarkers)
|
||||||
LoadingManager.hideLoading()
|
}
|
||||||
LogUtil.print("接单时获取定位失败", it)
|
updateState(uiState.value.copy(markers = markers))
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun refuseOrder() {
|
private fun showTaskNotes() {
|
||||||
LoadingManager.showLoading()
|
if (uiState.value.taskNotesBean != null && isNeedShowNotes()) {
|
||||||
RetrofitHelper.getDefaultService().refuseOrder(RefuseOrderRequest(taskId = uiState.value.jpushBean?.taskId,
|
updateState(uiState.value.copy(showTaskNotesDialog = true))
|
||||||
vehicleId = GlobalData.driverInfoBean?.vehicleId,
|
return
|
||||||
taskCode = uiState.value.jpushBean?.taskCode,
|
}
|
||||||
userId = GlobalData.driverInfoBean?.userId))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : BaseObserver<String>() {
|
|
||||||
override fun doSuccess(it: String?) {
|
|
||||||
LoadingManager.hideLoading()
|
|
||||||
updateState(uiState.value.copy(refuseSuccess = true))
|
|
||||||
LogUtil.print("refuseOrder", "订单拒绝成功")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doFailure(code: Int, msg: String?) {
|
acceptOrder()
|
||||||
LoadingManager.hideLoading()
|
}
|
||||||
ToastUtils.showShort(msg)
|
|
||||||
LogUtil.print("refuseOrder", "failed=$msg")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startTimer() {
|
private fun acceptOrder() {
|
||||||
timerJob?.cancel()
|
LoadingManager.showLoading()
|
||||||
timerJob = viewModelScope.launch {
|
ZdLocationManager.getSingleLocation(success = {
|
||||||
try {
|
val orderInfo = uiState.value.jpushBean
|
||||||
var timeLeft = 120
|
val acceptOrderRequest = AcceptOrderRequest()
|
||||||
while (timeLeft > 0 && isActive) {
|
acceptOrderRequest.taskId = orderInfo?.taskId
|
||||||
delay(1000)
|
acceptOrderRequest.vehicleId = GlobalData.driverInfoBean?.vehicleId
|
||||||
timeLeft--
|
acceptOrderRequest.userId = GlobalData.driverInfoBean?.userId
|
||||||
updateState(uiState.value.copy(remainingTime = timeLeft))
|
acceptOrderRequest.taskCode = orderInfo?.taskCode
|
||||||
}
|
acceptOrderRequest.deviceId = DeviceUtil.getAndroidId(ActivityUtils.getTopActivity())
|
||||||
if (timeLeft == 0 && isActive) {
|
acceptOrderRequest.lat = it.latitude
|
||||||
// 倒计时结束,显示订单超时
|
acceptOrderRequest.lng = it.longitude
|
||||||
updateState(uiState.value.copy(
|
RetrofitHelper.getDefaultService().acceptOrder(acceptOrderRequest)
|
||||||
isTimeout = true,
|
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
showTimeoutDialog = true
|
.subscribe(object : BaseObserver<String>() {
|
||||||
))
|
override fun doSuccess(it : String?) {
|
||||||
}
|
LoadingManager.hideLoading()
|
||||||
} catch (e: Exception) {
|
LogUtil.print("接单成功", "request=$acceptOrderRequest")
|
||||||
LogUtil.print("startTimer", "倒计时异常: ${e.message}")
|
updateState(uiState.value.copy(showCallPhoneDialog = orderInfo?.isNeedCallCustomPhone()))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateTimer(remainingTime: Int) {
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
updateState(uiState.value.copy(remainingTime = remainingTime))
|
LoadingManager.hideLoading()
|
||||||
}
|
LogUtil.print("接单失败", "request=$acceptOrderRequest msg=$msg")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, failed = {
|
||||||
|
LoadingManager.hideLoading()
|
||||||
|
LogUtil.print("接单时获取定位失败", it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private fun searchDrivingRoute(jpushBean: JpushBean?) {
|
private fun refuseOrder() {
|
||||||
if (GlobalData.currentLocation == null) {
|
LoadingManager.showLoading()
|
||||||
ToastUtils.showShort("获取当前位置失败")
|
RetrofitHelper.getDefaultService()
|
||||||
return
|
.refuseOrder(RefuseOrderRequest(taskId = uiState.value.jpushBean?.taskId,
|
||||||
}
|
vehicleId = GlobalData.driverInfoBean?.vehicleId,
|
||||||
|
taskCode = uiState.value.jpushBean?.taskCode,
|
||||||
|
userId = GlobalData.driverInfoBean?.userId)).subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread()).subscribe(object : BaseObserver<String>() {
|
||||||
|
override fun doSuccess(it : String?) {
|
||||||
|
LoadingManager.hideLoading()
|
||||||
|
updateState(uiState.value.copy(refuseSuccess = true))
|
||||||
|
LogUtil.print("refuseOrder", "订单拒绝成功")
|
||||||
|
}
|
||||||
|
|
||||||
updateState(uiState.value.copy(isLoading = true))
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
|
LoadingManager.hideLoading()
|
||||||
|
ToastUtils.showShort(msg)
|
||||||
|
LogUtil.print("refuseOrder", "failed=$msg")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
val startPoint = LatLonPoint(
|
private fun startTimer() {
|
||||||
GlobalData.currentLocation?.latitude ?: 0.0,
|
timerJob?.cancel()
|
||||||
GlobalData.currentLocation?.longitude ?: 0.0
|
timerJob = viewModelScope.launch {
|
||||||
)
|
try {
|
||||||
|
var timeLeft = 120
|
||||||
|
while (timeLeft > 0 && isActive) {
|
||||||
|
delay(1000)
|
||||||
|
timeLeft --
|
||||||
|
updateState(uiState.value.copy(remainingTime = timeLeft))
|
||||||
|
}
|
||||||
|
if (timeLeft == 0 && isActive) { // 倒计时结束,显示订单超时
|
||||||
|
updateState(uiState.value.copy(isTimeout = true, showTimeoutDialog = true))
|
||||||
|
}
|
||||||
|
} catch (e : Exception) {
|
||||||
|
LogUtil.print("startTimer", "倒计时异常: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val endPoint = when {
|
private fun isNeedShowNotes() : Boolean {
|
||||||
jpushBean?.distLat != null && jpushBean.distLat != 0.0 &&
|
if (! uiState.value.taskNotesBean?.taskNotes.isNullOrBlank()) {
|
||||||
jpushBean.distLng != null && jpushBean.distLng != 0.0 -> {
|
return true
|
||||||
LatLonPoint(jpushBean.distLat, jpushBean.distLng)
|
}
|
||||||
}
|
|
||||||
jpushBean?.lat != null && jpushBean.lat != 0.0 &&
|
|
||||||
jpushBean.lng != null && jpushBean.lng != 0.0 -> {
|
|
||||||
LatLonPoint(jpushBean.lat, jpushBean.lng)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endPoint == null) return
|
if (! uiState.value.taskNotesBean?.customerNotes.isNullOrBlank()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
val fromAndTo = RouteSearch.FromAndTo(startPoint, endPoint)
|
if (! uiState.value.taskNotesBean?.feeStandard.isNullOrBlank()) {
|
||||||
val query = RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, null, null, "")
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
RouteSearch(GlobalData.application).apply {
|
if (! uiState.value.taskNotesBean?.otherNotes.isNullOrBlank()) {
|
||||||
setRouteSearchListener(object : RouteSearch.OnRouteSearchListener {
|
return true
|
||||||
override fun onDriveRouteSearched(result: DriveRouteResult?, errorCode: Int) {
|
}
|
||||||
updateState(uiState.value.copy(isLoading = false))
|
|
||||||
|
|
||||||
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) }
|
|
||||||
}
|
|
||||||
|
|
||||||
val duration = path.duration
|
|
||||||
val arrivalTime = System.currentTimeMillis() + duration * 1000
|
|
||||||
val dateFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
|
|
||||||
val estimatedTime = dateFormat.format(Date(arrivalTime))
|
|
||||||
|
|
||||||
updateState(uiState.value.copy(
|
|
||||||
routePoints = points,
|
|
||||||
remainingDistance = path.distance.toDouble(),
|
|
||||||
estimatedArrivalTime = estimatedTime
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
ToastUtils.showShort("路线规划失败,请重试")
|
|
||||||
LogUtil.print("searchDrivingRoute", "路径规划失败: errorCode=$errorCode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBusRouteSearched(p0: BusRouteResult?, p1: Int) {}
|
return false
|
||||||
override fun onWalkRouteSearched(p0: WalkRouteResult?, p1: Int) {}
|
}
|
||||||
override fun onRideRouteSearched(p0: RideRouteResult?, p1: Int) {}
|
|
||||||
})
|
|
||||||
calculateDriveRouteAsyn(query)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCleared() {
|
private fun updateTimer(remainingTime : Int) {
|
||||||
super.onCleared()
|
updateState(uiState.value.copy(remainingTime = remainingTime))
|
||||||
try {
|
}
|
||||||
timerJob?.cancel()
|
|
||||||
timerJob = null
|
|
||||||
} catch (e: Exception) {
|
|
||||||
LogUtil.print("onCleared", "取消倒计时异常: ${e.message}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Action {
|
private fun searchDrivingRoute(jpushBean : JpushBean?) {
|
||||||
data class Init(val jpushBean: JpushBean?) : Action()
|
if (GlobalData.currentLocation == null) {
|
||||||
data object AcceptOrder : Action()
|
ToastUtils.showShort("获取当前位置失败")
|
||||||
data class UpdateState(val uiState: UiState) : Action()
|
return
|
||||||
data object RefuseOrder : Action()
|
}
|
||||||
data object StartTimer : Action()
|
|
||||||
data class UpdateTimer(val remainingTime: Int) : Action()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class UiState(
|
updateState(uiState.value.copy(isLoading = true))
|
||||||
val jpushBean: JpushBean? = null,
|
|
||||||
val showCallPhoneDialog: Boolean? = false,
|
val startPoint = LatLonPoint(GlobalData.currentLocation?.latitude ?: 0.0,
|
||||||
val markers: ArrayList<MarkerOptions>? = null,
|
GlobalData.currentLocation?.longitude ?: 0.0)
|
||||||
val refuseSuccess: Boolean? = false,
|
|
||||||
val remainingTime: Int = 50,
|
val endPoint = when {
|
||||||
val routePoints: List<LatLng>? = null,
|
jpushBean?.distLat != null && jpushBean.distLat != 0.0 && jpushBean.distLng != null && jpushBean.distLng != 0.0 -> {
|
||||||
val remainingDistance: Double = 0.0,
|
LatLonPoint(jpushBean.distLat, jpushBean.distLng)
|
||||||
val estimatedArrivalTime: String = "",
|
}
|
||||||
val isLoading: Boolean = false,
|
|
||||||
val isTimeout: Boolean = false,
|
jpushBean?.lat != null && jpushBean.lat != 0.0 && jpushBean.lng != null && jpushBean.lng != 0.0 -> {
|
||||||
val showTimeoutDialog: Boolean = false
|
LatLonPoint(jpushBean.lat, jpushBean.lng)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endPoint == null) return
|
||||||
|
|
||||||
|
val fromAndTo = RouteSearch.FromAndTo(startPoint, endPoint)
|
||||||
|
val query =
|
||||||
|
RouteSearch.DriveRouteQuery(fromAndTo, RouteSearch.DrivingDefault, null, null, "")
|
||||||
|
|
||||||
|
RouteSearch(GlobalData.application).apply {
|
||||||
|
setRouteSearchListener(object : RouteSearch.OnRouteSearchListener {
|
||||||
|
override fun onDriveRouteSearched(result : DriveRouteResult?, errorCode : Int) {
|
||||||
|
updateState(uiState.value.copy(isLoading = false))
|
||||||
|
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val duration = path.duration
|
||||||
|
val arrivalTime = System.currentTimeMillis() + duration * 1000
|
||||||
|
val dateFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||||
|
val estimatedTime = dateFormat.format(Date(arrivalTime))
|
||||||
|
|
||||||
|
updateState(uiState.value.copy(routePoints = points,
|
||||||
|
remainingDistance = path.distance.toDouble(),
|
||||||
|
estimatedArrivalTime = estimatedTime))
|
||||||
|
} else {
|
||||||
|
ToastUtils.showShort("路线规划失败,请重试")
|
||||||
|
LogUtil.print("searchDrivingRoute", "路径规划失败: errorCode=$errorCode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBusRouteSearched(p0 : BusRouteResult?, p1 : Int) {}
|
||||||
|
override fun onWalkRouteSearched(p0 : WalkRouteResult?, p1 : Int) {}
|
||||||
|
override fun onRideRouteSearched(p0 : RideRouteResult?, p1 : Int) {}
|
||||||
|
})
|
||||||
|
calculateDriveRouteAsyn(query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
try {
|
||||||
|
timerJob?.cancel()
|
||||||
|
timerJob = null
|
||||||
|
} catch (e : Exception) {
|
||||||
|
LogUtil.print("onCleared", "取消倒计时异常: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Action {
|
||||||
|
data class Init(val jpushBean : JpushBean?) : Action()
|
||||||
|
data object AcceptOrder : Action()
|
||||||
|
data class UpdateState(val uiState : UiState) : Action()
|
||||||
|
data object RefuseOrder : Action()
|
||||||
|
data object ShowTaskNotes : Action()
|
||||||
|
data object StartTimer : Action()
|
||||||
|
data class UpdateTimer(val remainingTime : Int) : Action()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class UiState(val jpushBean : JpushBean? = null,
|
||||||
|
val showCallPhoneDialog : Boolean? = false,
|
||||||
|
val markers : ArrayList<MarkerOptions>? = null,
|
||||||
|
val refuseSuccess : Boolean? = false,
|
||||||
|
val taskNotesBean : TaskNotesBean? = null,
|
||||||
|
val showTaskNotesDialog : Boolean? = false,
|
||||||
|
val acceptOrderDialog : Boolean? = null,
|
||||||
|
val remainingTime : Int = 50,
|
||||||
|
val routePoints : List<LatLng>? = null,
|
||||||
|
val remainingDistance : Double = 0.0,
|
||||||
|
val estimatedArrivalTime : String = "",
|
||||||
|
val isLoading : Boolean = false,
|
||||||
|
val isTimeout : Boolean = false,
|
||||||
|
val showTimeoutDialog : Boolean = false)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -39,14 +39,12 @@ import com.za.base.theme.bgColor
|
|||||||
import com.za.base.theme.black5
|
import com.za.base.theme.black5
|
||||||
import com.za.base.theme.headBgColor
|
import com.za.base.theme.headBgColor
|
||||||
import com.za.base.view.ChoiceMapDialog
|
import com.za.base.view.ChoiceMapDialog
|
||||||
import com.za.base.view.CommonButton
|
|
||||||
import com.za.base.view.CommonDialog
|
import com.za.base.view.CommonDialog
|
||||||
import com.za.bean.db.order.OrderInfo
|
import com.za.bean.db.order.OrderInfo
|
||||||
import com.za.ext.callPhone
|
import com.za.ext.callPhone
|
||||||
import com.za.ext.convertToFlowName
|
import com.za.ext.convertToFlowName
|
||||||
import com.za.ext.copy
|
import com.za.ext.copy
|
||||||
import com.za.servicing.R
|
import com.za.servicing.R
|
||||||
import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OrderDetailItemScreen(orderInfo : OrderInfo?) {
|
fun OrderDetailItemScreen(orderInfo : OrderInfo?) {
|
||||||
@ -57,6 +55,7 @@ fun OrderDetailItemScreen(orderInfo : OrderInfo?) {
|
|||||||
.padding(5.dp)) {
|
.padding(5.dp)) {
|
||||||
OrderDetailBaseInformationView(orderInfo = orderInfo)
|
OrderDetailBaseInformationView(orderInfo = orderInfo)
|
||||||
OrderDetailServiceInformationView(orderInfo = orderInfo)
|
OrderDetailServiceInformationView(orderInfo = orderInfo)
|
||||||
|
OrderDetailTime(orderInfo = orderInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,18 +186,40 @@ private fun OrderDetailBaseInformationView(orderInfo : OrderInfo?) {
|
|||||||
modifier = Modifier.size(15.dp))
|
modifier = Modifier.size(15.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
if (! orderInfo?.carModel.isNullOrBlank()) {
|
||||||
Text(text = "车型",
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
color = titleColor,
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
fontSize = titleSize,
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
fontWeight = FontWeight.Medium,
|
Text(text = "车型",
|
||||||
modifier = Modifier.width(75.dp))
|
color = titleColor,
|
||||||
Spacer(modifier = Modifier.width(5.dp))
|
fontSize = titleSize,
|
||||||
Text(text = "${orderInfo?.carModel}",
|
fontWeight = FontWeight.Medium,
|
||||||
color = contentColor,
|
modifier = Modifier.width(75.dp))
|
||||||
fontSize = titleSize,
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
fontWeight = FontWeight.Medium)
|
Text(text = "${orderInfo?.carModel}",
|
||||||
|
color = contentColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//拖车责任险
|
||||||
|
if (! orderInfo?.policyNo.isNullOrBlank()) {
|
||||||
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(text = "拖车责任险",
|
||||||
|
color = titleColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.width(75.dp))
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
Text(text = "${orderInfo?.policyNo}",
|
||||||
|
color = contentColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +232,6 @@ private fun OrderDetailServiceInformationView(orderInfo : OrderInfo?) {
|
|||||||
val titleSize = 12.sp
|
val titleSize = 12.sp
|
||||||
val titleColor = Color(0xFF7A7A7A)
|
val titleColor = Color(0xFF7A7A7A)
|
||||||
val contentColor = Color.Black
|
val contentColor = Color.Black
|
||||||
val context = LocalContext.current
|
|
||||||
|
|
||||||
// 1 事发地 2 目的地
|
// 1 事发地 2 目的地
|
||||||
var showChoiceMapDialog by remember { mutableStateOf<Int?>(null) }
|
var showChoiceMapDialog by remember { mutableStateOf<Int?>(null) }
|
||||||
@ -355,11 +375,77 @@ private fun OrderDetailServiceInformationView(orderInfo : OrderInfo?) {
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
|
||||||
CommonButton(text = "客户放弃") {
|
}
|
||||||
OrderGiveUpActivity.goOrderGiveUpActivity(context,
|
|
||||||
orderInfo = orderInfo,
|
|
||||||
userOrderId = orderInfo?.userOrderId,
|
|
||||||
giveUpType = 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OrderDetailTime(orderInfo : OrderInfo?) {
|
||||||
|
val titleSize = 12.sp
|
||||||
|
val titleColor = Color(0xFF7A7A7A)
|
||||||
|
val contentColor = Color.Black
|
||||||
|
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(color = Color.White, shape = RoundedCornerShape(4.dp))
|
||||||
|
.padding(10.dp),
|
||||||
|
verticalArrangement = Arrangement.Top) {
|
||||||
|
Box(contentAlignment = Alignment.CenterStart) {
|
||||||
|
Text(text = "订单时间",
|
||||||
|
color = Color.Black,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
HorizontalDivider(color = black5, modifier = Modifier.padding(vertical = 10.dp))
|
||||||
|
|
||||||
|
if (! orderInfo?.acceptTime.isNullOrBlank()) {
|
||||||
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(text = "接单时间",
|
||||||
|
color = titleColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.width(75.dp))
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
Text(text = "${orderInfo?.acceptTime}",
|
||||||
|
color = contentColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! orderInfo?.arriveTime.isNullOrBlank()) {
|
||||||
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(text = "到达事发地时间",
|
||||||
|
color = titleColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.width(75.dp))
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
Text(text = "${orderInfo?.arriveTime}",
|
||||||
|
color = contentColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! orderInfo?.arriveDestTime.isNullOrBlank()) {
|
||||||
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(text = "到达目的地时间",
|
||||||
|
color = titleColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.width(75.dp))
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
|
Text(text = "${orderInfo?.arriveDestTime}",
|
||||||
|
color = contentColor,
|
||||||
|
fontSize = titleSize,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
}
|
||||||
}
|
}
|
@ -28,9 +28,11 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.za.base.theme.headBgColor
|
import com.za.base.theme.headBgColor
|
||||||
import com.za.base.theme.white80
|
import com.za.base.theme.white80
|
||||||
|
import com.za.base.view.CommonButton
|
||||||
import com.za.base.view.HeadView
|
import com.za.base.view.HeadView
|
||||||
import com.za.bean.db.order.OrderInfo
|
import com.za.bean.db.order.OrderInfo
|
||||||
import com.za.ext.finish
|
import com.za.ext.finish
|
||||||
|
import com.za.ui.servicing.order_give_up.OrderGiveUpActivity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -41,6 +43,13 @@ fun OrderDetailScreen(orderInfo : OrderInfo?) {
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
HeadView(title = "订单信息", onBack = { context.finish() })
|
HeadView(title = "订单信息", onBack = { context.finish() })
|
||||||
|
}, bottomBar = {
|
||||||
|
CommonButton(text = "客户放弃") {
|
||||||
|
OrderGiveUpActivity.goOrderGiveUpActivity(context,
|
||||||
|
orderInfo = orderInfo,
|
||||||
|
userOrderId = orderInfo?.userOrderId,
|
||||||
|
giveUpType = 0)
|
||||||
|
}
|
||||||
}) {
|
}) {
|
||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.za.ui.servicing.in_servicing_setting
|
package com.za.ui.servicing.in_servicing_setting
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@ -9,9 +12,14 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Warning
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -21,9 +29,13 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.za.base.theme.black5
|
import com.za.base.theme.black5
|
||||||
import com.za.base.theme.black65
|
import com.za.base.theme.black65
|
||||||
|
import com.za.base.view.CommonButton
|
||||||
|
import com.za.bean.TaskNotesBean
|
||||||
import com.za.bean.db.order.OrderInfo
|
import com.za.bean.db.order.OrderInfo
|
||||||
import com.za.servicing.R
|
import com.za.servicing.R
|
||||||
|
|
||||||
@ -49,10 +61,10 @@ fun OrderRequirementsScreen(orderInfo : OrderInfo?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun OrderRequirementsItemView(title : String?, content : String?) {
|
fun OrderRequirementsItemView(title : String?, content : String?) {
|
||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 12.dp)) {
|
.padding(vertical = 5.dp)) {
|
||||||
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
AsyncImage(model = R.drawable.sv_warn_red,
|
AsyncImage(model = R.drawable.sv_warn_red,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
@ -76,10 +88,10 @@ private fun OrderRequirementsItemView(title : String?, content : String?) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun CarModeView(orderInfo : OrderInfo?) {
|
fun CarModeView(orderInfo : OrderInfo?) {
|
||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 12.dp)) {
|
.padding(vertical = 5.dp)) {
|
||||||
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
AsyncImage(model = R.drawable.sv_warn_red,
|
AsyncImage(model = R.drawable.sv_warn_red,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
@ -100,4 +112,90 @@ private fun CarModeView(orderInfo : OrderInfo?) {
|
|||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
HorizontalDivider(color = black5, modifier = Modifier.fillMaxWidth())
|
HorizontalDivider(color = black5, modifier = Modifier.fillMaxWidth())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OrderTaskNotesDialog(taskNotesBean : TaskNotesBean?,
|
||||||
|
isShowChangeBattery : Boolean? = false,
|
||||||
|
dismiss : () -> Unit,
|
||||||
|
confirm : () -> Unit) {
|
||||||
|
|
||||||
|
Dialog(onDismissRequest = { dismiss() },
|
||||||
|
properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)) {
|
||||||
|
Box(contentAlignment = Alignment.BottomCenter,
|
||||||
|
modifier = Modifier.background(color = Color.White,
|
||||||
|
shape = RoundedCornerShape(13.dp))) {
|
||||||
|
Column(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
.verticalScroll(state = rememberScrollState())
|
||||||
|
.padding(horizontal = 10.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Top) {
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
|
||||||
|
Row(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 10.dp)) {
|
||||||
|
Text("合同名称",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Medium)
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
|
||||||
|
Text("平安保险",
|
||||||
|
color = Color.Black,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(color = black5, modifier = Modifier.padding(vertical = 10.dp))
|
||||||
|
|
||||||
|
if (! taskNotesBean?.otherNotes.isNullOrBlank()) {
|
||||||
|
OrderRequirementsItemView(title = "特殊提醒",
|
||||||
|
content = taskNotesBean?.otherNotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! taskNotesBean?.feeStandard.isNullOrBlank()) {
|
||||||
|
OrderRequirementsItemView(title = "收费标准",
|
||||||
|
content = taskNotesBean?.feeStandard)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! taskNotesBean?.modelVinNo.isNullOrBlank()) {
|
||||||
|
OrderRequirementsItemView(title = "车型", content = taskNotesBean?.modelVinNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! taskNotesBean?.taskNotes.isNullOrBlank()) {
|
||||||
|
OrderRequirementsItemView(title = "救援要求",
|
||||||
|
content = taskNotesBean?.taskNotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! taskNotesBean?.customerNotes.isNullOrBlank()) {
|
||||||
|
OrderRequirementsItemView(title = "客户要求",
|
||||||
|
content = taskNotesBean?.customerNotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isShowChangeBattery == true) {
|
||||||
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
|
Row(modifier = Modifier.padding(vertical = 10.dp, horizontal = 10.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Icon(imageVector = Icons.Default.Warning,
|
||||||
|
tint = Color.Red,
|
||||||
|
contentDescription = "",
|
||||||
|
modifier = Modifier.size(24.dp))
|
||||||
|
Text("此订单不允许销售电瓶",
|
||||||
|
color = Color.Red,
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
modifier = Modifier.padding(start = 8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(65.dp))
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonButton(text = "我已阅读") { confirm() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ import com.za.common.GlobalData
|
|||||||
import com.za.common.log.LogUtil
|
import com.za.common.log.LogUtil
|
||||||
import com.za.ext.goNextPage
|
import com.za.ext.goNextPage
|
||||||
import com.za.servicing.R
|
import com.za.servicing.R
|
||||||
import com.za.ui.camera.ZdCameraXActivity
|
import com.za.ui.camera.ServicePeopleRealActivity
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ServicePeopleConfirmScreen(vm : InServicePeopleConfirmVm = viewModel(),
|
fun ServicePeopleConfirmScreen(vm : InServicePeopleConfirmVm = viewModel(),
|
||||||
@ -86,8 +86,7 @@ fun ServicePeopleConfirmScreen(vm : InServicePeopleConfirmVm = viewModel(),
|
|||||||
confirmText = "重新认证",
|
confirmText = "重新认证",
|
||||||
confirm = {
|
confirm = {
|
||||||
vm.updateState(uiState.value.copy(showCompareFailedDialog = null))
|
vm.updateState(uiState.value.copy(showCompareFailedDialog = null))
|
||||||
val intent = Intent(context, ZdCameraXActivity::class.java)
|
val intent = Intent(context, ServicePeopleRealActivity::class.java)
|
||||||
intent.putExtra("isBack", false)
|
|
||||||
getResult.launch(intent)
|
getResult.launch(intent)
|
||||||
},
|
},
|
||||||
cancelText = "关闭",
|
cancelText = "关闭",
|
||||||
@ -166,8 +165,7 @@ fun ServicePeopleConfirmScreen(vm : InServicePeopleConfirmVm = viewModel(),
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(40.dp))
|
Spacer(modifier = Modifier.height(40.dp))
|
||||||
CommonButton(text = "开始核验", onClick = {
|
CommonButton(text = "开始核验", onClick = {
|
||||||
val intent = Intent(context, ZdCameraXActivity::class.java)
|
val intent = Intent(context, ServicePeopleRealActivity::class.java)
|
||||||
intent.putExtra("isBack", false)
|
|
||||||
getResult.launch(intent)
|
getResult.launch(intent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,8 @@ class ConfirmH5SuccessVm : IServicingVm<ConfirmH5SuccessVm.Action, ConfirmH5Succ
|
|||||||
is Action.UpdateState -> updateState(action.uiState)
|
is Action.UpdateState -> updateState(action.uiState)
|
||||||
is Action.TaskFinish -> taskFinish()
|
is Action.TaskFinish -> taskFinish()
|
||||||
is Action.ClearOfflineTask -> clearCurrentOrderOfflineTask()
|
is Action.ClearOfflineTask -> clearCurrentOrderOfflineTask()
|
||||||
is Action.UpdateCurrentEleWorkOrder->updateCurrentEleWorkOrder(action.type, action.path)
|
is Action.UpdateCurrentEleWorkOrder -> updateCurrentEleWorkOrder(action.type,
|
||||||
|
action.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,13 +215,14 @@ class ConfirmH5SuccessVm : IServicingVm<ConfirmH5SuccessVm.Action, ConfirmH5Succ
|
|||||||
updateState(uiState.value.copy(goNextPage = true))
|
updateState(uiState.value.copy(goNextPage = true))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateState(uiState.value.copy(loadingState = LoadingState.LoadingFailed))
|
updateState(uiState.value.copy(loadingState = LoadingState.LoadingFailed(msg)))
|
||||||
LogUtil.print("任务失败", "code==$code msg==$msg")
|
LogUtil.print("任务失败", "code==$code msg==$msg")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, failed = {
|
}, failed = {
|
||||||
LoadingManager.hideLoading()
|
LoadingManager.hideLoading()
|
||||||
updateState(uiState.value.copy(loadingState = LoadingState.LoadingFailed))
|
ToastUtils.showLong(it)
|
||||||
|
updateState(uiState.value.copy(loadingState = LoadingState.LoadingFailed(it)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,65 +12,77 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import com.za.base.BaseActivity
|
import com.za.base.BaseActivity
|
||||||
import com.za.base.view.CommonDialog
|
import com.za.base.view.CommonDialog
|
||||||
import com.za.base.view.LoadingManager
|
import com.za.base.view.LoadingManager
|
||||||
|
import com.za.room.RoomHelper
|
||||||
import com.za.ui.servicing.order_confirm.input_money.InputMoneyActivity
|
import com.za.ui.servicing.order_confirm.input_money.InputMoneyActivity
|
||||||
import com.za.ui.servicing.order_confirm.real_order_confirm.RealOrderConfirmActivity
|
import com.za.ui.servicing.order_confirm.real_order_confirm.RealOrderConfirmActivity
|
||||||
import com.za.ui.servicing.order_confirm.receive_money.ReceiveMoneyActivity
|
import com.za.ui.servicing.order_confirm.receive_money.ReceiveMoneyActivity
|
||||||
|
|
||||||
class OrderConfirmActivity : BaseActivity() {
|
class OrderConfirmActivity : BaseActivity() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ContentView() {
|
override fun ContentView() {
|
||||||
OrderConfirmInitScreen()
|
OrderConfirmInitScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OrderConfirmInitScreen(vm: OrderConfirmInitVm = viewModel()) {
|
fun OrderConfirmInitScreen(vm : OrderConfirmInitVm = viewModel()) {
|
||||||
val uiState = vm.uiState.collectAsStateWithLifecycle()
|
val uiState = vm.uiState.collectAsStateWithLifecycle()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
LaunchedEffect(key1 = Unit) {
|
LaunchedEffect(key1 = Unit) {
|
||||||
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uiState.value.showNoNeedPayDialog == true) {
|
if (uiState.value.showNoNeedPayDialog == true) {
|
||||||
CommonDialog(title = "是否需要收款?", confirmText = "去收款", cancelText = "无需收款",
|
CommonDialog(title = "是否需要收款?",
|
||||||
confirm = {
|
confirmText = "去收款",
|
||||||
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false))
|
cancelText = "无需收款",
|
||||||
InputMoneyActivity.goInputMoney(context, userOrderId = uiState.value.orderInfo?.userOrderId
|
confirm = {
|
||||||
?: 0, taskId = uiState.value.orderInfo?.taskId ?: 0)
|
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false))
|
||||||
},
|
InputMoneyActivity.goInputMoney(context,
|
||||||
cancel = {
|
userOrderId = uiState.value.orderInfo?.userOrderId ?: 0,
|
||||||
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false, orderConfirmState = OrderConfirmInitVm.OrderConfirmState.OrderConfirm))
|
taskId = uiState.value.orderInfo?.taskId ?: 0)
|
||||||
},
|
},
|
||||||
dismiss = {
|
cancel = {
|
||||||
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false, orderConfirmState = OrderConfirmInitVm.OrderConfirmState.OrderConfirm))
|
uiState.value.eleWorkOrderBean?.copy(driverChoiceNoNeedReceiveMoney = true)?.let {
|
||||||
})
|
RoomHelper.db?.eleWorkOrderDao()?.update(it)
|
||||||
}
|
}
|
||||||
|
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false,
|
||||||
|
orderConfirmState = OrderConfirmInitVm.OrderConfirmState.Init))
|
||||||
|
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
||||||
|
},
|
||||||
|
dismiss = {
|
||||||
|
vm.updateState(uiState.value.copy(showNoNeedPayDialog = false,
|
||||||
|
orderConfirmState = OrderConfirmInitVm.OrderConfirmState.Init))
|
||||||
|
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
when (uiState.value.orderConfirmState) {
|
when (uiState.value.orderConfirmState) {
|
||||||
is OrderConfirmInitVm.OrderConfirmState.ChangeBattery -> ChangeBatteryScreen()
|
is OrderConfirmInitVm.OrderConfirmState.ChangeBattery -> ChangeBatteryScreen()
|
||||||
is OrderConfirmInitVm.OrderConfirmState.ConfirmEle -> ConfirmEleScreen()
|
is OrderConfirmInitVm.OrderConfirmState.ConfirmEle -> ConfirmEleScreen()
|
||||||
is OrderConfirmInitVm.OrderConfirmState.ConfirmH5Success -> ConfirmH5SuccessScreen()
|
is OrderConfirmInitVm.OrderConfirmState.ConfirmH5Success -> ConfirmH5SuccessScreen()
|
||||||
is OrderConfirmInitVm.OrderConfirmState.Init -> {
|
is OrderConfirmInitVm.OrderConfirmState.Init -> {
|
||||||
Box {
|
Box {
|
||||||
LoadingManager.showLoading()
|
LoadingManager.showLoading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is OrderConfirmInitVm.OrderConfirmState.Failed -> {
|
is OrderConfirmInitVm.OrderConfirmState.Failed -> {
|
||||||
Box(modifier = Modifier.clickable {
|
Box(modifier = Modifier.clickable {
|
||||||
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
vm.dispatch(OrderConfirmInitVm.Action.Init)
|
||||||
}) {
|
}) {
|
||||||
Text("点击重试")
|
Text("点击重试")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is OrderConfirmInitVm.OrderConfirmState.PaymentInfo -> {
|
is OrderConfirmInitVm.OrderConfirmState.PaymentInfo -> {
|
||||||
ReceiveMoneyActivity.goReceiveMoney(context, userOrderId = uiState.value.orderInfo?.userOrderId
|
ReceiveMoneyActivity.goReceiveMoney(context,
|
||||||
?: 0, taskId = uiState.value.orderInfo?.taskId ?: 0)
|
userOrderId = uiState.value.orderInfo?.userOrderId ?: 0,
|
||||||
}
|
taskId = uiState.value.orderInfo?.taskId ?: 0)
|
||||||
|
}
|
||||||
|
|
||||||
else -> RealOrderConfirmActivity.goRealOrderConfirm(context)
|
else -> RealOrderConfirmActivity.goRealOrderConfirm(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -17,110 +17,102 @@ import io.reactivex.rxjava3.schedulers.Schedulers
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
class OrderConfirmInitVm : IServicingVm<OrderConfirmInitVm.Action, OrderConfirmInitVm.UiState>() {
|
class OrderConfirmInitVm : IServicingVm<OrderConfirmInitVm.Action, OrderConfirmInitVm.UiState>() {
|
||||||
private val _uiState = MutableStateFlow(UiState())
|
private val _uiState = MutableStateFlow(UiState())
|
||||||
val uiState get() = _uiState
|
val uiState get() = _uiState
|
||||||
override fun updateState(uiState: UiState) {
|
override fun updateState(uiState : UiState) {
|
||||||
_uiState.value = uiState
|
_uiState.value = uiState
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatch(action: Action) {
|
override fun dispatch(action : Action) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is Action.Init -> init()
|
is Action.Init -> init()
|
||||||
is Action.UpdateState -> updateState(action.uiState)
|
is Action.UpdateState -> updateState(action.uiState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun init() {
|
private fun init() {
|
||||||
updateState(uiState.value.copy(orderInfo = getCurrentOrder()))
|
updateState(uiState.value.copy(orderInfo = getCurrentOrder()))
|
||||||
queryPaymentInfo(uiState.value.orderInfo)
|
queryPaymentInfo(uiState.value.orderInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queryPaymentInfo(orderInfo: OrderInfo?) {
|
private fun queryPaymentInfo(orderInfo : OrderInfo?) {
|
||||||
LoadingManager.showLoading()
|
LoadingManager.showLoading()
|
||||||
val paymentInfoRequest = PaymentInfoRequest(orderInfo?.userOrderId, orderInfo?.taskId)
|
val paymentInfoRequest = PaymentInfoRequest(orderInfo?.userOrderId, orderInfo?.taskId)
|
||||||
val eleWorkOrderBean = RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(taskId = orderInfo?.taskId
|
val eleWorkOrderBean =
|
||||||
?: 0)
|
RoomHelper.db?.eleWorkOrderDao()?.getEleWorkOrder(taskId = orderInfo?.taskId ?: 0)
|
||||||
RetrofitHelper.getDefaultService().paymentInfoQuery(paymentInfoRequest)
|
RetrofitHelper.getDefaultService().paymentInfoQuery(paymentInfoRequest)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(object : BaseObserver<PaymentInfoBean>() {
|
||||||
.subscribe(object : BaseObserver<PaymentInfoBean>() {
|
override fun doSuccess(it : PaymentInfoBean?) {
|
||||||
override fun doSuccess(it: PaymentInfoBean?) {
|
LoadingManager.hideLoading()
|
||||||
LoadingManager.hideLoading()
|
updateState(uiState.value.copy(paymentInfoBean = it,
|
||||||
updateState(uiState.value.copy(paymentInfoBean = it, orderInfo = orderInfo, eleWorkOrderBean = eleWorkOrderBean))
|
orderInfo = orderInfo,
|
||||||
if (it?.isPayment == true && it.tradeState != 2) {
|
eleWorkOrderBean = eleWorkOrderBean))
|
||||||
if (it.askPayment == true) {
|
if (eleWorkOrderBean != null && eleWorkOrderBean.driverChoiceNoNeedReceiveMoney == true) {
|
||||||
updateState(uiState.value.copy(showNoNeedPayDialog = true))
|
handlerOtherState(orderInfo, eleWorkOrderBean)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.PaymentInfo))
|
if (it?.isPayment == true && it.tradeState != 2) {
|
||||||
return
|
if (it.askPayment == true) {
|
||||||
}
|
updateState(uiState.value.copy(showNoNeedPayDialog = true))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.PaymentInfo))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (orderInfo?.electronOrderState == 0 || orderInfo?.electronOrderState == 1
|
handlerOtherState(orderInfo, eleWorkOrderBean)
|
||||||
|| orderInfo?.electronOrderState == 2
|
}
|
||||||
) {
|
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmEle))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eleWorkOrderBean?.changeBattery == true) {
|
override fun doFailure(code : Int, msg : String?) {
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ChangeBattery))
|
LoadingManager.hideLoading()
|
||||||
return
|
LogUtil.print("eleworkOrder", eleWorkOrderBean.toJson() ?: "")
|
||||||
}
|
updateState(uiState.value.copy(orderInfo = orderInfo, eleWorkOrderBean = eleWorkOrderBean))
|
||||||
if (eleWorkOrderBean?.hasCreatedEleWorkOrderPhoto == null || eleWorkOrderBean.hasCreatedEleWorkOrderPhoto != true) {
|
handlerOtherState(orderInfo, eleWorkOrderBean)
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmH5Success))
|
LogUtil.print("queryPaymentInfo", "failed=$msg request=${paymentInfoRequest.toJson()}")
|
||||||
return
|
}
|
||||||
}
|
})
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.OrderConfirm))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun doFailure(code: Int, msg: String?) {
|
private fun handlerOtherState(orderInfo : OrderInfo?, eleWorkOrderBean : EleWorkOrderBean?) {
|
||||||
LoadingManager.hideLoading()
|
if (orderInfo?.electronOrderState == 0 || orderInfo?.electronOrderState == 1 || orderInfo?.electronOrderState == 2) {
|
||||||
LogUtil.print("eleworkOrder", eleWorkOrderBean.toJson() ?: "")
|
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmEle))
|
||||||
updateState(uiState.value.copy(orderInfo = orderInfo, eleWorkOrderBean = eleWorkOrderBean))
|
return
|
||||||
if (orderInfo?.electronOrderState == 0 || orderInfo?.electronOrderState == 1 || orderInfo?.electronOrderState == 2) {
|
}
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmEle))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eleWorkOrderBean?.changeBattery == true) {
|
if (eleWorkOrderBean?.changeBattery == true) {
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ChangeBattery))
|
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ChangeBattery))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (eleWorkOrderBean?.hasCreatedEleWorkOrderPhoto == null || eleWorkOrderBean.hasCreatedEleWorkOrderPhoto != true) {
|
||||||
|
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmH5Success))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.OrderConfirm))
|
||||||
|
}
|
||||||
|
|
||||||
if (eleWorkOrderBean?.hasCreatedEleWorkOrderPhoto == null || eleWorkOrderBean.hasCreatedEleWorkOrderPhoto != true) {
|
sealed class Action {
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.ConfirmH5Success))
|
data object Init : Action()
|
||||||
return
|
data class UpdateState(val uiState : UiState) : Action()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateState(uiState.value.copy(orderConfirmState = OrderConfirmState.OrderConfirm))
|
data class UiState(
|
||||||
LogUtil.print("queryPaymentInfo", "failed=$msg request=${paymentInfoRequest.toJson()}")
|
val orderConfirmState : OrderConfirmState = OrderConfirmState.Init,
|
||||||
}
|
val orderInfo : OrderInfo? = null,
|
||||||
})
|
val eleWorkOrderBean : EleWorkOrderBean? = null,
|
||||||
}
|
val goNextPage : UpdateTaskBean? = null,
|
||||||
|
val isGoNextPageDialog : Boolean? = null,
|
||||||
|
val paymentInfoBean : PaymentInfoBean? = null,
|
||||||
|
val showNoNeedPayDialog : Boolean? = null,
|
||||||
|
)
|
||||||
|
|
||||||
sealed class Action {
|
sealed class OrderConfirmState {
|
||||||
data object Init : Action()
|
data object Init : OrderConfirmState()
|
||||||
data class UpdateState(val uiState: UiState) : Action()
|
data object Failed : OrderConfirmState()
|
||||||
}
|
data object PaymentInfo : OrderConfirmState()
|
||||||
|
data object ConfirmEle : OrderConfirmState()
|
||||||
data class UiState(
|
data object ChangeBattery : OrderConfirmState()
|
||||||
val orderConfirmState: OrderConfirmState = OrderConfirmState.Init,
|
data object ConfirmH5Success : OrderConfirmState()
|
||||||
val orderInfo: OrderInfo? = null,
|
data object OrderConfirm : OrderConfirmState()
|
||||||
val eleWorkOrderBean: EleWorkOrderBean? = null,
|
}
|
||||||
val goNextPage: UpdateTaskBean? = null,
|
|
||||||
val isGoNextPageDialog: Boolean? = null,
|
|
||||||
val paymentInfoBean: PaymentInfoBean? = null,
|
|
||||||
val showNoNeedPayDialog: Boolean? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
sealed class OrderConfirmState {
|
|
||||||
data object Init : OrderConfirmState()
|
|
||||||
data object Failed : OrderConfirmState()
|
|
||||||
data object PaymentInfo : OrderConfirmState()
|
|
||||||
data object ConfirmEle : OrderConfirmState()
|
|
||||||
data object ChangeBattery : OrderConfirmState()
|
|
||||||
data object ConfirmH5Success : OrderConfirmState()
|
|
||||||
data object OrderConfirm : OrderConfirmState()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.za.ui.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Path
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.camera.view.PreviewView
|
||||||
|
import com.blankj.utilcode.util.ConvertUtils
|
||||||
|
|
||||||
|
class CirclePreviewContainer @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : FrameLayout(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private val path = Path()
|
||||||
|
private var previewView: PreviewView? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
setWillNotDraw(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh)
|
||||||
|
val centerX = w / 2f
|
||||||
|
val centerY = h / 2f
|
||||||
|
val radius = ConvertUtils.dp2px(150f).toFloat().coerceAtMost(w / 2f).coerceAtMost(h / 2f)
|
||||||
|
path.reset()
|
||||||
|
path.addCircle(centerX, centerY, radius, Path.Direction.CW)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispatchDraw(canvas: Canvas) {
|
||||||
|
canvas.save()
|
||||||
|
canvas.clipPath(path)
|
||||||
|
super.dispatchDraw(canvas)
|
||||||
|
canvas.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinishInflate() {
|
||||||
|
super.onFinishInflate()
|
||||||
|
if (childCount > 0) {
|
||||||
|
val child = getChildAt(0)
|
||||||
|
if (child is PreviewView) {
|
||||||
|
previewView = child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
servicing/src/main/res/drawable/preview_overlay_mask.xml
Normal file
21
servicing/src/main/res/drawable/preview_overlay_mask.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Dark semi-transparent background -->
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#00000000" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<!-- Circle with light border -->
|
||||||
|
<item android:gravity="center">
|
||||||
|
<shape android:shape="oval">
|
||||||
|
<size
|
||||||
|
android:width="300dp"
|
||||||
|
android:height="300dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="2dp"
|
||||||
|
android:color="#FFFFFFFF" />
|
||||||
|
<solid android:color="#00000000" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|
||||||
|
<com.za.ui.view.CirclePreviewContainer
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.camera.view.PreviewView
|
||||||
|
android:id="@+id/viewFinder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</com.za.ui.view.CirclePreviewContainer>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/previewOverlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/preview_overlay_mask" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/stepText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginBottom="50dp"
|
||||||
|
android:background="#80000000"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="请保持面部居中" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/confirmationLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/black"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<com.za.signature.view.CircleImageView
|
||||||
|
android:id="@+id/previewImage"
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="确认使用这张照片?"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/retryButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:text="重试" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/confirmButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="确认" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Reference in New Issue
Block a user