package com.xw.yunwei.ui.task.normal
|
|
import android.app.Application
|
import android.content.Context
|
import android.util.Log
|
import android.view.View
|
import androidx.core.os.bundleOf
|
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.map
|
import androidx.lifecycle.viewModelScope
|
import com.amap.api.location.AMapLocation
|
import com.blankj.utilcode.util.GsonUtils
|
import com.xw.common.base.BaseViewModel
|
import com.xw.common.base.FileSelectBean
|
import com.xw.common.base.ImageEventListener
|
import com.xw.common.base.ImageSelectAdapter
|
import com.xw.common.utils.LogUtils
|
import com.xw.common.utils.ToastUtilCommon
|
import com.xw.yunwei.Constants
|
import com.xw.yunwei.Constants.user
|
import com.xw.yunwei.R
|
import com.xw.yunwei.model.SwitchTabMain
|
import com.xw.yunwei.model.SwitchTabTask
|
import com.xw.yunwei.model.TaskNormalChargeModel
|
import com.xw.yunwei.model.TaskNormalCheckModel
|
import com.xw.yunwei.model.TaskNormalCleanModel
|
import com.xw.yunwei.model.TaskNormalMaintainModel
|
import com.xw.yunwei.model.TaskNormalModel
|
import com.xw.yunwei.model.TaskNormalRepairModel
|
import com.xw.yunwei.model.VehicleLocationInfo
|
import com.xw.yunwei.net.CommonRepository
|
import com.xw.yunwei.net.TaskRepository
|
import com.xw.yunwei.net.WorkRepository
|
import com.xw.yunwei.ui.dialog.ApplyForReassignReasonDialog
|
import com.xw.yunwei.ui.work.car.detail.StandardDescriptionActivity
|
import com.xw.yunwei.ui.work.car.detail.operations.charge.ChargeCarActivity
|
import com.xw.yunwei.ui.work.car.detail.operations.check.CheckCarActivity
|
import com.xw.yunwei.ui.work.car.detail.operations.maintain.MaintainCarActivity
|
import com.xw.yunwei.ui.work.car.detail.operations.repair.RepairCarActivity
|
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.launch
|
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MultipartBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
import org.greenrobot.eventbus.EventBus
|
import org.koin.core.component.inject
|
import java.io.File
|
|
/**
|
* 常规任务详情视图模型
|
*
|
* 负责任务详情的查询、子详情加载、图片适配器管理以及任务提交操作。
|
* 根据任务类型(检测、充电、整备、洗车、维修、保养等)和状态(待处理/已处理)
|
* 动态切换 UI 状态并处理对应的业务逻辑。
|
*/
|
class NormalTaskDetailVM(application: Application) : BaseViewModel(application) {
|
/** 任务数据仓库 */
|
val taskRepository: TaskRepository by inject()
|
|
/** 工作台数据仓库 */
|
val workRepository: WorkRepository by inject()
|
|
/** 通用数据仓库(如文件上传) */
|
val commonRepository: CommonRepository by inject()
|
|
/** 当前定位信息 */
|
var location: AMapLocation? = null
|
|
/** 当前任务 ID */
|
var taskId = 0L
|
|
/** 任务主详情数据 */
|
val taskDetail: MutableLiveData<TaskNormalModel> = MutableLiveData()
|
|
/** 页面标题:根据任务状态映射为"待处理"或"已处理" */
|
val title = taskDetail.map {
|
if (it.status == 1) "待处理" else if (it.status == 2) "已处理" else ""
|
}
|
|
/** 紧急程度图标资源 ID */
|
val levelId = taskDetail.map {
|
when (it.taskUrgencyLevel) {
|
0 -> R.mipmap.ic_accident_one
|
1 -> R.mipmap.ic_accident_two
|
2 -> R.mipmap.ic_accident_three
|
3 -> R.mipmap.ic_accident_four
|
else -> R.mipmap.ic_accident_one
|
}
|
}
|
|
/** 待处理状态下操作按钮的文案 */
|
val btnDoingAction = MutableLiveData("")
|
|
/** 是否显示操作按钮 */
|
val showDoingBtn = MutableLiveData(true)
|
|
/** 是否显示滑动完成控件(用于充电任务结束充电) */
|
val showDoingSlide = MutableLiveData(false)
|
|
/** 维修任务是否已送修 */
|
val isRepair = MutableLiveData(false)
|
|
/** 完成任务情况说明(用于保养/年检/保险等) */
|
val taskDescription = MutableLiveData("")
|
|
/** 可编辑图片适配器,仅用于洗车和保养/年检/保险等需要上传图片的任务 */
|
lateinit var adapterCanEdit: ImageSelectAdapter
|
|
/** 可编辑图片的事件监听器 */
|
lateinit var imageEventCanEdit: ImageEventListener<FileSelectBean>
|
|
/** 图片最大选择数量 */
|
val maxSize = 6
|
|
/** 仅查看模式的图片适配器列表 */
|
val adapters = mutableListOf<ImageSelectAdapter>()
|
|
/** 仅查看模式的图片事件监听器列表 */
|
val imageEvents = mutableListOf<ImageEventListener<FileSelectBean>>()
|
|
/** 充电任务子详情 */
|
val chargeModel: MutableLiveData<TaskNormalChargeModel> = MutableLiveData()
|
|
/** 洗车任务子详情 */
|
val cleanModel: MutableLiveData<TaskNormalCleanModel> = MutableLiveData()
|
|
/** 检测任务子详情 */
|
val checkModel: MutableLiveData<TaskNormalCheckModel> = MutableLiveData()
|
|
/** 整备任务子详情 */
|
val maintainModel: MutableLiveData<TaskNormalMaintainModel> = MutableLiveData()
|
|
/** 维修任务子详情 */
|
val repairModel: MutableLiveData<TaskNormalRepairModel> = MutableLiveData()
|
|
//是否已经循环检测车辆位置
|
var hadLoopRefreshCarLocation = false
|
|
//车辆位置
|
val carLocation = MutableLiveData<VehicleLocationInfo>()
|
|
/** 统一点击事件处理:查看标准说明、提交任务 */
|
val onClick = View.OnClickListener {
|
when (it.id) {
|
R.id.viewDetail, R.id.viewDetail1 -> {
|
taskDetail.value?.let {
|
// 根据任务类型跳转到对应标准说明页面
|
val type = when (it.taskTypeId) {
|
"1" -> 7 // 车辆检测
|
"2" -> 6 // 开始充电
|
"4" -> 3 // 车身标识及清洁说明
|
"6" -> 10 // 保养
|
"7" -> 8 // 保险
|
"8" -> 9 //年检
|
"9" -> 11 // 车辆运营资质
|
else -> null
|
}
|
type?.let {
|
startActivity(
|
StandardDescriptionActivity::class.java,
|
bundleOf("type" to type)
|
)
|
}
|
}
|
}
|
|
R.id.submit -> submit()
|
}
|
}
|
|
/**
|
* 查询任务详情
|
*
|
* 根据 [taskId] 拉取主详情,并根据任务状态进一步查询子详情。
|
*/
|
fun queryDetail() {
|
launchRequest {
|
Log.e(TAG, "queryDetail: $taskId")
|
taskRepository.vehicleRoutineDetail("$taskId")?.let {
|
runOnMainThread {
|
// 当首次加载或任务状态发生变化时更新主详情
|
if (taskDetail.value == null || taskDetail.value!!.status != it.status) {
|
taskDetail.value = it
|
}
|
if (it.status == 1) { // 待处理
|
queryDoingTaskStatusByType()
|
carLocation.postValue(
|
VehicleLocationInfo(
|
it.vehicleLon?.toString(),
|
it.vehicleLat?.toString(),
|
it.vehicleLocation
|
)
|
)
|
loopRefreshCarLocation()
|
} else if (it.status == 2) { // 已处理
|
queryFinishTaskByType()
|
}
|
}
|
}
|
}
|
}
|
|
/**
|
* 查询进行中(待处理)任务的子详情
|
*
|
* 目前仅充电和维修任务有待处理子详情需要单独查询。
|
*/
|
fun queryDoingTaskStatusByType() {
|
taskDetail.value?.let {
|
launchRequest {
|
when (it.taskTypeId) {
|
"2" -> { // 充电
|
taskRepository.chargingDetail("$taskId")?.let {
|
chargeModel.postValue(it)
|
}
|
}
|
|
"5" -> { // 维修
|
taskRepository.repairDetail("$taskId")?.let {
|
repairModel.postValue(it)
|
}
|
}
|
}
|
}
|
|
}
|
}
|
|
/**
|
* 查询已完成任务的子详情
|
*
|
* 根据任务类型分别查询检测、充电、整备、洗车、维修等子详情数据。
|
*/
|
fun queryFinishTaskByType() {
|
taskDetail.value?.let {
|
launchRequest {
|
when (it.taskTypeId) {
|
"1" -> { // 检测
|
taskRepository.detectionDetail("$taskId")?.let {
|
checkModel.postValue(it)
|
}
|
}
|
|
"2" -> { // 充电
|
taskRepository.chargingDetail("$taskId")?.let {
|
chargeModel.postValue(it)
|
}
|
}
|
|
"3" -> { // 整备
|
taskRepository.preparationDetail("$taskId")?.let {
|
maintainModel.postValue(it)
|
}
|
}
|
|
"4" -> { // 洗车
|
taskRepository.cleanDetail("$taskId")?.let {
|
cleanModel.postValue(it)
|
}
|
}
|
|
"5" -> { // 维修
|
taskRepository.repairDetail("$taskId")?.let {
|
repairModel.postValue(it)
|
}
|
}
|
}
|
}
|
}
|
}
|
|
/**
|
* 根据任务类型执行对应的提交操作
|
*
|
* 检测、充电、整备、维修等任务跳转对应页面;
|
* 洗车任务直接提交;
|
* 保养/年检/保险/资质到期调用统一保存接口。
|
*/
|
private fun submit() {
|
taskDetail.value?.let {
|
when (it.taskTypeId) {
|
"1" -> { // 车辆检测
|
startActivity(
|
CheckCarActivity::class.java,
|
bundleOf("carId" to (it.vehicleId ?: 0L), "taskId" to (it.id ?: 0L))
|
)
|
}
|
|
"2" -> { // 开始充电
|
startActivity(
|
ChargeCarActivity::class.java,
|
bundleOf("carId" to (it.vehicleId ?: 0L), "taskId" to (it.id ?: 0L))
|
)
|
}
|
|
"3" -> { // 开始整备
|
startActivity(
|
MaintainCarActivity::class.java,
|
bundleOf("carId" to (it.vehicleId ?: 0L), "taskId" to (it.id ?: 0L))
|
)
|
}
|
|
"4" -> { // 完成洗车任务
|
cleanCar()
|
}
|
|
"5" -> { // 去送修/取回
|
startActivity(
|
RepairCarActivity::class.java,
|
bundleOf("carId" to (it.vehicleId ?: 0L), "taskId" to (it.id ?: 0L))
|
)
|
}
|
|
"6", "7", "8", "9" -> { // 完成保养 完成续保 完成年检 车辆运营资质到期
|
saveBy()
|
}
|
}
|
}
|
}
|
|
/**
|
* 提交洗车任务
|
*
|
* 校验图片非空后上传图片,随后调用洗车完成接口。
|
*/
|
private fun cleanCar() {
|
if (adapterCanEdit.data.isEmpty()) {
|
ToastUtilCommon.showError("请先上传车身清洁照片")
|
return
|
}
|
|
val files = mutableListOf<FileSelectBean>()
|
files.addAll(adapterCanEdit.data)
|
|
showDialog("上传中...")
|
uploadFile(files) {
|
dismissDialog()
|
|
val map = mapOf(
|
"operationsUserId" to user?.id,
|
"vehicleId" to taskDetail.value?.vehicleId,
|
"taskImage" to "${files.map { it.url }}",
|
"taskId" to taskDetail.value?.id
|
)
|
launchRequest(tips = "提交中...") {
|
workRepository.cleanCar(map)
|
ToastUtilCommon.showSuc("提交成功")
|
queryDetail()
|
}
|
}
|
}
|
|
/**
|
* 提交保养/保险/年检任务
|
*
|
* 校验说明文字与图片非空后上传图片,随后调用统一保存接口。
|
*/
|
private fun saveBy() {
|
if (taskDescription.value.isNullOrEmpty()) {
|
ToastUtilCommon.showError("请录入完成任务情况说明")
|
return
|
}
|
if (adapterCanEdit.data.isEmpty()) {
|
ToastUtilCommon.showError("请先上传完成任务情况图片")
|
return
|
}
|
|
val files = mutableListOf<FileSelectBean>()
|
files.addAll(adapterCanEdit.data)
|
|
showDialog("上传中...")
|
uploadFile(files) {
|
dismissDialog()
|
|
val map = mapOf(
|
"taskDescription" to taskDescription.value,
|
"taskImage" to GsonUtils.toJson(files.map { it.url }),
|
"id" to taskDetail.value?.id
|
)
|
launchRequest(tips = "提交中...") {
|
taskRepository.saveRoutineDetail(map)
|
ToastUtilCommon.showSuc("提交成功")
|
queryDetail()
|
}
|
}
|
}
|
|
/**
|
* 递归上传文件
|
*
|
* 遍历待上传文件列表,对未上传(url 为空)的文件逐个上传到服务器,
|
* 全部上传完成后执行成功回调。
|
*
|
* @param files 待上传的文件列表
|
* @param succ 全部上传成功后的回调
|
*/
|
private fun uploadFile(files: List<FileSelectBean>, succ: () -> Unit) {
|
val result = files.find { it.url.isEmpty() }
|
if (result == null) {
|
succ()
|
} else {
|
launchRequest(showLoading = false, error = { _, errMsg ->
|
ToastUtilCommon.showError(errMsg)
|
dismissDialog()
|
}) {
|
val file = File(result.localPath)
|
val fileRequestBody = file.asRequestBody("image/jpg".toMediaType())
|
val mBuilder = MultipartBody.Builder()
|
mBuilder.addFormDataPart("file", file.name, fileRequestBody)
|
mBuilder.setType(MultipartBody.FORM)
|
val data = commonRepository.uploadFile(mBuilder.build())
|
result.url = GsonUtils.toJson(data)
|
uploadFile(files, succ)
|
}
|
}
|
}
|
|
//显示改派弹窗
|
fun showApplyForReassignDialog(context: Context) {
|
if (taskDetail.value == null) {
|
return
|
}
|
ApplyForReassignReasonDialog.show(
|
context,
|
Constants.reasons,
|
) { position, input, dialog ->
|
showDialog(content = "改派中...")
|
launchRequest(showLoading = false, error = { code, msg ->
|
dismissDialog()
|
ToastUtilCommon.showError(msg)
|
LogUtils.e(TAG, "launchRequest: code = $code msg = $msg")
|
}) {
|
val comment = Constants.reasons[position]
|
taskRepository.taskReassignment(comment, input, taskId.toString()).also {
|
dialog.dismiss()
|
checkApplyForReassignResult()
|
}
|
}
|
}
|
}
|
|
//检测申请改派结果
|
private fun checkApplyForReassignResult() {
|
launchRequest(showLoading = false, error = { code, msg ->
|
dismissDialog()
|
ToastUtilCommon.showError(msg)
|
LogUtils.e(TAG, "launchRequest: code = $code msg = $msg")
|
}) {
|
delay(3 * 1000)
|
val isOk = taskRepository.checkApplyForReassignResult(taskId.toString())
|
dismissDialog()
|
isOk?.also {
|
if (it) ToastUtilCommon.showSuc("改派成功") else ToastUtilCommon.showError("暂未找到运维人员")
|
EventBus.getDefault().post(SwitchTabMain(1))
|
if (!it) {
|
EventBus.getDefault().post(SwitchTabTask(4))
|
}
|
}
|
delay(1000)
|
finish()
|
}
|
}
|
|
//循环刷新车辆位置
|
private fun loopRefreshCarLocation() {
|
if (hadLoopRefreshCarLocation) {
|
return
|
}
|
hadLoopRefreshCarLocation = true
|
|
viewModelScope.launch {
|
while (true) {
|
delay(60 * 1000)
|
launchRequest(showLoading = false, error = { code, msg ->
|
LogUtils.e(TAG, "launchRequest: code = $code msg = $msg")
|
}) {
|
taskDetail.value?.also { it ->
|
taskRepository.queryVehicleNewPoint(it.vehicleId?.toString())?.also {
|
carLocation.postValue(it)
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|