package com.xw.yunwei.ui.task.accident.handle
|
|
import android.app.Application
|
import android.view.View
|
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.map
|
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.ToastUtilCommon
|
import com.xw.yunwei.R
|
import com.xw.yunwei.model.Category
|
import com.xw.yunwei.model.Item
|
import com.xw.yunwei.net.CommonRepository
|
import com.xw.yunwei.net.TaskRepository
|
import com.xw.yunwei.ui.MainActivity
|
import kotlinx.coroutines.delay
|
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MultipartBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
import org.koin.core.component.inject
|
import java.io.File
|
|
|
/**
|
* 事故处理页面 ViewModel
|
*
|
* 负责事故处理页面的业务逻辑与数据管理,包括:
|
* - 人员伤亡计数(死亡、重伤、轻伤)的 LiveData 维护与增减操作
|
* - 现场情况、处置情况文本及字数统计
|
* - 责任判定选项与选中状态
|
* - 三组图片适配器与图片事件监听的管理
|
* - 文件上传(递归上传本地图片到服务器)
|
* - 事故处理提交
|
*/
|
class AccidentProcessVM(myApplication: Application) : BaseViewModel(myApplication) {
|
val commonRepository: CommonRepository by inject()
|
val taskRepository: TaskRepository by inject()
|
|
/** 当前任务ID */
|
var taskId = 0L
|
|
/**
|
* 任务类型ID 组id|子id1, 子id2, 子id3...
|
*/
|
var taskTypeId: String? = null
|
|
/** 死亡人数 LiveData,默认 0 */
|
val death = MutableLiveData("0")
|
|
/** 重伤人数 LiveData,默认 0 */
|
val badlyHurt = MutableLiveData("0")
|
|
/** 轻伤人数 LiveData,默认 0 */
|
val minorInjuries = MutableLiveData("0")
|
|
/** 现场情况描述 LiveData */
|
val siteDesc = MutableLiveData("")
|
|
/** 处置情况描述 LiveData */
|
val disposalDesc = MutableLiveData("")
|
|
/** 现场情况当前字数 / 200 */
|
val siteNums = siteDesc.map { "${it.length}/200" }
|
|
/** 处置情况当前字数 / 200 */
|
val disposalNums = disposalDesc.map { "${it.length}/200" }
|
|
/** 责任判定选项列表 */
|
val dataZrpd = listOf("我方主责", "我方无责", "双方同责")
|
|
/** 当前选中的责任判定 */
|
var selectZrpd = ""
|
|
/** 三组图片选择适配器(对应交警判责、现场情况、处置情况) */
|
val adapters = mutableListOf<ImageSelectAdapter>()
|
|
/** 三组图片的事件监听器 */
|
val imageEvents = mutableListOf<ImageEventListener<FileSelectBean>>()
|
|
/** 每组图片最大可上传数量,默认均为 8 张 */
|
val maxSizes = listOf(8, 8, 8)
|
|
/** 当前正在操作的图片组下标(0/1/2),-1 表示未选择 */
|
var operateIndex = -1
|
|
/** 事故类型分类列表(大类 + 子类) */
|
var categories = mutableListOf<Category>()
|
|
/** 页面点击事件统一处理:增减人数按钮、提交按钮 */
|
var onClick = View.OnClickListener {
|
when (it.id) {
|
R.id.cut1 -> death.cut()
|
R.id.cut2 -> badlyHurt.cut()
|
R.id.cut3 -> minorInjuries.cut()
|
R.id.add1 -> death.add()
|
R.id.add2 -> badlyHurt.add()
|
R.id.add3 -> minorInjuries.add()
|
R.id.tvControl -> submit()
|
}
|
}
|
|
/**
|
* 提交事故处理信息
|
*
|
* 校验逻辑:
|
* 1. 必须选择责任判定
|
* 2. 必须上传交警判责照片
|
* 3. 现场情况(文字或照片)至少填一项
|
* 4. 处置情况(文字或照片)至少填一项
|
*
|
* 校验通过后先递归上传本地图片,再调用 [TaskRepository.handleVehicleAccident] 提交。
|
*/
|
private fun submit() {
|
// if (selectZrpd.isEmpty()) {
|
// ToastUtilCommon.showWarn("请选择责任判断")
|
// return
|
// }
|
// if(adapters[0].data.isEmpty()){
|
// ToastUtilCommon.showWarn("请上传交警判责照片")
|
// return
|
// }
|
if (siteDesc.value.isNullOrEmpty() && adapters[1].data.isEmpty()) {
|
ToastUtilCommon.showWarn("请填写现场情况或上传现场情况照片")
|
return
|
}
|
if (disposalDesc.value.isNullOrEmpty() && adapters[2].data.isEmpty()) {
|
ToastUtilCommon.showWarn("请填写处置情况或上传处置情况照片")
|
return
|
}
|
val files = mutableListOf<FileSelectBean>()
|
adapters.forEach {
|
files.addAll(it.data)
|
}
|
showDialog("上传中...")
|
uploadFile(files) {
|
dismissDialog()
|
launchRequest("提交中") {
|
val map = mutableMapOf<String, Any?>()
|
map["id"] = taskId
|
map["deathCount"] = death.value
|
map["severeCount"] = badlyHurt.value
|
map["minorCount"] = minorInjuries.value
|
map["situationDescription"] = siteDesc.value
|
map["disposalDescription"] = disposalDesc.value
|
map["responsibilityJudgment"] = dataZrpd.indexOf(selectZrpd) + 1
|
map["responsibleImage"] = "${adapters[0].data.map { it.url }}"
|
map["situationImage"] = "${adapters[1].data.map { it.url }}"
|
map["disposalImage"] = "${adapters[2].data.map { it.url }}"
|
map["taskTypeId"] = getSelectType()
|
taskRepository.handleVehicleAccident(map)
|
runOnMainThread { ToastUtilCommon.showSuc("提交成功,事故已归档") }
|
delay(500)
|
startActivity(MainActivity::class.java)
|
}
|
}
|
|
}
|
|
/**
|
* 递归上传本地图片文件到服务器
|
*
|
* 遍历 [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)
|
}
|
}
|
}
|
|
/**
|
* MutableLiveData<String> 扩展:人数减 1
|
*
|
* 当前值小于等于 0 时给出提示,不再递减。
|
*/
|
fun MutableLiveData<String>.cut() {
|
val current = value?.toInt() ?: 0
|
if (current <= 0) {
|
ToastUtilCommon.showWarn("不能再减了")
|
} else {
|
value = (current - 1).toString()
|
}
|
}
|
|
/**
|
* MutableLiveData<String> 扩展:人数加 1
|
*
|
* 当前值大于等于 99 时给出提示,不再递增。
|
*/
|
fun MutableLiveData<String>.add() {
|
val current = value?.toInt() ?: 0
|
if (current >= 99) {
|
ToastUtilCommon.showWarn("不能再加了")
|
} else {
|
value = (current + 1).toString()
|
}
|
}
|
|
/**
|
* 获取事故类型列表
|
*
|
* 若 [categories] 已存在则直接回调,否则通过网络请求拉取并转换数据结构。
|
*
|
* @param block 数据就绪后的回调(在主线程执行)
|
*/
|
fun getTypeList(block: () -> Unit) {
|
if (categories.isNotEmpty()) {
|
block()
|
} else {
|
launchRequest {
|
taskRepository.getTypeList()?.also { it ->
|
runOnMainThread {
|
categories.clear()
|
it.mapIndexed { index, type ->
|
val items = mutableListOf<Item>()
|
type.child?.forEach {
|
items.add(Item(it.id ?: 0L, it.errorName ?: ""))
|
}
|
categories.add(Category(index, type.errorName ?: "", items))
|
}
|
val ids = taskTypeId?.split(", ") ?: emptyList()
|
categories.forEach { category ->
|
category.items.forEach {
|
it.isSelected = ids.contains(it.id.toString())
|
}
|
}
|
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 }
|
}
|
}
|