package com.xw.yunwei.ui.task.create
|
|
import android.app.Application
|
import android.view.View
|
import androidx.lifecycle.MutableLiveData
|
import com.blankj.utilcode.util.GsonUtils
|
import com.xw.common.base.BaseViewModel
|
import com.xw.common.base.FileSelectBean
|
import com.xw.common.base.ImageSelectAdapter
|
import com.xw.common.utils.ToastUtilCommon
|
import com.xw.yunwei.R
|
import com.xw.yunwei.model.CacheAccidentModel
|
import com.xw.yunwei.model.CarModel
|
import com.xw.yunwei.model.Category
|
import com.xw.yunwei.model.FinishPage
|
import com.xw.yunwei.model.Item
|
import com.xw.yunwei.model.SwitchTabMain
|
import com.xw.yunwei.model.SwitchTabTask
|
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 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
|
|
/**
|
* 事故上报页面 ViewModel
|
*
|
* 负责事故工单创建的业务逻辑与数据管理,包括:
|
* - 车辆信息、定位地址、事故类型、任务等级、任务描述的 LiveData 维护
|
* - 图片选择适配器管理
|
* - 事故类型列表的获取与缓存
|
* - 本地图片递归上传到服务器
|
* - 提交事故工单并通知首页/任务页切换 Tab
|
* - 草稿数据组装与恢复
|
*/
|
class CreateTaskVM(myApplication: Application) : BaseViewModel(myApplication) {
|
|
val workRepository: WorkRepository by inject()
|
val taskRepository: TaskRepository by inject()
|
val commonRepository: CommonRepository by inject()
|
|
/** 事故类型分类列表(大类 + 子类) */
|
var categories = mutableListOf<Category>()
|
|
/** 当前选中的车辆信息 */
|
var selectCar: MutableLiveData<CarModel> = MutableLiveData()
|
/** 当前定位信息,null 表示未获取到定位 */
|
// var location: MutableLiveData<AMapLocation?> = MutableLiveData(null)
|
/** 根据定位信息转换的地址文案,未定位时显示"定位中..." */
|
// val address = location.map {
|
// it?.address ?: "定位中..."
|
// }
|
/** 任务紧急等级:0 = P0(最紧急), 1 = P1 , 2 = P2 , 3 = P3(最不紧急),默认 P3 */
|
val taskLevel: MutableLiveData<Int> = MutableLiveData(2)
|
|
/** 任务描述文本 */
|
val taskDesc = MutableLiveData("")
|
|
//车辆实时位置信息
|
val carLocationInfo = MutableLiveData<VehicleLocationInfo?>()
|
|
/** 页面点击事件统一处理:选择车辆、等级切换、提交 */
|
var onClick = View.OnClickListener {
|
when (it.id) {
|
R.id.imgSelectCar -> {
|
// startActivityForResult(
|
// SelectCarActivity::class.java,
|
// 110,
|
// bundleOf("car" to selectCar.value)
|
// )
|
onBackPressed()
|
}
|
|
R.id.level0 -> taskLevel.value = 0
|
R.id.level1 -> taskLevel.value = 1
|
R.id.level2 -> taskLevel.value = 2
|
R.id.submit -> submit()
|
}
|
}
|
|
/** 图片选择适配器 */
|
lateinit var adapter: ImageSelectAdapter
|
|
/** 图片最大可上传数量 */
|
val maxSize = 6
|
|
/**
|
* 提交事故上报信息
|
*
|
* 校验逻辑:
|
* 1. 必须选择车辆
|
* 2. 必须获取到定位
|
* 3. 必须选择事故类型
|
* 4. 必须选择任务等级(0~3)
|
* 5. 必须填写任务描述
|
* 6. 必须上传相关照片
|
*
|
* 校验通过后先递归上传本地图片,再调用 [TaskRepository.saveVehicleAccident] 提交。
|
* 提交成功后通过 EventBus 通知首页切换到任务 Tab 并关闭当前页面。
|
*/
|
fun submit() {
|
if (selectCar.value == null) {
|
ToastUtilCommon.showWarn("请选择车辆")
|
return
|
}
|
if (carLocationInfo.value == null) {
|
ToastUtilCommon.showWarn("未获取到定位")
|
return
|
}
|
// if (getSelectType().isEmpty()) {
|
// ToastUtilCommon.showWarn("请选择事故类型")
|
// return
|
// }
|
if (taskLevel.value !in arrayOf(0, 1, 2, 3)) {
|
ToastUtilCommon.showWarn("请选择任务等级")
|
return
|
}
|
// if (taskDesc.value.isNullOrEmpty()) {
|
// ToastUtilCommon.showWarn("请填写任务描述")
|
// return
|
// }
|
// if (adapter.data.isEmpty()) {
|
// ToastUtilCommon.showWarn("请上传相关照片")
|
// return
|
// }
|
|
showDialog("上传中...")
|
uploadFile(adapter.data) {
|
dismissDialog()
|
launchRequest("提交中") {
|
val map = mutableMapOf<String, Any?>()
|
map["id"] = selectCar.value?.id
|
map["taskDescription"] = taskDesc.value
|
map["taskImage"] = "${adapter.data.map { it.url }}"
|
map["taskTypeId"] = getSelectType()
|
map["taskUrgencyLevel"] = taskLevel.value
|
taskRepository.saveVehicleAccident(map)
|
ToastUtilCommon.showSuc("提交成功")
|
EventBus.getDefault().post(SwitchTabMain(1))
|
EventBus.getDefault().post(SwitchTabTask(0))
|
// delay(1000)
|
EventBus.getDefault().post(FinishPage())
|
finish()
|
}
|
}
|
|
}
|
|
/**
|
* 递归上传本地图片文件到服务器
|
*
|
* 遍历 [files] 列表,找到第一个 [FileSelectBean.url] 为空的本地文件进行上传,
|
* 上传成功后将服务器返回的 URL 写入 [FileSelectBean.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)
|
}
|
}
|
}
|
|
/**
|
* 获取事故类型列表
|
*
|
* 若 [categories] 已存在则直接回调,否则通过网络请求拉取并转换数据结构。
|
*
|
* @param block 数据就绪后的回调(在主线程执行)
|
*/
|
fun getTypeList(block: () -> Unit) {
|
if (categories.isNotEmpty()) {
|
block()
|
} else {
|
launchRequest {
|
taskRepository.getTypeList()?.forEachIndexed { index, type ->
|
val items = mutableListOf<Item>()
|
type.child?.forEach {
|
items.add(Item(it.id ?: 0L, it.errorName ?: ""))
|
}
|
categories.add(Category(index, type.errorName ?: "", items))
|
runOnMainThread { block() }
|
}
|
}
|
}
|
}
|
|
/**
|
* 获取当前已选中的事故类型 ID 字符串
|
*
|
* 遍历所有分类的子项,过滤出 [Item.isSelected] 为 true 的项,
|
* 将其 ID 以逗号分隔拼接成字符串返回。
|
*
|
* @return 已选中事故类型 ID 的逗号分隔字符串,未选择时返回空串
|
*/
|
fun getSelectType(): String {
|
val items = mutableListOf<Item>()
|
categories.forEach { items.addAll(it.items) }
|
return items.filter { it.isSelected }.map { it.id }.joinToString()
|
}
|
|
/**
|
* 获取当前已选中的事故类型 name 列表
|
*
|
*/
|
fun getSelectTypeName(): List<String> {
|
val items = mutableListOf<Item>()
|
categories.forEach { items.addAll(it.items) }
|
return items.filter { it.isSelected }.map { it.name }
|
}
|
|
/**
|
* 获取当前数据填写情况,用于判断是否需要保存草稿
|
*
|
* 当事故类型、任务等级、任务描述、相关照片均未填写时返回 null,
|
* 否则返回包含当前页面数据的 [CacheAccidentModel]。
|
*
|
* @return 当前页面缓存数据,或 null 表示未填写任何内容
|
*/
|
/*获取数据填写情况*/
|
fun getDataWrite(): CacheAccidentModel? {
|
// 事故类型/任务等级/任务描述/相关照片 暂时定义为这几个填了就算填了事故
|
return if (getSelectType().isEmpty() && taskLevel.value !in arrayOf(0, 1, 2, 3)
|
&& taskDesc.value.isNullOrEmpty() && adapter.data.isEmpty()
|
) {
|
null
|
} else {
|
CacheAccidentModel(
|
selectCar.value,
|
categories,
|
taskLevel.value!!,
|
taskDesc.value!!,
|
adapter.data
|
)
|
}
|
}
|
|
//获取车辆实时位置信息
|
fun getVehicleLocation() {
|
selectCar.value?.also { it ->
|
launchRequest {
|
val vehicleLocation = workRepository.getVehicleLocation(it.id.toString())
|
carLocationInfo.postValue(vehicleLocation)
|
}
|
}
|
}
|
}
|