| | |
| | | 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.net.CommonRepository |
| | | 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 |
| | | import kotlin.getValue |
| | | |
| | | /** |
| | | * 常规任务详情视图模型 |
| | | * |
| | | * 负责任务详情的查询、子详情加载、图片适配器管理以及任务提交操作。 |
| | | * 根据任务类型(检测、充电、整备、洗车、维修、保养等)和状态(待处理/已处理) |
| | | * 动态切换 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 "" |
| | | } |
| | | 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 // 只有洗车和(保养/年检/保险) |
| | | /** 任务主详情数据 */ |
| | | 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() // 维修 |
| | | /** 充电任务子详情 */ |
| | | 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 // 开始充电 |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 查询任务详情 |
| | | * |
| | | * 根据 [taskId] 拉取主详情,并根据任务状态进一步查询子详情。 |
| | | */ |
| | | fun queryDetail() { |
| | | launchRequest { |
| | | Log.e(TAG, "queryDetail: $taskId", ) |
| | | 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 { |
| | |
| | | } |
| | | } |
| | | |
| | | /*查询已完成任务的具体子详情*/ |
| | | /** |
| | | * 查询已完成任务的子详情 |
| | | * |
| | | * 根据任务类型分别查询检测、充电、整备、洗车、维修等子详情数据。 |
| | | */ |
| | | fun queryFinishTaskByType() { |
| | | taskDetail.value?.let { |
| | | launchRequest { |
| | |
| | | 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(){ |
| | | /** |
| | | * 根据任务类型执行对应的提交操作 |
| | | * |
| | | * 检测、充电、整备、维修等任务跳转对应页面; |
| | | * 洗车任务直接提交; |
| | | * 保养/年检/保险/资质到期调用统一保存接口。 |
| | | */ |
| | | private fun submit() { |
| | | taskDetail.value?.let { |
| | | when (it.taskTypeId) { |
| | | "1" -> { // 车辆检测 |
| | |
| | | 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" -> { // 完成保养 完成续保 完成年检 车辆运营资质到期 |
| | | |
| | | "6", "7", "8", "9" -> { // 完成保养 完成续保 完成年检 车辆运营资质到期 |
| | | saveBy() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 提交洗车任务 |
| | | * |
| | | * 校验图片非空后上传图片,随后调用洗车完成接口。 |
| | | */ |
| | | private fun cleanCar() { |
| | | if (adapterCanEdit.data.isEmpty()) { |
| | | ToastUtilCommon.showError("请先上传车身清洁照片") |
| | |
| | | val map = mapOf( |
| | | "operationsUserId" to user?.id, |
| | | "vehicleId" to taskDetail.value?.vehicleId, |
| | | "taskImage" to GsonUtils.toJson(files.map { it.url }), |
| | | "taskImage" to "${files.map { it.url }}", |
| | | "taskId" to taskDetail.value?.id |
| | | ) |
| | | launchRequest(tips = "提交中...") { |
| | |
| | | } |
| | | } |
| | | |
| | | /*完成保养/保险/年检*/ |
| | | private fun saveBy(){ |
| | | /** |
| | | * 提交保养/保险/年检任务 |
| | | * |
| | | * 校验说明文字与图片非空后上传图片,随后调用统一保存接口。 |
| | | */ |
| | | private fun saveBy() { |
| | | if (taskDescription.value.isNullOrEmpty()) { |
| | | ToastUtilCommon.showError("请录入完成任务情况说明") |
| | | return |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 递归上传文件 |
| | | * |
| | | * 遍历待上传文件列表,对未上传(url 为空)的文件逐个上传到服务器, |
| | | * 全部上传完成后执行成功回调。 |
| | | * |
| | | * @param files 待上传的文件列表 |
| | | * @param succ 全部上传成功后的回调 |
| | | */ |
| | | private fun uploadFile(files: List<FileSelectBean>, succ: () -> Unit) { |
| | | val result = files.find { it.url.isEmpty() } |
| | | if (result == null) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | //显示改派弹窗 |
| | | 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) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |