18034727885
2026-06-12 7e886295218e76f4c4fea91f5164c9114bc77ed0
车辆详情优化
7个文件已添加
10个文件已修改
528 ■■■■■ 已修改文件
app/src/main/java/com/xw/yunwei/model/AcceptCarPointInfo.kt 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/model/CarModel.kt 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/net/WorkApi.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/net/WorkRepository.kt 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/dialog/ConfirmAcceptCarPointDialog.kt 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/dialog/SelectConfirmAcceptCarPointDialog.kt 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/work/car/detail/CarDetailActivity.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/work/car/detail/CarDetailVM.kt 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/work/car/detail/adapter/AcceptCarPointAdapter.kt 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/ui/work/car/detail/dispatch/DispatchFragment.kt 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/dialog_confirm_accept_car_point.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/dialog_select_confirm_accept_car_point.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/fragment_car_dispatch.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/item_accept_car_point.xml 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/mipmap-xhdpi/icon_circle_gray2.png 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/mipmap-xhdpi/icon_circle_ring_blue.png 补丁 | 查看 | 原始文档 | blame | 历史
common/src/main/res/drawable/shape_white_bg_top_16.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/xw/yunwei/model/AcceptCarPointInfo.kt
New file
@@ -0,0 +1,62 @@
package com.xw.yunwei.model
import android.os.Parcelable
import com.xw.common.utils.BindUtils.getUrl
import kotlinx.parcelize.Parcelize
import org.json.JSONArray
@Parcelize
data class AcceptCarPointInfo(
    val chargePoint: String? = null,//0否 1是充电点位
    val cityCode: String? = null,//城市code
    val cityName: String? = null,//城市名称
    val deleted: String? = null,//是否删除 0未删除 1已删除
    val distance: String? = null,//距离 单位米
    val districtCode: String? = null,//区县code
    val districtName: String? = null,//区县名称
    val effectTime: String? = null,//生效时间
    val effectivePeriod: String? = null,//生效周期 1=“每日生效”、2=“仅工作日生效”、3=“仅非工作日生效”、4=“仅节假日生效”
    val effectiveTimePeriod: String? = null,//自定义运营生效时间段
    val electronicAreaId: String? = null,//电子围栏区域id
    val electronicEffectTime: String? = null,//围栏的生效时间
    val electronicName: String? = null,//电子围栏名称
    val fenceOperationStrategy: String? = null,//围栏运营策略
    val fpElectronicAreaId: String? = null,//
    val hoverStatusDes: String? = null,//状态描述
    val id: String? = null,//
    val operationStatus: String? = null,//运营状态 1=待启用 2=启用中 3=已停用 4=已失效
    val operationType: String? = null,//运营类型 1=与运营区同步 2=自定义时间段
    val parkingPoint: String? = null,//0否 1是收车点位
    val parkingTimeLimit: String? = null,//限停时长
    val pointAddress: String? = null,//点位地址
    val pointLat: String? = null,//纬度
    val pointLon: String? = null,//经度
    val pointName: String? = null,//点位名称
    val pointNumber: String? = null,//点位编号唯一
    val pointOnOff: String? = null,//点位上下车 1仅上车点/ 2 仅下车/ 3上下车均可
    val pointOnOffName: String? = null,//
    val pointPictures: String? = null,//点位照片
    val pointPoi: String? = null,//点位poi
    val pointType: String? = null,//点位类型 1=运营点位 2=测试点位
    val provinceCode: String? = null,//省份code
    val provinceName: String? = null,//省份名称
    val remarks: String? = null,//备注
    val stationEffectivePeriod: String? = null,//场站生效周期 1=每日 2=仅工作日 3=仅非工作日 4=仅节假日
    val stationEffectiveTimePeriod: String? = null,//场站运营策略
    val stationId: String? = null,//所属场站id,为空表示运营区直属点位
    val stationName: String? = null,//所属场站名称
    val stationOperationType: String? = null,//场站运营类型 1=与运营区同步 2=自定义时间段
    val stationSortNo: String? = null,//点位在场站内排序
    val strId: String? = null,//
    val verificationStatus: String? = null,//验证状态 1=待验证、2=验证中、3=已验证 4验证失败 5待生效
) : Parcelable {
    //获取显示图片地址
    fun getShowPictureUrl(): String {
        return try {
            JSONArray(pointPictures).get(0).toString().getUrl()
        } catch (e: Exception) {
            e.printStackTrace()
            return ""
        }
    }
}
app/src/main/java/com/xw/yunwei/model/CarModel.kt
@@ -243,10 +243,21 @@
     * 记录修改时间,前端忽略
     */
    @SerializedName("updateTime")
    val updateTime: String? = null
    val updateTime: String? = null,
    var pointName: String? = null,//收车点位名称
) : Parcelable {
    //是否正在工作中
    fun isWorking(): Boolean {
        return operatingStatus == 1
    }
    //是否已经开启接单
    fun hadOpenTakeOrder(): Boolean {
        return acceptOrTest == 1 && acceptOrTestStatus == 1
    }
    //正在前往收车点中
    fun isArrivingPoint(): Boolean {
        return !pointName.isNullOrEmpty()
    }
}
app/src/main/java/com/xw/yunwei/net/WorkApi.kt
@@ -2,6 +2,7 @@
import com.xw.common.net.interceptor.HttpResponse
import com.xw.common.net.interceptor.PageResponse
import com.xw.yunwei.model.AcceptCarPointInfo
import com.xw.yunwei.model.AreaModel
import com.xw.yunwei.model.CarModel
import com.xw.yunwei.model.CarOperationRecordModel
@@ -170,4 +171,8 @@
        @Path("id") id: String,
        @Path("locationId") locationId: String
    ): Call<HttpResponse<CruiseCheckInOperationResult>>
    /* 获取所有收车点 */
    @GET("operation/maintenance-app/api/v1/point/listParkingPoint")
    fun getAllAcceptCarPoints(@Query("vehicleId") vehicleId: String): Call<HttpResponse<List<AcceptCarPointInfo>>>
}
app/src/main/java/com/xw/yunwei/net/WorkRepository.kt
@@ -3,6 +3,7 @@
import com.blankj.utilcode.util.GsonUtils
import com.xw.common.net.BaseHttpManager.Companion.getBody
import com.xw.common.net.interceptAwait
import com.xw.yunwei.model.AcceptCarPointInfo
import com.xw.yunwei.model.CheckInMissionPointInfo
import com.xw.yunwei.model.CheckRecordModel
import com.xw.yunwei.model.CruiseCheckInMissionInfo
@@ -25,20 +26,17 @@
    suspend fun unlockByType(map: Map<String, Any?>) =
        api.unlockByType(getBody(map)).interceptAwait()
    suspend fun saveRepair(map: Map<String, Any?>) =
        api.saveRepair(getBody(map)).interceptAwait()
    suspend fun saveRepair(map: Map<String, Any?>) = api.saveRepair(getBody(map)).interceptAwait()
    suspend fun saveReturnRepair(map: Map<String, Any?>) =
        api.saveReturnRepair(getBody(map)).interceptAwait()
    suspend fun cleanCar(map: Map<String, Any?>) =
        api.cleanCar(getBody(map)).interceptAwait()
    suspend fun cleanCar(map: Map<String, Any?>) = api.cleanCar(getBody(map)).interceptAwait()
    suspend fun savePreparation(body: MaintainRecordModel) =
        api.savePreparation(body).interceptAwait()
    suspend fun getRecord(map: Map<String, Any?>) =
        api.getRecord(getBody(map)).interceptAwait()
    suspend fun getRecord(map: Map<String, Any?>) = api.getRecord(getBody(map)).interceptAwait()
    suspend fun startCharging(map: Map<String, Any?>) =
        api.startCharging(getBody(map)).interceptAwait()
@@ -65,6 +63,7 @@
    /* 获取车辆实时位置 */
    suspend fun getVehicleLocation(vehicleId: String) =
        api.getVehicleLocation(vehicleId).interceptAwait()
    /* 现场情况上报 */
    suspend fun addPointSituationReport(
        work: Boolean,
@@ -124,9 +123,13 @@
    /* 获取打卡结果详情 */
    suspend fun getCruiseCheckInRecordInfo(
        id: String,
        locationId: String
        id: String, locationId: String
    ): CruiseCheckInOperationResult? {
        return api.getCruiseCheckInRecordInfo(id, locationId).interceptAwait()
    }
    /* 获取所有收车点 */
    suspend fun getAllAcceptCarPoints(vehicleId: String): List<AcceptCarPointInfo>? {
        return api.getAllAcceptCarPoints(vehicleId).interceptAwait()
    }
}
app/src/main/java/com/xw/yunwei/ui/dialog/ConfirmAcceptCarPointDialog.kt
@@ -6,14 +6,17 @@
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.xw.yunwei.R
import com.xw.yunwei.model.AcceptCarPointInfo
import com.xw.yunwei.utils.DialogFactory
//收车点确认弹窗
object ConfirmAcceptCarPointDialog {
    fun show(
        context: Context,
        reasons: List<String>,
        submitBlock: (position: Int, input: String, dialog: MaterialDialog) -> Unit
        index: Int = 0,
        points: List<AcceptCarPointInfo>,
        cancelBlock: () -> Unit,
        confirmBlock: (AcceptCarPointInfo, MaterialDialog) -> Unit
    ) {
        val dialog = DialogFactory.produce(context).apply {
            customView(
@@ -23,8 +26,33 @@
            )
            cornerRadius(8f)
            val tv_title = findViewById<TextView>(R.id.tv_title)
            val tvTitle = findViewById<TextView>(R.id.tv_title)
            val tvDetail = findViewById<TextView>(R.id.tv_detail)
            val tvChange = findViewById<TextView>(R.id.tv_change)
            val tvConfirm = findViewById<TextView>(R.id.tv_confirm)
            tvTitle.text = points[index].pointName
            tvDetail.text = points[index].pointAddress
            var needChange = false
            tvChange.setOnClickListener {
                needChange = true
                dismiss()
                SelectConfirmAcceptCarPointDialog.show(
                    context = context,
                    index = index,
                    points = points,
                    cancelBlock = cancelBlock,
                    confirmBlock = confirmBlock
                )
            }
            tvConfirm.setOnClickListener {
                confirmBlock.invoke(points[index], this)
            }
            setOnDismissListener {
                if (!needChange) {
                    cancelBlock.invoke()
                }
            }
        }
        dialog.show()
        dialog.window?.setGravity(Gravity.CENTER)
app/src/main/java/com/xw/yunwei/ui/dialog/SelectConfirmAcceptCarPointDialog.kt
@@ -2,30 +2,70 @@
import android.content.Context
import android.view.Gravity
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.google.android.material.button.MaterialButton
import com.xw.yunwei.R
import com.xw.yunwei.extension.dpToPx
import com.xw.yunwei.model.AcceptCarPointInfo
import com.xw.yunwei.ui.work.car.detail.adapter.AcceptCarPointAdapter
import com.xw.yunwei.utils.DialogFactory
import kotlin.math.min
//选择确认收车点弹窗
object SelectConfirmAcceptCarPointDialog {
    var hadOperation = false
    fun show(
        context: Context,
        reasons: List<String>,
        submitBlock: (position: Int, input: String, dialog: MaterialDialog) -> Unit
        index: Int = 0,
        points: List<AcceptCarPointInfo>,
        maxShowLength: Int = 3,
        cancelBlock: () -> Unit,
        confirmBlock: (AcceptCarPointInfo, MaterialDialog) -> Unit
    ) {
        val dialog = DialogFactory.produce(context).apply {
            customView(
                R.layout.dialog_apply_for_reassign_reason,
                R.layout.dialog_select_confirm_accept_car_point,
                noVerticalPadding = true,
                dialogWrapContent = false
            )
            cornerRadius(4f)
            val ivFlexing = findViewById<ImageView>(R.id.iv_flexing)
            val rvList = findViewById<RecyclerView>(R.id.rv_list)
            val btnOperation = findViewById<MaterialButton>(R.id.btn_operation)
            ivFlexing.setOnClickListener {
                dismiss()
                cancelBlock.invoke()
            }
            val recyclerViewHeight = min(maxShowLength, points.size) * 109.dpToPx(context)
            rvList.layoutParams = rvList.layoutParams.apply {
                height = recyclerViewHeight
            }
            rvList.layoutManager = LinearLayoutManager(context)
            val adapter = AcceptCarPointAdapter(index)
            rvList.adapter = adapter
            adapter.setList(points)
            btnOperation.setOnClickListener {
                hadOperation = true
                confirmBlock.invoke(points[adapter.selectIndex], this)
            }
            setOnDismissListener {
                if (!hadOperation) {
                    cancelBlock.invoke()
                }
            }
        }
        dialog.show()
        dialog.window?.setGravity(Gravity.CENTER)
        dialog.window?.setWindowAnimations(com.xw.common.R.style.AnimLeft)
        dialog.window?.setLayout(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        dialog.window?.setGravity(Gravity.BOTTOM)
        dialog.window?.setWindowAnimations(com.xw.common.R.style.AnimUp)
    }
}
app/src/main/java/com/xw/yunwei/ui/work/car/detail/CarDetailActivity.kt
@@ -1,9 +1,7 @@
package com.xw.yunwei.ui.work.car.detail
import android.util.Log
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.blankj.utilcode.util.GsonUtils
import com.google.android.material.tabs.TabLayoutMediator
import com.xw.common.base.fastObserve
import com.xw.yunwei.BR
@@ -59,6 +57,7 @@
            viewModel.qingjiePermissions.value = findPermissionByName("车辆清洁")?.visible == "0"
            viewModel.recordPermissions.value = findPermissionByName("运维记录")?.visible == "0"
            viewModel.policyPermissions.value = findPermissionByName("查看保单")?.visible == "0"
            viewModel.checkCould()
        }
    }
app/src/main/java/com/xw/yunwei/ui/work/car/detail/CarDetailVM.kt
@@ -4,14 +4,13 @@
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import com.xw.common.base.BasePagingViewModel
import com.xw.common.base.BaseViewModel
import com.xw.common.utils.ToastUtilCommon
import com.xw.yunwei.MyApp
import com.xw.yunwei.model.AcceptCarPointInfo
import com.xw.yunwei.model.CarModel
import com.xw.yunwei.net.UserRepository
import com.xw.yunwei.net.WorkRepository
import org.koin.core.component.inject
import kotlin.getValue
class CarDetailVM(application: Application) : BasePagingViewModel(application) {
    val workRepository: WorkRepository by inject()
@@ -21,14 +20,18 @@
    val carInfo: MutableLiveData<CarModel> = MutableLiveData()
    val nextTime = carInfo.map {
        it.nextMaintenanceTime?:"--"
        it.nextMaintenanceTime ?: "--"
    }
    val unlockDoorPermissions = MutableLiveData(false) // 车门解锁权限
    val unlockBoxPermissions = MutableLiveData(false) // 车门解锁权限
    val isArrivingAcceptPoint = MutableLiveData(false) // 是否正在前往收车点
    val arrivingAcceptPointAddress = MutableLiveData("") // 正在前往收车点信息
    val departurePermissions = MutableLiveData(false) // 发车/收车权限
    val takeOrdersPermissions = MutableLiveData(false) // 接单/测试权限
    val couldTakeOrderOrTest = MutableLiveData(false) // 是否能接单/测试
    val hadOpenTakeOrder = MutableLiveData(false) // 是否打开接单
    val couldOperationDevice = MutableLiveData(false)//是否能操作设备
    val unlockDoorPermissions = MutableLiveData(false) // 车门解锁权限
    val unlockBoxPermissions = MutableLiveData(false) // 车门解锁权限
    val zhengbeiPermissions = MutableLiveData(false) // 整备权限
    val chongdianPermissions = MutableLiveData(false) // 充电权限
    val jiancePermissions = MutableLiveData(false) // 检测权限
@@ -44,9 +47,28 @@
            refreshLiveData.done()
        }) {
            workRepository.queryCarInfo(carId)?.let {
                carInfo.postValue(it)
                refreshLiveData.done()
                runOnMainThread {
                    carInfo.value = it
                    refreshLiveData.done()
                    checkCould()
                }
            }
        }
    }
    //检查是否能够
    fun checkCould() {
        carInfo.value?.also {
            this.isArrivingAcceptPoint.postValue(it.isArrivingPoint() && !it.isWorking())
            this.arrivingAcceptPointAddress.postValue(it.pointName)
            val couldTakeOrder = (takeOrdersPermissions.value ?: false) && it.isWorking()
            this.couldTakeOrderOrTest.postValue(couldTakeOrder)
            val hadOpenTakeOrder = it.hadOpenTakeOrder()
            this.hadOpenTakeOrder.postValue(hadOpenTakeOrder)
            val couldOperationDevice =
                ((unlockDoorPermissions.value ?: false) || (unlockBoxPermissions.value
                    ?: false)) && !hadOpenTakeOrder && couldTakeOrder
            this.couldOperationDevice.postValue(couldOperationDevice)
        }
    }
@@ -66,17 +88,46 @@
        }
    }
    fun vehicleDispatchDeparture(map: Map<String, Any?>, error: () -> Unit, block: () -> Unit) {
        launchRequest(tips = "正在传达指令", error = { code, msg ->
            runOnMainThread {
                ToastUtilCommon.showError(msg.ifEmpty { "操作失败" })
                error()
    //获取所有收车点
    fun getAllAcceptCarPoints(error: () -> Unit, block: (List<AcceptCarPointInfo>) -> Unit) {
        carInfo.value?.also { it ->
            launchRequest(error = { code, msg ->
                runOnMainThread {
                    ToastUtilCommon.showError(msg.ifEmpty { "操作失败" })
                    error()
                }
            }) {
                workRepository.getAllAcceptCarPoints(it.id.toString())?.also {
                    runOnMainThread { block.invoke(it) }
                }
            }
        }) {
            workRepository.vehicleDispatchDeparture(map)
            runOnMainThread {
                ToastUtilCommon.showSuc("操作成功")
                block()
        }
    }
    //收发车
    fun vehicleDispatchDeparture(
        setStatus: Int,
        xpPointId: String? = null,
        error: () -> Unit,
        block: () -> Unit
    ) {
        carInfo.value?.let {
            val map = mutableMapOf<String, Any?>()
            map["vehicleId"] = it.id // 车辆ID
            map["xpPointId"] = xpPointId // 车辆ID
            map["departureStatus"] = setStatus // 发车状态 1=发车 3=收车
            launchRequest(tips = "正在传达指令", error = { code, msg ->
                runOnMainThread {
                    ToastUtilCommon.showError(msg.ifEmpty { "操作失败" })
                    error()
                }
            }) {
                workRepository.vehicleDispatchDeparture(map)
                runOnMainThread {
                    ToastUtilCommon.showSuc("操作成功")
                    carInfo.value?.operatingStatus = setStatus
                    block()
                }
            }
        }
    }
app/src/main/java/com/xw/yunwei/ui/work/car/detail/adapter/AcceptCarPointAdapter.kt
New file
@@ -0,0 +1,40 @@
package com.xw.yunwei.ui.work.car.detail.adapter
import android.widget.ImageView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.xw.common.utils.GlideEngine
import com.xw.yunwei.R
import com.xw.yunwei.model.AcceptCarPointInfo
//收车点适配器
class AcceptCarPointAdapter(var selectIndex: Int = 0) :
    BaseQuickAdapter<AcceptCarPointInfo, BaseViewHolder>(R.layout.item_accept_car_point) {
    val defaultSelectIndex = selectIndex
    override fun convert(holder: BaseViewHolder, item: AcceptCarPointInfo) {
        holder
            .setImageResource(
                R.id.iv_selected,
                if (holder.bindingAdapterPosition == selectIndex) R.mipmap.icon_circle_ring_blue else R.mipmap.icon_circle_gray2
            )
            .setText(R.id.tv_title, item.pointName)
            .setText(R.id.tv_detail, item.pointAddress)
            .setGone(R.id.tv_label, defaultSelectIndex != holder.bindingAdapterPosition)
            .setGone(R.id.v_line, holder.bindingAdapterPosition == data.size - 1)
        val ivPicture = holder.getView<ImageView>(R.id.iv_picture)
        GlideEngine.createGlideEngine()
            .load(
                ivPicture,
                item.getShowPictureUrl(),
                R.mipmap.img_site_bg,
                R.mipmap.img_site_bg,
                4f
            )
        holder.itemView.setOnClickListener {
            val lastIndex = selectIndex
            selectIndex = holder.bindingAdapterPosition
            notifyItemChanged(lastIndex)
            notifyItemChanged(selectIndex)
        }
    }
}
app/src/main/java/com/xw/yunwei/ui/work/car/detail/dispatch/DispatchFragment.kt
@@ -12,6 +12,8 @@
import com.xw.yunwei.R
import com.xw.yunwei.databinding.FragmentCarDispatchBinding
import com.xw.yunwei.model.CarModel
import com.xw.yunwei.ui.dialog.ConfirmAcceptCarPointDialog
import com.xw.yunwei.ui.dialog.SelectConfirmAcceptCarPointDialog
import com.xw.yunwei.ui.work.car.detail.CarDetailActivity
/**
@@ -31,6 +33,11 @@
        super.setObservable()
        viewModel.carInfo.observe(this) {
            initBasicInfo(it)
            if (it.operatingStatus == 1) {
                resetSlideView(binding.slideView1, DIRECTION_LEFT, "左滑收车")
            } else {
                resetSlideView(binding.slideView1, DIRECTION_RIGHT, "右滑发车")
            }
        }
    }
@@ -38,39 +45,69 @@
        super.setListener()
        with(binding.slideView1) {
            setOnSlideCompleteListener {
                val carInfo = viewModel.carInfo.value
                carInfo?.let { carInfo ->
                    val setStatus = if (carInfo.operatingStatus == 1) 3 else 1
                    val map = mutableMapOf<String, Any?>()
                    map["vehicleId"] = carInfo.id // 车辆ID
                    map["departureStatus"] = setStatus // 发车状态 1=发车 3=收车
                    viewModel.vehicleDispatchDeparture(map, {
                        binding.slideView1.animateReset()
                    }) {
                        carInfo.operatingStatus = setStatus
                viewModel.carInfo.value?.also { it ->
                    val setStatus = if (it.operatingStatus == 1) 3 else 1
                    if (setStatus == 3) {
                        viewModel.getAllAcceptCarPoints(error = {
                            binding.slideView1.animateReset()
                        }) {
                            ConfirmAcceptCarPointDialog.show(
                                context = requireActivity(),
                                points = it,
                                cancelBlock = {
                                    binding.slideView1.animateReset()
                                },
                                confirmBlock = { point, dialog ->
                                    viewModel.vehicleDispatchDeparture(
                                        setStatus = setStatus,
                                        xpPointId = point.id,
                                        error = {
                                            SelectConfirmAcceptCarPointDialog.hadOperation = false
                                        }) {
                                        dialog.dismiss()
                                        if (getSlideDirection() == DIRECTION_RIGHT) {
                                            resetSlideView(this, DIRECTION_LEFT, "左滑收车")
                                        } else if (getSlideDirection() == DIRECTION_LEFT) {
                                            resetSlideView(this, DIRECTION_RIGHT, "右滑发车")
                                        }
                                        viewModel.checkCould()
                                    }
                                })
                        }
                        return@also
                    }
                    viewModel.vehicleDispatchDeparture(
                        setStatus = setStatus,
                        error = {
                            binding.slideView1.animateReset()
                        }) {
                        if (getSlideDirection() == DIRECTION_RIGHT) {
                            resetSlideView(this, DIRECTION_LEFT, "左滑收车")
                        } else if (getSlideDirection() == DIRECTION_LEFT) {
                            resetSlideView(this, DIRECTION_RIGHT, "右滑发车")
                        }
                        viewModel.checkCould()
                    }
                }
            }
        }
        binding.cbTakeOrder.setOnCheckedChangeListener { button, bool ->
            viewModel.carInfo.value?.takeIf {
                it.hadOpenTakeOrder() != bool
            }?.also { carInfo ->
                val setStatus = if (carInfo.acceptOrTestStatus == 1) 2 else 1
            viewModel.hadOpenTakeOrder.value?.takeIf {
                it != bool
            }?.also { hadOpenTakeOrder ->
                val setStatus = if (hadOpenTakeOrder) 2 else 1
                val map = mutableMapOf<String, Any?>()
                map["vehicleId"] = carInfo.id // 车辆ID
                map["acceptOrTest"] = carInfo.acceptOrTest // 当前模式 1接单 2测试
                map["vehicleId"] = viewModel.carInfo.value?.id // 车辆ID
                map["acceptOrTest"] = 1 // 当前模式 1接单 2测试
                map["acceptOrTestStatus"] = setStatus // 模式状态 1开始接单/开始测试 2停止接单/停止测试
                viewModel.vehicleDispatchAccept(map, {
                    viewModel.queryInfo()
                }) {
                    viewModel.carInfo.postValue(carInfo.copy(acceptOrTestStatus = setStatus))
                    viewModel.runOnMainThread {
                        viewModel.carInfo.value?.acceptOrTestStatus = setStatus
                        viewModel.checkCould()
                    }
                }
            }
        }
app/src/main/res/layout/dialog_confirm_accept_car_point.xml
@@ -20,6 +20,7 @@
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_16"
        android:background="@drawable/shape_0d31456a_bg_8"
        android:padding="@dimen/dp_16">
@@ -55,6 +56,8 @@
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/dp_4"
            android:layout_marginTop="@dimen/dp_4"
            android:lineSpacingMultiplier="1.1"
            android:textColor="@color/color_838fa6"
            android:textSize="@dimen/sp_14"
            app:layout_constraintEnd_toEndOf="parent"
app/src/main/res/layout/dialog_select_confirm_accept_car_point.xml
New file
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/shape_white_bg_top_16"
    android:gravity="center"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/iv_flexing"
        android:layout_width="@dimen/dp_40"
        android:layout_height="@dimen/dp_40"
        android:padding="@dimen/dp_8"
        android:src="@mipmap/ic_down" />
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:itemCount="3"
        tools:listitem="@layout/item_accept_car_point" />
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/gray_4" />
    <com.google.android.material.button.MaterialButton
        android:id="@+id/btn_operation"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_42"
        android:layout_marginHorizontal="@dimen/dp_20"
        android:layout_marginVertical="@dimen/dp_12"
        android:background="@drawable/shape_blue_5_bg_4"
        android:text="确认选择"
        android:textSize="@dimen/sp_16"
        android:textStyle="bold"
        app:cornerRadius="@dimen/dp_4" />
</LinearLayout>
app/src/main/res/layout/fragment_car_dispatch.xml
@@ -93,6 +93,7 @@
            <LinearLayout
                android:id="@+id/ll_destination"
                show="@{viewModel.isArrivingAcceptPoint}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="@dimen/dp_20"
@@ -132,6 +133,7 @@
                        android:layout_weight="1"
                        android:ellipsize="end"
                        android:singleLine="true"
                        android:text="@{viewModel.arrivingAcceptPointAddress}"
                        android:textColor="@color/blue_5"
                        android:textSize="@dimen/sp_11"
                        tools:text="广州市天河区珠江新城幸福小区东北门广州市天河区珠江新城幸福小区东北门" />
@@ -159,7 +161,7 @@
            <LinearLayout
                android:id="@+id/layout1"
                show="@{viewModel.takeOrdersPermissions}"
                show="@{viewModel.couldTakeOrderOrTest}"
                android:layout_width="match_parent"
                android:layout_height="@dimen/dp_72"
                android:layout_marginHorizontal="@dimen/dp_20"
@@ -198,13 +200,13 @@
                    android:layout_height="@dimen/dp_32"
                    android:background="@drawable/selector_switch_off_on"
                    android:button="@null"
                    android:checked="@{viewModel.carInfo.hadOpenTakeOrder()}"
                    android:checked="@{viewModel.hadOpenTakeOrder}"
                    android:text="" />
            </LinearLayout>
            <LinearLayout
                android:id="@+id/unlockLayout"
                show="@{(viewModel.unlockDoorPermissions||viewModel.unlockBoxPermissions)&amp;&amp;!viewModel.carInfo.hadOpenTakeOrder()}"
                show="@{viewModel.couldOperationDevice}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
@@ -236,9 +238,7 @@
                    android:layout_marginHorizontal="@dimen/dp_14"
                    android:layout_marginTop="@dimen/dp_8"
                    android:baselineAligned="false"
                    android:orientation="horizontal"
                    android:visibility="gone"
                    tools:visibility="visible">
                    android:orientation="horizontal">
                    <LinearLayout
                        android:id="@+id/unlockDoor"
app/src/main/res/layout/item_accept_car_point.xml
New file
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_109">
    <ImageView
        android:id="@+id/iv_selected"
        android:layout_width="@dimen/dp_20"
        android:layout_height="@dimen/dp_20"
        android:layout_marginStart="@dimen/dp_20"
        android:src="@mipmap/icon_circle_gray2"
        app:layout_constraintBottom_toBottomOf="@id/iv_picture"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/iv_picture" />
    <ImageView
        android:id="@+id/iv_picture"
        android:layout_width="@dimen/dp_68"
        android:layout_height="@dimen/dp_92"
        android:layout_marginStart="@dimen/dp_48"
        android:layout_marginTop="@dimen/dp_8"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tv_label"
        android:layout_width="@dimen/dp_38"
        android:layout_height="@dimen/dp_18"
        android:layout_marginStart="@dimen/dp_8"
        android:background="@drawable/shape_e5f0fc_bg_2"
        android:gravity="center"
        android:text="默认"
        android:textColor="@color/color_0256ff"
        android:textSize="@dimen/sp_11"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="@id/tv_title"
        app:layout_constraintStart_toEndOf="@id/iv_picture"
        app:layout_constraintTop_toTopOf="@id/tv_title"
        tools:visibility="visible" />
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/dp_4"
        android:layout_marginEnd="@dimen/dp_20"
        android:singleLine="true"
        android:textColor="@color/gray_9"
        android:textSize="@dimen/sp_14"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/tv_label"
        app:layout_constraintTop_toTopOf="@id/iv_picture"
        app:layout_goneMarginStart="@dimen/dp_8"
        tools:text="广州市白云机场T2航站楼" />
    <TextView
        android:id="@+id/tv_detail"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/dp_8"
        android:layout_marginTop="@dimen/dp_4"
        android:layout_marginEnd="@dimen/dp_20"
        android:textColor="@color/color_838fa6"
        android:textSize="@dimen/sp_14"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/iv_picture"
        app:layout_constraintTop_toBottomOf="@id/tv_title"
        tools:text="深圳市宝安区西大街阳光绿色温馨家园17号楼313" />
    <View
        android:id="@+id/v_line"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginStart="@dimen/dp_20"
        android:background="@color/gray_4"
        app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/res/mipmap-xhdpi/icon_circle_gray2.png
app/src/main/res/mipmap-xhdpi/icon_circle_ring_blue.png
common/src/main/res/drawable/shape_white_bg_top_16.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:topLeftRadius="@dimen/dp_16" android:topRightRadius="@dimen/dp_16" />
    <solid android:color="@color/white" />
</shape>