puzhibing
2026-08-21 5fa94b3718b4a78a4fcea4c97652b0ef20b7de3a
app/src/main/java/com/xw/yunwei/ui/task/normal/NormalTaskDetailActivity.kt
@@ -9,55 +9,37 @@
import com.amap.api.location.AMapLocation
import com.amap.api.maps.model.LatLng
import com.blankj.utilcode.util.UriUtils
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.xw.common.CommonDialog
import com.xw.common.base.BaseActivity
import com.xw.common.base.FileSelectBean
import com.xw.common.base.ImageEventListener
import com.xw.common.base.ImageSelectAdapter
import com.xw.common.base.ShowImgListDialog
import com.xw.common.custom.BatteryView.Companion.getBatteryColorByBatteryLife
import com.xw.common.utils.BindUtils.getUrls
import com.xw.common.utils.GlideEngine
import com.xw.common.utils.GpsHelper
import com.xw.common.utils.GpsHelper.Companion.navigate
import com.xw.common.utils.PictureCompressEngine
import com.xw.common.utils.ToastUtilCommon
import com.xw.yunwei.BR
import com.xw.yunwei.BaseBusinessActivity
import com.xw.yunwei.databinding.ActivityNormalTaskDetailBinding
import com.xw.yunwei.model.TaskNormalModel
import com.xw.yunwei.ui.work.car.detail.operations.charge.ChargeCarActivity
import java.util.ArrayList
import com.xw.yunwei.utils.PictureSelectorFactory
/**
 *  任务详情  待处理
 * 常规任务详情页面
 *
 *  日常检查 -> 工作台对应业务
 *  车辆充电  1:充电中  2:结束充电
 *  车辆整备 -> 工作台对应业务
 *  洗车
 *  维修    1:送修 -> 工作台对应业务  2:取回
 *  保养
 *  年检
 *  保险
 *  车辆运营资质到期
 * 支持展示多种任务类型的详情,包括:
 * - 待处理:日常检查、车辆充电、车辆整备、洗车、维修、保养、年检、保险、车辆运营资质到期
 * - 已处理:检测、车辆充电、车辆整备、洗车、维修、保养、年检、保险、车辆运营资质到期
 *
 *  任务详情  已处理
 *  检测
 *  车辆充电
 *  车辆整备
 *  洗车
 *  维修
 *  保养
 *  年检
 *  保险
 *  车辆运营资质到期
 * 页面根据任务状态(待处理/已处理)和任务类型动态展示不同布局,
 * 并支持图片选择、上传及高德地图导航功能。
 */
class NormalTaskDetailActivity: BaseActivity<ActivityNormalTaskDetailBinding, NormalTaskDetailVM>(), GpsHelper.OnMapLocation{
class NormalTaskDetailActivity: BaseBusinessActivity<ActivityNormalTaskDetailBinding, NormalTaskDetailVM>(), GpsHelper.OnMapLocation{
    override fun getBindingVariable(): Int = BR.viewModel
//    var gpsHelper: GpsHelper? = null
@@ -75,24 +57,30 @@
    override fun init() {
        super.init()
        // 从 intent 中获取任务 ID
        viewModel.taskId = intent.getLongExtra("taskId", 0L)
    }
    /** 标识是否从图片选择页返回,避免 onResume 中重复刷新详情 */
    var isGetPictureBack = false
    override fun onResume() {
        super.onResume()
        if (isGetPictureBack) {
            isGetPictureBack = false
            return
        }
        // 查询任务详情及子详情
        viewModel.queryDetail()
    }
    @SuppressLint("SetTextI18n")
    override fun setObservable() {
        super.setObservable()
        // 监听任务主详情,初始化适配器与按钮文案
        viewModel.taskDetail.observe(this) {
            initAdapter(it)
            // 根据任务类型设置待处理状态下的操作按钮文案
            viewModel.btnDoingAction.value = when (it.taskTypeId) {
                "1" -> "开始检查"
                "2" -> "开始充电"
@@ -105,12 +93,15 @@
                "9" -> "完成任务"
                else -> ""
            }
            // 整备和维修任务隐藏详情入口
            binding.layoutDoing.viewDetail.isVisible = it.taskTypeId !in arrayOf("3", "5")
            binding.layoutFinish.viewDetail1.isVisible = it.taskTypeId !in arrayOf("3", "5")
            // 加载任务图片到第一个仅查看适配器
            it.taskImage?.getUrls()?.let {
                viewModel.adapters.getOrNull(0)?.setList(it.map { FileSelectBean(url = it, type = "img") })
            }
        }
        // 监听充电任务子详情
        viewModel.chargeModel.observe(this) {
            if (viewModel.taskDetail.value?.status == 1) { // 待处理
                if (it.startOperationsUserId == null) { // 未充电
@@ -132,6 +123,7 @@
                binding.layoutFinish.chargeLayout.batteryLife2.setTextColor(getBatteryColorByBatteryLife(it.endRemainingBattery ?: 0))
            }
            // 加载充电开始/结束图片
            it.startChargingPicture?.getUrls()?.let {
                viewModel.adapters.getOrNull(0)?.setList(it.map { FileSelectBean(url = it, type = "img") })
            }
@@ -139,11 +131,13 @@
                viewModel.adapters.getOrNull(1)?.setList(it.map { FileSelectBean(url = it, type = "img") })
            }
        }
        // 监听洗车任务子详情
        viewModel.cleanModel.observe(this) {
            it.taskImage?.getUrls()?.let {
                viewModel.adapters.getOrNull(0)?.setList(it.map { FileSelectBean(url = it, type = "img") })
            }
        }
        // 监听检测任务子详情
        viewModel.checkModel.observe(this) {
            it.sensorCleaningPicture?.getUrls()?.let {
                viewModel.adapters.getOrNull(0)?.setList(it.map { FileSelectBean(url = it, type = "img") })
@@ -161,6 +155,7 @@
                viewModel.adapters.getOrNull(4)?.setList(it.map { FileSelectBean(url = it, type = "img") })
            }
        }
        // 监听整备任务子详情
        viewModel.maintainModel.observe(this) {
            it.headLight?.getUrls()?.let {
                viewModel.adapters.getOrNull(0)?.setList(it.map { FileSelectBean(url = it, type = "img") })
@@ -182,6 +177,7 @@
            }
        }
        // 监听维修任务子详情
        viewModel.repairModel.observe(this) {
            if (viewModel.taskDetail.value?.status == 1) { // 待处理
                viewModel.isRepair.value = it.sendUserId != null
@@ -198,6 +194,10 @@
    override fun setListener() {
        super.setListener()
        binding.tvApplyForReassignment.setOnClickListener {
            viewModel.showApplyForReassignDialog(this)
        }
        // 导航按钮:跳转高德地图导航到车辆位置
        binding.layoutDoing.nav.setOnClickListener {
            viewModel.taskDetail.value?.let { item ->
                if ((item.vehicleLat ?: 0.0) != 0.0 && (item.vehicleLon ?: 0.0) != 0.0) {
@@ -211,6 +211,7 @@
            }
        }
        // 滑动完成按钮:充电任务中滑动结束后跳转到充电页面
        binding.layoutDoing.slideView.setOnSlideCompleteListener{
            viewModel.taskDetail.value?.let {
                startActivity(
@@ -222,9 +223,15 @@
        }
    }
    /**
     * 根据任务状态与类型初始化对应的图片适配器
     *
     * @param it 任务详情数据
     */
    private fun initAdapter(it: TaskNormalModel) {
        if (it.status == 1) { // 待处理
            if (it.taskTypeId in arrayOf("4", "6", "7", "8", "9")) {
                // 洗车、保养、年检、保险、资质到期:使用可编辑适配器
                initEditAdapter()
                if (it.taskTypeId == "4") {
                    binding.layoutDoing.cleanLayout.rv.adapter = viewModel.adapterCanEdit
@@ -293,6 +300,7 @@
        }
    }
    /** 初始化可编辑图片适配器,支持添加、查看、删除图片 */
    private fun initEditAdapter() {
        viewModel.imageEventCanEdit = object : ImageEventListener<FileSelectBean>() {
            override fun addImage(item: FileSelectBean) {
@@ -318,6 +326,11 @@
        viewModel.adapterCanEdit = ImageSelectAdapter(this, viewModel.maxSize, 1, viewModel.imageEventCanEdit)
    }
    /**
     * 初始化仅查看图片适配器
     *
     * @param num 需要创建的适配器数量
     */
    private fun initOnlyViewAdapter(num: Int){
        viewModel.imageEvents.clear()
        viewModel.adapters.clear()
@@ -341,6 +354,7 @@
        }
    }
    /** 显示选择拍照或相册的弹窗 */
    private fun showTypeDialog() {
        CommonDialog.showTypeDialog(this) {
            isGetPictureBack = it in arrayOf(1, 0)
@@ -351,25 +365,19 @@
    // 进入图库
    @SuppressLint("SourceLockedOrientationActivity")
    private fun enterGallery() {
        PictureSelector.create(this)
            .openGallery(SelectMimeType.ofImage())
            .setImageEngine(GlideEngine.createGlideEngine())
            .setMaxSelectNum(viewModel.maxSize - viewModel.adapterCanEdit.data.size)
            .setImageSpanCount(4)
            .isPreviewImage(true)
            .isDisplayCamera(false)
            .setCompressEngine(PictureCompressEngine())
            .forResult(resultCallbackListener)
        PictureSelectorFactory.enterGallery(
            this,
            viewModel.maxSize - viewModel.adapterCanEdit.data.size,
            resultCallbackListener
        )
    }
    // 拍照
    private fun takeAPhotograph() {
        PictureSelector.create(this)
            .openCamera(SelectMimeType.ofImage())
            .setCompressEngine(PictureCompressEngine())
            .forResultActivity(resultCallbackListener)
        PictureSelectorFactory.takeAPhotograph(this, resultCallbackListener)
    }
    /** 图片选择结果回调 */
    private var resultCallbackListener = object : OnResultCallbackListener<LocalMedia> {
        override fun onResult(result: ArrayList<LocalMedia>?) {
            result?.let { selectList ->
@@ -377,6 +385,7 @@
                dataList.addAll(viewModel.adapterCanEdit.data)
                for (item in selectList) {
                    val path: String = item.availablePath
                    // 处理 content Uri,转换为绝对路径
                    var imgPath = if (PictureMimeType.isContent(path) && !item.isCut && !item.isCompressed) {
                        UriUtils.uri2File(Uri.parse(path)).absolutePath
                    } else {
@@ -390,6 +399,11 @@
        override fun onCancel() {}
    }
    /**
     * 高德定位回调
     *
     * @param pLocation 定位结果
     */
    override fun location(pLocation: AMapLocation?) {
        viewModel.location = pLocation
    }