From 632255913b21d02141c794f829da0e9ad3edda9a Mon Sep 17 00:00:00 2001 From: aibingbing Date: Wed, 15 Nov 2023 20:41:45 +0800 Subject: [PATCH 01/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E8=BF=90=E8=90=A5=E9=9D=A2?= =?UTF-8?q?=E6=9D=BF=E5=A2=9E=E5=8A=A0=E8=B0=83=E8=AF=95=E5=BC=80=E5=85=B3?= =?UTF-8?q?=E5=92=8C=E7=9B=B8=E5=85=B3=E8=B0=83=E7=94=A8=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/taxi/ui/base/BaseTaxiTabFragment.kt | 20 ++++++++- .../core/function/hmi/ui/MoGoHmiProvider.kt | 43 ++++++++++++++----- .../function/hmi/ui/setting/SOPSettingView.kt | 35 +++++++++++++++ .../src/main/res/layout/view_sop_setting.xml | 15 ++++++- .../api/hmi/warning/IMoGoHmiProvider.kt | 21 +++++++++ .../function/call/hmi/CallerHmiManager.kt | 36 ++++++++++++++-- .../module/status/IMogoStatusManager.java | 30 +++++++++++++ .../module/status/MogoStatusManager.java | 30 +++++++++++++ .../module/status/StatusDescriptor.java | 17 +++++++- 9 files changed, 228 insertions(+), 19 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt index ff9092412c..39364027fa 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt @@ -11,6 +11,8 @@ import android.view.animation.LinearInterpolator import androidx.fragment.app.FragmentTransaction import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.mogo.commons.AbsMogoApplication +import com.mogo.commons.module.status.MogoStatusManager +import com.mogo.commons.module.status.StatusDescriptor import com.mogo.commons.mvp.IView import com.mogo.commons.mvp.MvpFragment import com.mogo.commons.mvp.Presenter @@ -26,6 +28,7 @@ import com.mogo.eagle.core.function.hmi.ui.widget.ParallelDriveView import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener +import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.map.listener.IMogoMapListener import com.mogo.map.uicontroller.VisualAngleMode @@ -197,9 +200,22 @@ abstract class BaseTaxiTabFragment> : MvpFragment + if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { + UiThreadHandler.post { + module_mogo_och_operation_status.isEnabled = !isTrue + } + } + } taxi_close_navi_icon.setOnClickListener { showAmapNaviToStationFragment(false) @@ -222,13 +238,13 @@ abstract class BaseTaxiTabFragment> : MvpFragment + if(!buttonView.isPressed) return@setOnCheckedChangeListener + if (isChecked) { + if (CallerHmiManager.isTaxiUnmanedDriverPerformTask()) { + ToastUtils.showLong("请先结束当前任务") + buttonView.isChecked = !isChecked + return@setOnCheckedChangeListener + } + if (CallerHmiManager.isTaxiUnmanedDriverTakingOrders()) { + ToastUtils.showLong("请先结束接单状态") + buttonView.isChecked = !isChecked + return@setOnCheckedChangeListener + } + CallerHmiManager.setTaxiUnmanedDriverLineRoutingVerifyMode(true) + } else { + if (CallerHmiManager.isTaxiUnmanedDriverPerformTask()) { + ToastUtils.showLong("请先结束当前任务") + buttonView.isChecked = !isChecked + return@setOnCheckedChangeListener + } + CallerHmiManager.setTaxiUnmanedDriverLineRoutingVerifyMode(false) + } + } + it.isChecked = CallerHmiManager.isTaxiUnmanedDriverLineRoutingVerifyMode() + } else { + it.isEnabled = false + it.visibility = View.GONE + } + } + //是否展示被动触发的录包弹窗(自动驾驶下出现问题触发的录包) scShowBagRecordWindow.isChecked = FunctionBuildConfig.isShowBagRecordWindow scShowBagRecordWindow.setOnCheckedChangeListener { _, isChecked -> diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml index 1a05165d25..b4dd1a06f9 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml @@ -548,6 +548,19 @@ app:layout_constraintRight_toRightOf="@id/otherGuideLine" app:layout_constraintTop_toBottomOf="@id/scIPCReport" /> + + + + app:layout_constraintTop_toBottomOf="@id/scLineRoutingVerify" /> Date: Thu, 16 Nov 2023 21:09:22 +0800 Subject: [PATCH 02/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A02=E7=A7=8D?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E5=88=87=E6=8D=A2=EF=BC=8C=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E8=B7=AF=E7=BA=BF=E9=A1=B5=E9=9D=A2=E7=AD=89=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/AndroidManifest.xml | 8 +- .../bean/TaxiRoutingQueryLineResponse.java | 22 + .../com/mogo/och/taxi/ui/base/TaxiFragment.kt | 56 +- .../routing/TaxiRoutingChooseLineActivity.kt | 137 ++++ .../routing/TaxiRoutingChooseLineAdapter.kt | 80 +++ ...TaxiRoutingChooseLineItemOpenAnimator.java | 641 ++++++++++++++++++ .../taxi/ui/routing/TaxiRoutingFragment.kt | 37 + .../routing_line_task_arrow.png | Bin 0 -> 491 bytes .../routing_choose_line_btn_submit_bg.xml | 5 + ...ting_choose_line_btn_submit_bg_default.xml | 10 + ...ting_choose_line_btn_submit_bg_pressed.xml | 10 + .../drawable/routing_choose_line_close.png | Bin 0 -> 3825 bytes ..._line_shape_select_line_item_bg_normal.xml | 7 + ...ine_shape_select_line_item_bg_selected.xml | 7 + .../res/drawable/routing_click_btn_bg.xml | 5 + .../drawable/routing_click_btn_bg_default.xml | 10 + .../drawable/routing_click_btn_bg_pressed.xml | 10 + .../src/main/res/drawable/taxi_routing_bg.xml | 35 + .../layout/routing_choose_line_activity.xml | 73 ++ .../layout/routing_choose_line_list_item.xml | 51 ++ .../src/main/res/layout/routing_fragment.xml | 275 ++++++++ .../layout/routing_no_data_common_view.xml | 33 + .../src/main/res/values/colors.xml | 7 +- .../src/main/res/values/dimens.xml | 5 +- .../src/main/res/values/strings.xml | 10 + .../src/main/res/values/styles.xml | 21 + .../src/main/res/layout/view_sop_setting.xml | 4 +- 27 files changed, 1546 insertions(+), 13 deletions(-) create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineItemOpenAnimator.java create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_line_task_arrow.png create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_default.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_pressed.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_close.png create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_shape_select_line_item_bg_normal.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_shape_select_line_item_bg_selected.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_default.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_pressed.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_routing_bg.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/routing_no_data_common_view.xml diff --git a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml index fb42392054..3ab0402e38 100644 --- a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml +++ b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml @@ -1,5 +1,9 @@ - - / + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java new file mode 100644 index 0000000000..7c3efdda76 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java @@ -0,0 +1,22 @@ +package com.mogo.och.taxi.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class TaxiRoutingQueryLineResponse extends BaseData { + public List data; + + public static class Result { + public int lineId;//线路id + public String name;//线路名字 + public int todayVerifyNum;//本车今天验证次数 + public int historyVerifyTotalUsableNum;//历史累计验证可用次数 + public int historyVerifyTotalNotUsableNum;//历史累计验证不可用次数 + public boolean isChoosed;//当前是否选中 + } +} diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index 7b83ee52a7..18ecb7806e 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -8,11 +8,13 @@ import android.view.ViewGroup import androidx.fragment.app.FragmentTransaction import com.alibaba.android.arouter.launcher.ARouter import com.mogo.commons.module.status.MogoStatusManager +import com.mogo.commons.module.status.StatusDescriptor import com.mogo.eagle.core.data.temp.EventLogout import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.biz.constant.OchCommonConst import com.mogo.och.common.module.biz.provider.LoginService import com.mogo.och.common.module.utils.FlowBus @@ -21,6 +23,7 @@ import com.mogo.och.taxi.constant.TaxiDriverEventConst import com.mogo.och.taxi.constant.TaxiOrderStatusEnum import com.mogo.och.taxi.network.TaxiDriverLoginImpl import com.mogo.och.taxi.ui.operational.TaxiOperationalDialogFragment +import com.mogo.och.taxi.ui.routing.TaxiRoutingFragment import com.mogo.och.taxi.ui.task.TaxiTaskModel import com.mogo.och.taxi.ui.task.TaxiTaskTabFragment import com.mogo.och.taxi.utils.TPRouteDataTestUtils @@ -45,6 +48,7 @@ class TaxiFragment : BaseTaxiTabFragment(), private var taskTabFragment: WeakReference? = null private var personalDialogFragment: WeakReference? = null + private var routingVerifyFragment: WeakReference? = null private var loginService: LoginService? = null @Subscribe(threadMode = ThreadMode.MAIN) @@ -151,15 +155,53 @@ class TaxiFragment : BaseTaxiTabFragment(), } private fun initFragment() { - taskTabFragment = WeakReference(TaxiTaskTabFragment.newInstance()) + showTaskFragment() + MogoStatusManager.getInstance() + .registerStatusChangedListener( + TAG, StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE + ) { descriptor, isTrue -> + if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { + UiThreadHandler.post { + if (isTrue) { + showRoutingFragment() + } else { + showTaskFragment() + } + } + } + } + } + + private fun showTaskFragment() { val transaction: FragmentTransaction = childFragmentManager.beginTransaction() - //默认显示OCHTaxiServerOrdersFragment - taskTabFragment?.get()?.let { - transaction.add(R.id.fragment_container, it).show( - it - ) + if (routingVerifyFragment?.get()?.isVisible == true) { + routingVerifyFragment?.get()?.also { + transaction.hide(it) + } + } + if (taskTabFragment?.get() == null) { + taskTabFragment = WeakReference(TaxiTaskTabFragment.newInstance()) + } + taskTabFragment?.get()?.also { + transaction.replace(R.id.fragment_container, it).show(it) + transaction.commitAllowingStateLoss() + } + } + + private fun showRoutingFragment() { + val transaction: FragmentTransaction = childFragmentManager.beginTransaction() + if (taskTabFragment?.get()?.isVisible == true) { + taskTabFragment?.get()?.also { + transaction.hide(it) + } + } + if (routingVerifyFragment?.get() == null) { + routingVerifyFragment = WeakReference(TaxiRoutingFragment.newInstance()) + } + routingVerifyFragment?.get()?.also { + transaction.replace(R.id.fragment_container, it).show(it) + transaction.commitAllowingStateLoss() } - transaction.commitAllowingStateLoss() } override fun createPresenter(): TaxiPresenter { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt new file mode 100644 index 0000000000..a23d982b90 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt @@ -0,0 +1,137 @@ +package com.mogo.och.taxi.ui.routing + +import android.graphics.Point +import android.os.Bundle +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.appcompat.app.AppCompatActivity +import androidx.recyclerview.widget.LinearLayoutManager +import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.taxi.R +import com.mogo.och.taxi.bean.TaxiRoutingQueryLineResponse +import kotlinx.android.synthetic.main.routing_choose_line_activity.btnChooseLineSubmit +import kotlinx.android.synthetic.main.routing_choose_line_activity.btnClose +import kotlinx.android.synthetic.main.routing_choose_line_activity.chooseLineListView +import kotlinx.android.synthetic.main.routing_no_data_common_view.noDataContainer +import kotlinx.android.synthetic.main.taxi_debug_order.currentLineId + +class TaxiRoutingChooseLineActivity : AppCompatActivity() { + + companion object { + const val TAG = "TaxiRoutingChooseLineActivity" + } + + private lateinit var mChooseLineListAdapter: TaxiRoutingChooseLineAdapter + private lateinit var mLinearLayoutManager: LinearLayoutManager + private val mRoutingLineList: MutableList = ArrayList() + private var mCurrentChoosedLineId: Int? = -1 + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.routing_choose_line_activity) + initWindowParams() + initView() + loadData() + } + + private fun initWindowParams() { + val window = window + val params = window.attributes + val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager + val point = Point() + windowManager.defaultDisplay.getSize(point) //用于获取屏幕高度 + params.width = (point.x * 0.375).toInt() + params.height = ViewGroup.LayoutParams.MATCH_PARENT + window.attributes = params + window.setGravity(Gravity.START or Gravity.BOTTOM) + } + + private fun initView() { + mLinearLayoutManager = LinearLayoutManager(this) + chooseLineListView.layoutManager = mLinearLayoutManager + chooseLineListView.itemAnimator = + TaxiRoutingChooseLineItemOpenAnimator() + mChooseLineListAdapter = TaxiRoutingChooseLineAdapter(applicationContext, mRoutingLineList) + chooseLineListView.addItemDecoration(SpacesItemDecoration(4)) + chooseLineListView.adapter = mChooseLineListAdapter + //设置item 点击事件 + mChooseLineListAdapter.setOnLineItemClickListener(object : + TaxiRoutingChooseLineAdapter.OnChooseLineItemClickListener { + override fun onItemClick(position: Int, close: Boolean) { + mCurrentChoosedLineId = mRoutingLineList[position].lineId + } + }) + + btnClose.setOnClickListener { + finish() + } + btnChooseLineSubmit.setOnClickListener { + if (mCurrentChoosedLineId == -1) { + ToastUtils.showLong("请先选择任务") + return@setOnClickListener + } + ToastUtils.showLong("当前选择的路线LineId:$currentLineId") + } + } + + private fun showEmptyView() { + chooseLineListView.visibility = View.GONE + btnChooseLineSubmit.visibility = View.GONE + noDataContainer.visibility = View.VISIBLE + } + + private fun showRecyclerView() { + chooseLineListView.visibility = View.VISIBLE + btnChooseLineSubmit.visibility = View.VISIBLE + noDataContainer.visibility = View.GONE + } + + /** + * 初始化数据 + */ + private fun loadData() { + //TODO + for (i in 1..10) { + val result = TaxiRoutingQueryLineResponse.Result() + result.lineId = i + result.name = "路线名称$i" + result.todayVerifyNum = 2 + result.historyVerifyTotalUsableNum = 5 + result.historyVerifyTotalNotUsableNum = 1 + result.isChoosed = false + mRoutingLineList.add(result) + } + if (mRoutingLineList.isEmpty()) { + showEmptyView() + } else { + showRecyclerView() + mChooseLineListAdapter.notifyDataSetChanged() + } + } + + fun onRoutingLineDataChanged(data: TaxiRoutingQueryLineResponse?) { + if (data?.data?.isNotEmpty() == true) { + showRecyclerView() + mRoutingLineList.clear() + mRoutingLineList.addAll(data.data) + mChooseLineListAdapter.notifyDataSetChanged() + } else { + showEmptyView() + } + } + + fun onChangeLineIdSuccess() { + //ToastUtils.showLong(resources.getString(R.string.bus_change_line_commit_tip_s)) + //mPresenter?.queryBusRoutes() + mChooseLineListAdapter.setOnLineItemClickListener(null) + //mPresenter?.removeListener() + finish() + } + + override fun onDestroy() { + super.onDestroy() + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt new file mode 100644 index 0000000000..ae513a83d3 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt @@ -0,0 +1,80 @@ +package com.mogo.och.taxi.ui.routing + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.widget.AppCompatTextView +import androidx.recyclerview.widget.RecyclerView +import com.mogo.och.taxi.R +import com.mogo.och.taxi.bean.TaxiRoutingQueryLineResponse + +class TaxiRoutingChooseLineAdapter( + private val mContext: Context, + private val mData: List +) : RecyclerView.Adapter() { + + companion object { + const val TAG = "TaxiRoutingChooseLineAdapter" + } + + private var mItemClickListener: OnChooseLineItemClickListener? = null + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SwitchLineViewHolder { + val view = LayoutInflater.from(mContext).inflate( + R.layout.routing_choose_line_list_item, parent, false + ) + return SwitchLineViewHolder(view) + } + + override fun onBindViewHolder(holder: SwitchLineViewHolder, position: Int) { + val currentPosition = holder.bindingAdapterPosition + val data = mData[currentPosition] + holder.lineNameTextView.text = data.name + holder.todayVerifyNumTextView.text = "本车今日已验证:${data.todayVerifyNum}次" + holder.historyVerifyNumTextView.text = + "路线累计反馈${data.historyVerifyTotalUsableNum}可用,${data.historyVerifyTotalNotUsableNum}不可用" + if (data.isChoosed) { + holder.itemView.setBackgroundResource(R.drawable.routing_choose_line_shape_select_line_item_bg_selected) + } else { + holder.itemView.setBackgroundResource(R.drawable.routing_choose_line_shape_select_line_item_bg_normal) + } + + //设置item点击事件 + holder.itemView.setOnClickListener { + mData.forEachIndexed { index, result -> + if (result.isChoosed) { + result.isChoosed = false + + } + } + mData[currentPosition].isChoosed = true + notifyItemChanged(currentPosition) + mItemClickListener?.onItemClick(currentPosition, false) + } + } + + override fun getItemCount(): Int { + return mData.size + } + + fun setOnLineItemClickListener(itemClickListener: OnChooseLineItemClickListener?) { + mItemClickListener = itemClickListener + } + + interface OnChooseLineItemClickListener { + fun onItemClick(position: Int, close: Boolean) + } + + class SwitchLineViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val lineNameTextView: AppCompatTextView//线路名称 + val todayVerifyNumTextView: AppCompatTextView //本车今天验证次数 + val historyVerifyNumTextView: AppCompatTextView //路线累计验证次数 + + init { + lineNameTextView = itemView.findViewById(R.id.switchLineNameTextView) + todayVerifyNumTextView = itemView.findViewById(R.id.todayVerifyNumTextView) + historyVerifyNumTextView = itemView.findViewById(R.id.historyVerifyNumTextView) + } + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineItemOpenAnimator.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineItemOpenAnimator.java new file mode 100644 index 0000000000..323ec5e83a --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineItemOpenAnimator.java @@ -0,0 +1,641 @@ +package com.mogo.och.taxi.ui.routing; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.view.View; +import android.view.ViewPropertyAnimator; + +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +/** + * This implementation of {@link RecyclerView.ItemAnimator} provides basic + * animations on remove, add, and move events that happen to the items in + * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. + * + * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) + */ +public class TaxiRoutingChooseLineItemOpenAnimator extends DefaultItemAnimator { + private static final boolean DEBUG = false; + private static TimeInterpolator sDefaultInterpolator; + private final ArrayList mPendingRemovals = new ArrayList<>(); + private final ArrayList mPendingAdditions = new ArrayList<>(); + private final ArrayList mPendingMoves = new ArrayList<>(); + private final ArrayList mPendingChanges = new ArrayList<>(); + private final ArrayList> mAdditionsList = new ArrayList<>(); + private final ArrayList> mMovesList = new ArrayList<>(); + private final ArrayList> mChangesList = new ArrayList<>(); + private final ArrayList mAddAnimations = new ArrayList<>(); + private final ArrayList mMoveAnimations = new ArrayList<>(); + private final ArrayList mRemoveAnimations = new ArrayList<>(); + private final ArrayList mChangeAnimations = new ArrayList<>(); + + private static class MoveInfo { + public RecyclerView.ViewHolder holder; + public int fromX, fromY, toX, toY; + + MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { + this.holder = holder; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + } + + private static class ChangeInfo { + public RecyclerView.ViewHolder oldHolder, newHolder; + public int fromX, fromY, toX, toY; + + private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) { + this.oldHolder = oldHolder; + this.newHolder = newHolder; + } + + ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + this(oldHolder, newHolder); + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + + @Override + public String toString() { + return "ChangeInfo{" + + "oldHolder=" + oldHolder + + ", newHolder=" + newHolder + + ", fromX=" + fromX + + ", fromY=" + fromY + + ", toX=" + toX + + ", toY=" + toY + + '}'; + } + } + + @Override + public void runPendingAnimations() { + boolean removalsPending = !mPendingRemovals.isEmpty(); + boolean movesPending = !mPendingMoves.isEmpty(); + boolean changesPending = !mPendingChanges.isEmpty(); + boolean additionsPending = !mPendingAdditions.isEmpty(); + if (!removalsPending && !movesPending && !additionsPending && !changesPending) { + // nothing to animate + return; + } + // First, remove stuff + for (RecyclerView.ViewHolder holder : mPendingRemovals) { + animateRemoveImpl(holder); + } + mPendingRemovals.clear(); + // Next, move stuff + if (movesPending) { + final ArrayList moves = new ArrayList<>(mPendingMoves); + mMovesList.add(moves); + mPendingMoves.clear(); + Runnable mover = () -> { + for (MoveInfo moveInfo : moves) { + animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, + moveInfo.toX, moveInfo.toY); + } + moves.clear(); + mMovesList.remove(moves); + }; + if (removalsPending) { + View view = moves.get(0).holder.itemView; + ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); + } else { + mover.run(); + } + } + // Next, change stuff, to run in parallel with move animations + if (changesPending) { + final ArrayList changes = new ArrayList<>(mPendingChanges); + mChangesList.add(changes); + mPendingChanges.clear(); + Runnable changer = () -> { + for (ChangeInfo change : changes) { + animateChangeImpl(change); + } + changes.clear(); + mChangesList.remove(changes); + }; + if (removalsPending) { + RecyclerView.ViewHolder holder = changes.get(0).oldHolder; + ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); + } else { + changer.run(); + } + } + // Next, add stuff + if (additionsPending) { + final ArrayList additions = new ArrayList<>(mPendingAdditions); + mAdditionsList.add(additions); + mPendingAdditions.clear(); + Runnable adder = () -> { + for (RecyclerView.ViewHolder holder : additions) { + animateAddImpl(holder); + } + additions.clear(); + mAdditionsList.remove(additions); + }; + if (removalsPending || movesPending || changesPending) { + long removeDuration = removalsPending ? getRemoveDuration() : 0; + long moveDuration = movesPending ? getMoveDuration() : 0; + long changeDuration = changesPending ? getChangeDuration() : 0; + long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); + View view = additions.get(0).itemView; + ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); + } else { + adder.run(); + } + } + } + + @Override + public boolean animateRemove(final RecyclerView.ViewHolder holder) { + resetAnimation(holder); + mPendingRemovals.add(holder); + return true; + } + + private void animateRemoveImpl(final RecyclerView.ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mRemoveAnimations.add(holder); + animation.setDuration(getRemoveDuration()).alpha(0).setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchRemoveStarting(holder); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + view.setAlpha(1); + dispatchRemoveFinished(holder); + mRemoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateAdd(final RecyclerView.ViewHolder holder) { + resetAnimation(holder); + holder.itemView.setAlpha(0); + mPendingAdditions.add(holder); + return true; + } + + void animateAddImpl(final RecyclerView.ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mAddAnimations.add(holder); + animation.alpha(1).setDuration(getAddDuration()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchAddStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + view.setAlpha(1); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchAddFinished(holder); + mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY, + int toX, int toY) { + final View view = holder.itemView; + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + return true; + } + + void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + final int deltaX = toX - fromX; + final int deltaY = toY - fromY; + if (deltaX != 0) { + view.animate().translationX(0); + } + if (deltaY != 0) { + view.animate().translationY(0); + } + // TODO: make EndActions end listeners instead, since end actions aren't called when + // vpas are canceled (and can't end them. why?) + // need listener functionality in VPACompat for this. Ick. + final ViewPropertyAnimator animation = view.animate(); + mMoveAnimations.add(holder); + animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchMoveStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + if (deltaX != 0) { + view.setTranslationX(0); + } + if (deltaY != 0) { + view.setTranslationY(0); + } + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchMoveFinished(holder); + mMoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + if (oldHolder == newHolder) { + // Don't know how to run change animations when the same view holder is re-used. + // run a move animation to handle position changes. + return animateMove(oldHolder, fromX, fromY, toX, toY); + } + final float prevTranslationX = oldHolder.itemView.getTranslationX(); + final float prevTranslationY = oldHolder.itemView.getTranslationY(); + final float prevAlpha = oldHolder.itemView.getAlpha(); + resetAnimation(oldHolder); + int deltaX = (int) (toX - fromX - prevTranslationX); + int deltaY = (int) (toY - fromY - prevTranslationY); + // recover prev translation state after ending animation + oldHolder.itemView.setTranslationX(prevTranslationX); + oldHolder.itemView.setTranslationY(prevTranslationY); + oldHolder.itemView.setAlpha(prevAlpha); + if (newHolder != null) { + // carry over translation values + resetAnimation(newHolder); + newHolder.itemView.setTranslationX(-deltaX); + newHolder.itemView.setTranslationY(-deltaY); + newHolder.itemView.setAlpha(0); + } + mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + return true; + } + + void animateChangeImpl(final ChangeInfo changeInfo) { + final RecyclerView.ViewHolder holder = changeInfo.oldHolder; + final View view = holder == null ? null : holder.itemView; + final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; + final View newView = newHolder != null ? newHolder.itemView : null; + if (view != null) { + final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( + getChangeDuration()); + mChangeAnimations.add(changeInfo.oldHolder); + oldViewAnim.translationX((float) (changeInfo.toX - changeInfo.fromX)); + oldViewAnim.translationY((float) (changeInfo.toY - changeInfo.fromY)); + oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.oldHolder, true); + } + + @Override + public void onAnimationEnd(Animator animator) { + oldViewAnim.setListener(null); + view.setAlpha(1); + view.setTranslationX(0); + view.setTranslationY(0); + dispatchChangeFinished(changeInfo.oldHolder, true); + mChangeAnimations.remove(changeInfo.oldHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + if (newView != null) { + final ViewPropertyAnimator newViewAnimation = newView.animate(); + mChangeAnimations.add(changeInfo.newHolder); + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) + .alpha(1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.newHolder, false); + } + + @Override + public void onAnimationEnd(Animator animator) { + newViewAnimation.setListener(null); + newView.setAlpha(1); + newView.setTranslationX(0); + newView.setTranslationY(0); + dispatchChangeFinished(changeInfo.newHolder, false); + mChangeAnimations.remove(changeInfo.newHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + } + + private void endChangeAnimation(List infoList, RecyclerView.ViewHolder item) { + for (int i = infoList.size() - 1; i >= 0; i--) { + ChangeInfo changeInfo = infoList.get(i); + if (endChangeAnimationIfNecessary(changeInfo, item)) { + if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { + infoList.remove(changeInfo); + } + } + } + } + + private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { + if (changeInfo.oldHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); + } + if (changeInfo.newHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); + } + } + + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) { + boolean oldItem = false; + if (changeInfo.newHolder == item) { + changeInfo.newHolder = null; + } else if (changeInfo.oldHolder == item) { + changeInfo.oldHolder = null; + oldItem = true; + } else { + return false; + } + item.itemView.setAlpha(1); + item.itemView.setTranslationX(0); + item.itemView.setTranslationY(0); + dispatchChangeFinished(item, oldItem); + return true; + } + + @Override + public void endAnimation(RecyclerView.ViewHolder item) { + final View view = item.itemView; + // this will trigger end callback which should set properties to their target values. + view.animate().cancel(); + // TODO if some other animations are chained to end, how do we cancel them as well? + for (int i = mPendingMoves.size() - 1; i >= 0; i--) { + MoveInfo moveInfo = mPendingMoves.get(i); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + mPendingMoves.remove(i); + } + } + endChangeAnimation(mPendingChanges, item); + if (mPendingRemovals.remove(item)) { + view.setAlpha(1); + dispatchRemoveFinished(item); + } + if (mPendingAdditions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + } + + for (int i = mChangesList.size() - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + endChangeAnimation(changes, item); + if (changes.isEmpty()) { + mChangesList.remove(i); + } + } + for (int i = mMovesList.size() - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + for (int j = moves.size() - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(i); + } + break; + } + } + } + for (int i = mAdditionsList.size() - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + if (additions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + if (additions.isEmpty()) { + mAdditionsList.remove(i); + } + } + } + + // animations should be ended by the cancel above. + //noinspection Pointless BooleanExpression,ConstantConditions + if (mRemoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mRemoveAnimations list"); + } + + //noinspection Pointless BooleanExpression,ConstantConditions + if (mAddAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mAddAnimations list"); + } + + //noinspection Pointless BooleanExpression,ConstantConditions + if (mChangeAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mChangeAnimations list"); + } + + //noinspection Pointless BooleanExpression,ConstantConditions + if (mMoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mMoveAnimations list"); + } + dispatchFinishedWhenDone(); + } + + private void resetAnimation(RecyclerView.ViewHolder holder) { + if (sDefaultInterpolator == null) { + sDefaultInterpolator = new ValueAnimator().getInterpolator(); + } + holder.itemView.animate().setInterpolator(sDefaultInterpolator); + endAnimation(holder); + } + + @Override + public boolean isRunning() { + return (!mPendingAdditions.isEmpty() + || !mPendingChanges.isEmpty() + || !mPendingMoves.isEmpty() + || !mPendingRemovals.isEmpty() + || !mMoveAnimations.isEmpty() + || !mRemoveAnimations.isEmpty() + || !mAddAnimations.isEmpty() + || !mChangeAnimations.isEmpty() + || !mMovesList.isEmpty() + || !mAdditionsList.isEmpty() + || !mChangesList.isEmpty()); + } + + /** + * Check the state of currently pending and running animations. If there are none + * pending/running, call {@link #dispatchAnimationsFinished()} to notify any + * listeners. + */ + void dispatchFinishedWhenDone() { + if (!isRunning()) { + dispatchAnimationsFinished(); + } + } + + @Override + public void endAnimations() { + int count = mPendingMoves.size(); + for (int i = count - 1; i >= 0; i--) { + MoveInfo item = mPendingMoves.get(i); + View view = item.holder.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item.holder); + mPendingMoves.remove(i); + } + count = mPendingRemovals.size(); + for (int i = count - 1; i >= 0; i--) { + RecyclerView.ViewHolder item = mPendingRemovals.get(i); + dispatchRemoveFinished(item); + mPendingRemovals.remove(i); + } + count = mPendingAdditions.size(); + for (int i = count - 1; i >= 0; i--) { + RecyclerView.ViewHolder item = mPendingAdditions.get(i); + item.itemView.setAlpha(1); + dispatchAddFinished(item); + mPendingAdditions.remove(i); + } + count = mPendingChanges.size(); + for (int i = count - 1; i >= 0; i--) { + endChangeAnimationIfNecessary(mPendingChanges.get(i)); + } + mPendingChanges.clear(); + if (!isRunning()) { + return; + } + + int listCount = mMovesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + count = moves.size(); + for (int j = count - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + RecyclerView.ViewHolder item = moveInfo.holder; + View view = item.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(moveInfo.holder); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(moves); + } + } + } + listCount = mAdditionsList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + count = additions.size(); + for (int j = count - 1; j >= 0; j--) { + RecyclerView.ViewHolder item = additions.get(j); + View view = item.itemView; + view.setAlpha(1); + dispatchAddFinished(item); + additions.remove(j); + if (additions.isEmpty()) { + mAdditionsList.remove(additions); + } + } + } + listCount = mChangesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + count = changes.size(); + for (int j = count - 1; j >= 0; j--) { + endChangeAnimationIfNecessary(changes.get(j)); + if (changes.isEmpty()) { + mChangesList.remove(changes); + } + } + } + + cancelAll(mRemoveAnimations); + cancelAll(mMoveAnimations); + cancelAll(mAddAnimations); + cancelAll(mChangeAnimations); + + dispatchAnimationsFinished(); + } + + void cancelAll(List viewHolders) { + for (int i = viewHolders.size() - 1; i >= 0; i--) { + viewHolders.get(i).itemView.animate().cancel(); + } + } + + /** + * {@inheritDoc} + *

+ * If the payload list is not empty, DefaultItemAnimator returns true. + * When this is the case: + *

    + *
  • If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both + * ViewHolder arguments will be the same instance. + *
  • + *
  • + * If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, + * then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and + * run a move animation instead. + *
  • + *
+ */ + @Override + public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, + @NonNull List payloads) { + return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt new file mode 100644 index 0000000000..b209267f14 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -0,0 +1,37 @@ +package com.mogo.och.taxi.ui.routing + +import android.content.Intent +import android.os.Bundle +import com.mogo.commons.mvp.BaseFragment +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.taxi.R +import kotlinx.android.synthetic.main.routing_fragment.btnChooseTask + +class TaxiRoutingFragment : BaseFragment() { + + companion object { + const val TAG = SceneConstant.M_TAXI + "RoutingFragment" + + fun newInstance(): TaxiRoutingFragment { + val args = Bundle() + val fragment = TaxiRoutingFragment() + fragment.arguments = args + return fragment + } + } + + override fun getLayoutId(): Int { + return R.layout.routing_fragment + } + + override fun getTagName(): String { + return "RoutingFragment" + } + + override fun initViews() { + btnChooseTask.setOnClickListener { + val intent = Intent(context, TaxiRoutingChooseLineActivity::class.java) + startActivity(intent) + } + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_line_task_arrow.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_line_task_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..b32f0693a6bd437f6e1c5e6039e9f9ef092dcaa3 GIT binary patch literal 491 zcmeAS@N?(olHy`uVBq!ia0vp^!a%IV!3HGvmOVNGq!^2X+?^QKos)S9xJU2c1fa4|PZ!4! z58k!YZhJX7inQtOUB6p{=W{@cUAzAS=}KLeMwW#gi(Icr|4^Bzv9xm6`=D+2oAgo) zCv8p>`?KNttCez^+OPBCOQV(s$U*6*hMs&A9%+1V6SKe zcg{lwvo!~dHcVxX*v_PV;2PHsMf>mbuP)QG@cHvgmP=ku;3tFklEd$rAM_cUGQ=+a z;K}VW?K02H57B-*xHW1PGIwrfWjwWz^U}pd1wZ249$VZtTTsjHHNCujy@=Ft%U29< zty|_-J}>7;exV?{UgVF%rfG&RyH87-UOwuY5GwNA>+AL1!VL$f@71j;wf^om OKzq9SxvX + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_default.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_default.xml new file mode 100644 index 0000000000..e94992d507 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_default.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_pressed.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_pressed.xml new file mode 100644 index 0000000000..975ed9780c --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_btn_submit_bg_pressed.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_close.png b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_close.png new file mode 100644 index 0000000000000000000000000000000000000000..370b61de38f35e5da73f6c3a98eeebc45b0bbeea GIT binary patch literal 3825 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 + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_shape_select_line_item_bg_selected.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_shape_select_line_item_bg_selected.xml new file mode 100644 index 0000000000..e5faafb27b --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_choose_line_shape_select_line_item_bg_selected.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg.xml new file mode 100644 index 0000000000..ff04ae2b6d --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_default.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_default.xml new file mode 100644 index 0000000000..6c763666ea --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_default.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_pressed.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_pressed.xml new file mode 100644 index 0000000000..3abd919e23 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_click_btn_bg_pressed.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_routing_bg.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_routing_bg.xml new file mode 100644 index 0000000000..f5efecaa11 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_routing_bg.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml new file mode 100644 index 0000000000..a3acc88b8a --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml new file mode 100644 index 0000000000..d0dd1cbcb5 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml @@ -0,0 +1,51 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml new file mode 100644 index 0000000000..4067a4c542 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_no_data_common_view.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_no_data_common_view.xml new file mode 100644 index 0000000000..434d9ad890 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_no_data_common_view.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/values/colors.xml b/OCH/taxi/unmanned-driver/src/main/res/values/colors.xml index aa93f0eeaa..e57d0be01c 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/values/colors.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/values/colors.xml @@ -28,5 +28,10 @@ #CAD6FF #00FFF8 #1D5EF3 - + #1D5EF3 + #801D5EF3 + #F7151D41 + #2966EC + #CCB9C3E9 + #4Dffffff \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/values/dimens.xml b/OCH/taxi/unmanned-driver/src/main/res/values/dimens.xml index 22d65210b4..2e8093ba90 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/values/dimens.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/values/dimens.xml @@ -117,6 +117,9 @@ 60dp 34dp - 1000dp + 934dp + 46dp + 50dp + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml b/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml index ce60468f17..d5ee38fc76 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml @@ -60,5 +60,15 @@ 查看 + 选择任务 + 任务列表 + 确认 + 暂无任务 + 选择时间 + 路线: + 起点: + 终点: + 往%1$s方向 + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/values/styles.xml b/OCH/taxi/unmanned-driver/src/main/res/values/styles.xml index 4dc523b396..f9764de193 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/values/styles.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/values/styles.xml @@ -23,4 +23,25 @@ + + \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml index b4dd1a06f9..5a584f262c 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_sop_setting.xml @@ -557,9 +557,9 @@ android:scaleX="1.2" android:scaleY="1.2" android:text="自主算路验证模式" - app:layout_constraintLeft_toLeftOf="@id/otherGuideLine" + app:layout_constraintLeft_toRightOf="@id/scShowBagRecordWindow" app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toBottomOf="@id/scShowBagRecordWindow" /> + app:layout_constraintTop_toBottomOf="@id/scIPCReport" /> Date: Fri, 17 Nov 2023 19:52:49 +0800 Subject: [PATCH 03/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E8=B7=AF=E7=BA=BF=E9=A1=B5=E9=9D=A2=EF=BC=8C=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=80=89=E4=B8=AD=EF=BC=8Cloading=EF=BC=8C=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E5=B1=95=E7=A4=BA=E4=BB=BB=E5=8A=A1=EF=BC=8C=E4=B8=8B?= =?UTF-8?q?=E6=96=B9=E6=8C=89=E9=92=AE=E5=B1=95=E7=A4=BA=E7=AD=89=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/AndroidManifest.xml | 2 +- .../taxi/constant/TaxiDriverEventConst.java | 4 + .../routing/TaxiRoutingChooseLineAdapter.kt | 18 ++- ...ty.kt => TaxiRoutingChooseTaskActivity.kt} | 46 +++--- .../taxi/ui/routing/TaxiRoutingFragment.kt | 63 ++++++++- .../ui/routing/TaxiRoutingLoadingDialog.kt | 73 ++++++++++ .../routing_btn_left_default.png | Bin 0 -> 38605 bytes .../routing_btn_left_pressed.png | Bin 0 -> 34649 bytes .../routing_btn_right_default.png | Bin 0 -> 24238 bytes .../routing_btn_right_pressed.png | Bin 0 -> 23950 bytes .../drawable-xhdpi/routing_loading_nor.png | Bin 0 -> 2221 bytes .../drawable/routing_btn_bg_finish_task.xml | 5 + .../drawable/routing_btn_bg_submit_issue.xml | 5 + .../res/layout/dialog_routing_loading.xml | 22 +++ .../layout/routing_choose_line_list_item.xml | 41 +++--- ...y.xml => routing_choose_task_activity.xml} | 4 +- .../src/main/res/layout/routing_fragment.xml | 131 +++++++++--------- .../src/main/res/values/strings.xml | 1 + 18 files changed, 302 insertions(+), 113 deletions(-) rename OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/{TaxiRoutingChooseLineActivity.kt => TaxiRoutingChooseTaskActivity.kt} (74%) create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingLoadingDialog.kt create mode 100755 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_default.png create mode 100755 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_pressed.png create mode 100755 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_right_default.png create mode 100755 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_right_pressed.png create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_loading_nor.png create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_finish_task.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_submit_issue.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_loading.xml rename OCH/taxi/unmanned-driver/src/main/res/layout/{routing_choose_line_activity.xml => routing_choose_task_activity.xml} (95%) diff --git a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml index 3ab0402e38..a7808094c9 100644 --- a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml +++ b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java index f2dc8a3cff..e7bb8bdc2f 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java @@ -13,4 +13,8 @@ public interface TaxiDriverEventConst { String EVENT_TYPE_SHOW_RED_POINT = "event_type_tab_fragment_show_red_point"; String EVENT_TYPE_TASK_WITH_ORDER_CHANGED = "event_type_tab_fragment_task_with_order_changed"; } + + interface RoutingActivityEvent { + String EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID = "event_type_get_chosen_line_task_id"; + } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt index ae513a83d3..4514478d16 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt @@ -1,6 +1,7 @@ package com.mogo.och.taxi.ui.routing import android.content.Context +import android.graphics.Color import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -19,6 +20,7 @@ class TaxiRoutingChooseLineAdapter( } private var mItemClickListener: OnChooseLineItemClickListener? = null + private var mLastChoosedLineIndex = -1 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SwitchLineViewHolder { val view = LayoutInflater.from(mContext).inflate( @@ -37,20 +39,24 @@ class TaxiRoutingChooseLineAdapter( if (data.isChoosed) { holder.itemView.setBackgroundResource(R.drawable.routing_choose_line_shape_select_line_item_bg_selected) } else { - holder.itemView.setBackgroundResource(R.drawable.routing_choose_line_shape_select_line_item_bg_normal) + holder.itemView.setBackgroundColor(Color.parseColor("#162761")) } //设置item点击事件 holder.itemView.setOnClickListener { mData.forEachIndexed { index, result -> - if (result.isChoosed) { + if (result.isChoosed && index != currentPosition) { result.isChoosed = false - + notifyItemChanged(index) } } - mData[currentPosition].isChoosed = true + mData[currentPosition].isChoosed = currentPosition != mLastChoosedLineIndex notifyItemChanged(currentPosition) - mItemClickListener?.onItemClick(currentPosition, false) + mItemClickListener?.onItemClick( + currentPosition, + currentPosition != mLastChoosedLineIndex + ) + mLastChoosedLineIndex = currentPosition } } @@ -63,7 +69,7 @@ class TaxiRoutingChooseLineAdapter( } interface OnChooseLineItemClickListener { - fun onItemClick(position: Int, close: Boolean) + fun onItemClick(position: Int, isChoosed: Boolean) } class SwitchLineViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt similarity index 74% rename from OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt rename to OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt index a23d982b90..1a43045ead 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt @@ -7,31 +7,39 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R import com.mogo.och.taxi.bean.TaxiRoutingQueryLineResponse -import kotlinx.android.synthetic.main.routing_choose_line_activity.btnChooseLineSubmit -import kotlinx.android.synthetic.main.routing_choose_line_activity.btnClose -import kotlinx.android.synthetic.main.routing_choose_line_activity.chooseLineListView +import com.mogo.och.taxi.constant.TaxiDriverEventConst +import kotlinx.android.synthetic.main.routing_choose_task_activity.btnChooseLineSubmit +import kotlinx.android.synthetic.main.routing_choose_task_activity.btnClose +import kotlinx.android.synthetic.main.routing_choose_task_activity.chooseLineListView import kotlinx.android.synthetic.main.routing_no_data_common_view.noDataContainer -import kotlinx.android.synthetic.main.taxi_debug_order.currentLineId -class TaxiRoutingChooseLineActivity : AppCompatActivity() { +class TaxiRoutingChooseTaskActivity : AppCompatActivity() { companion object { - const val TAG = "TaxiRoutingChooseLineActivity" + const val TAG = "TaxiRoutingChooseTaskActivity" } + private val mLoadingDialog: TaxiRoutingLoadingDialog by lazy { + TaxiRoutingLoadingDialog( + this + ) + } private lateinit var mChooseLineListAdapter: TaxiRoutingChooseLineAdapter private lateinit var mLinearLayoutManager: LinearLayoutManager private val mRoutingLineList: MutableList = ArrayList() - private var mCurrentChoosedLineId: Int? = -1 + private var mCurrentChosenLineId: Int? = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.routing_choose_line_activity) + setContentView(R.layout.routing_choose_task_activity) initWindowParams() initView() loadData() @@ -61,7 +69,7 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { mChooseLineListAdapter.setOnLineItemClickListener(object : TaxiRoutingChooseLineAdapter.OnChooseLineItemClickListener { override fun onItemClick(position: Int, close: Boolean) { - mCurrentChoosedLineId = mRoutingLineList[position].lineId + mCurrentChosenLineId = mRoutingLineList[position].lineId } }) @@ -69,11 +77,19 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { finish() } btnChooseLineSubmit.setOnClickListener { - if (mCurrentChoosedLineId == -1) { + if (mCurrentChosenLineId == -1) { ToastUtils.showLong("请先选择任务") return@setOnClickListener } - ToastUtils.showLong("当前选择的路线LineId:$currentLineId") + ToastUtils.showLong("当前选择的路线LineId:$mCurrentChosenLineId") + mLoadingDialog.showLoading() + UiThreadHandler.postDelayed({ + mLoadingDialog.hideLoading() + FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) + .post(this.lifecycleScope, 1000) + mChooseLineListAdapter.setOnLineItemClickListener(null) + finish() + }, 3000L) } } @@ -123,14 +139,6 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { } } - fun onChangeLineIdSuccess() { - //ToastUtils.showLong(resources.getString(R.string.bus_change_line_commit_tip_s)) - //mPresenter?.queryBusRoutes() - mChooseLineListAdapter.setOnLineItemClickListener(null) - //mPresenter?.removeListener() - finish() - } - override fun onDestroy() { super.onDestroy() } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index b209267f14..22c90c21fe 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -2,10 +2,22 @@ package com.mogo.och.taxi.ui.routing import android.content.Intent import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import com.mogo.commons.mvp.BaseFragment import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R +import com.mogo.och.taxi.constant.TaxiDriverEventConst import kotlinx.android.synthetic.main.routing_fragment.btnChooseTask +import kotlinx.android.synthetic.main.routing_fragment.btnStartTask +import kotlinx.android.synthetic.main.routing_fragment.finishSubmitIssueGroup +import kotlinx.android.synthetic.main.routing_fragment.headerTitleContainer +import kotlinx.android.synthetic.main.routing_fragment.mCurrentTaskLayout +import kotlinx.android.synthetic.main.routing_fragment.noDataContainer +import kotlinx.android.synthetic.main.routing_fragment.taskTitleTv class TaxiRoutingFragment : BaseFragment() { @@ -30,8 +42,57 @@ class TaxiRoutingFragment : BaseFragment() { override fun initViews() { btnChooseTask.setOnClickListener { - val intent = Intent(context, TaxiRoutingChooseLineActivity::class.java) + val intent = Intent(context, TaxiRoutingChooseTaskActivity::class.java) startActivity(intent) } + showChooseTaskView() + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + initEventBus() + return super.onCreateView(inflater, container, savedInstanceState) + } + + private fun initEventBus() { + FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) + .register(this) { taskId -> + ToastUtils.showLong("接收到taskId:$taskId") + showCurrentLineTaskContentView() + } + } + + private fun showChooseTaskView() { + noDataContainer.visibility = View.VISIBLE + mCurrentTaskLayout.visibility = View.GONE + headerTitleContainer.visibility = View.GONE + + btnChooseTask.visibility = View.VISIBLE + btnStartTask.visibility = View.GONE + finishSubmitIssueGroup.visibility = View.GONE + } + + private fun showCurrentLineTaskContentView() { + noDataContainer.visibility = View.GONE + mCurrentTaskLayout.visibility = View.VISIBLE + + headerTitleContainer.visibility = View.VISIBLE + taskTitleTv.text = "测试任务测试任务" + + btnChooseTask.visibility = View.GONE + btnStartTask.visibility = View.VISIBLE + btnStartTask.setOnClickListener { + showFinishTaskView() + } + finishSubmitIssueGroup.visibility = View.GONE + } + + private fun showFinishTaskView() { + btnChooseTask.visibility = View.GONE + btnStartTask.visibility = View.GONE + finishSubmitIssueGroup.visibility = View.VISIBLE } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingLoadingDialog.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingLoadingDialog.kt new file mode 100644 index 0000000000..2b7c726e84 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingLoadingDialog.kt @@ -0,0 +1,73 @@ +package com.mogo.och.taxi.ui.routing + +import android.animation.ObjectAnimator +import android.content.Context +import android.view.animation.LinearInterpolator +import androidx.lifecycle.LifecycleObserver +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.taxi.R +import kotlinx.android.synthetic.main.dialog_routing_loading.dialog_loading_text +import kotlinx.android.synthetic.main.dialog_routing_loading.dialog_loading_view + +/** + * loading + */ +class TaxiRoutingLoadingDialog : BaseFloatDialog, LifecycleObserver { + private var objectAnimator: ObjectAnimator? = null + private val mLoadingView by lazy { dialog_loading_view } + private val mLoadingText by lazy { dialog_loading_text } + private var mRunnable:Runnable= Runnable { + ToastUtils.showLong("超时未响应,请求失败") + hideLoading() + } + + constructor(context: Context) : super(context) + + init { + setContentView(R.layout.dialog_routing_loading) + setCanceledOnTouchOutside(false) + } + + /** + * 开始旋转 + */ + private fun startRotation() { + objectAnimator = ObjectAnimator.ofFloat(mLoadingView, "rotation", -720f, 0f) + objectAnimator?.let { + it.duration = 3000 + it.repeatCount = -1 + it.interpolator = LinearInterpolator() + it.start() + } + } + + /** + * 停止旋转 + */ + private fun stopRotation() { + objectAnimator?.let { + if (it.isRunning) { + it.end() + objectAnimator = null + } + } + } + + /** + * 显示dialog + */ + fun showLoading() { + mLoadingText.text = "请求中,请稍后..." + startRotation() + show() + } + + /** + * 隐藏dialog + */ + fun hideLoading() { + stopRotation() + dismiss() + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_default.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_default.png new file mode 100755 index 0000000000000000000000000000000000000000..bef6342f6460b8fa5ddf587bb03d12e9732d442d GIT binary patch literal 38605 zcmV)7K*zs{P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR92GN1zh1ONa40RR91bN~PV08J{iqW}Ov07*naRCoczon5bPTUM3#T6+`0 zD$XhH`~_Nnz=SLRgE#)3x>pb|lv)W=0SY8#0uiahh1_7&3!^4tqKOzanrI~8H!8aK zvOQ1hea!jpvni>s!&vK`V~pNgYrT&?$DHqc*IN6Wr$6&|-oCs_d*S%RfLXhzjO&~^ zvzMo1TOb&)wCOqkKGv6aFUk|-C0|d>qP3hC5^x^h*!5|Ti~cFB^pRqC@ULDy$Nx?( z0yY=)6Df1rOEjM#1t(u?asf|92dHDbfiueC2E=cFm); z?)68{{G;KzP$$W0o(Fu)k<3yZ>xUaBe!9Hcn&Z2GpI)AIEN3wfb9mOBbul3jg5_$8 z4bHnvI1l=8BnCBsgI(PTf*se>{rr!Qd^y+YUcGzw?$vWbF){P$W63<{+%?AtKJlKD zSNDK`_=zi13^_eT@I_)0V0(}U5{RZfJLn!ECGy79G&0+@V2|T@`0gLqka&{1C-Cb_ zknWN2$eX#kfYFMPcu!N?*vKC~P00YvgZgLe>f#`OYQ;*Q-Ot2|kpM6Q&|ZT+uugHK z2A|k6M%%UOEhu|d`KjwWbY%oTzRsg(_+%(SQIV)UP2Gutuo0}?&gdt9oTA!49N|QN z`HsXt{nihE@#8=B29LTU0-2DjEk9G;ZlawGZm@JTaGs~tQ;e`{0K;Yk2!k$ze0M=l z*$iDh3^zuc6p0hY+*8ZdF>P-`oMf8aeH@#cDSXT~=EKH@OLNlU?1b(OBui#tinQL8HQIP7{&EHQ$)0?lxe#$_%|)NHZ2snANJj?~FUog}sI zkQkVIR+hi}aIUkgjYw?z^b7;^d@v_L#n6gQ5-6l|DrQdLpubL5CKb<|OH&)2UVOpj zYW70s=AT+xnh0@|V@!GFXWU)FD(AvX9BWJ*a|%CR)8#IaeAOVaIJn1o_n@bdCwA85 zGh;>%4t zb|R4$s!wmI(W~Y|Oxna?K+dioTADe~W6p~ky!MPqPJ6J==A0b7`3DOpP!w4|bwTp! zHMvj^e8J?v8qEz$7T|RNhkV0(&IaKI`Vt^t?s3;20U8<{RG|yc+=!X4%@aL?C3wEG zZ+_%UUwV4?#uFR<+yDLQ)&Kk*1W8}r3{h_ZmyE2z3X8wtt%gYuGziXy(Bjd&YqNS5 z-c8UkiE$cdpGomR9#oqSnY_-;E3>W(jReiNC(7Lfd$bvvvj^>H62CXO;0Qr+u@eMT z#=ILnv8&V?2bfsggc(s6Ho7BfvSGlG)Bg=33!^TaOo=9*v2oLd&v+IDu(`yf85deo zV&P(sZR_PqV+e~wzK4bGj??>umITRb5Dqf62Gyf3%sr@QQKHrO&)uYx4|OlJ7qvnr z0Y4jCFKIf|&9uJkQ69(sl3&=dMPZQ(1V({rA3Y?=zbK!f=s+2l`sqTrK zIr*L^hB&By%z&4fJ{O>im|?KNwn*2<&HwMCaqcU#T z>D?!!kw$IIi(KK6bXv!daP*9|9NaWOkVj$z^xRBd;7P)ccv)fS?gi@9Vlhybea{|e zX3it-iq@@JyhFiaSx*hR8U_Qk2E<#*vS(hB#^Q18+uA5bQ!VPHBVijI$21aYD zaq=p!F$3acoj~Lo4wBZ0r)0xg@VQ2HQb}{KM{(0*9^T=E z#=^ou!Q9ZvSB+RR$~vC;3`ng6vX=V1V6}M|4RU&09X5#%?z zyc>eTc}KqQduXEC8>NA2uvi0fJWk@}w7ev}C(*k#)S?#Yc!Gfz3^ zL&wQ+#4?W-K!TW*gH=1JH3u|1g5S|>Q)59JKav@`{#`7XvHQNUQN|8c_K8t}PLroM z8^EGun?L%P$FlbeZSj#QjDAFOz#)4VYhEeXK5=b5sA20L-^r)3eNu|9stPwa_+s(R zCZDYdjM~{BPUac6JRR2nc$(7a4Q@9xIr$wxzI)C!MXy@q($z!eI$_ql>H9>ca)Y6h z5wE!0r{=R#ZO%67AY`+EG@@~AuSpJ|#mVR-OD!LoyNEuvyy&GfRlqJxQI_pW2cMSWUVbHqzsTD;i>I}K4~Jt(@|`z}lRtigUABt&`b?1swLoA;Bh`5l$uw0I|`?c)kWJ_r7%6~XRv$zs=ts| zuU^0T@fq1Y6WCCf?q2F$f>k9-X+C9Th#B!dJ;mTvNHK3hh}#0*rfuwqm;kKWZpbh` zz+asM1hcPoV%ignZQ{V0oVG9)>f{M_V=}%q&FI9ocy54WKPF-k=L5~~W8cf-l2d57 z6;P95UVG2o*w#Oety^UWd}8mWMj-mQuSA>X1~L5N5tw{3g2ucTOYFL09a-nY7y5xi z^E3gy)g+ybv;D@ah`5V(;bS}bYyy|WLk800>vnq&H1SUwv)T$Q_EzTsdj2BJR1kygl207vZuYH{q19$| z>D|*k^_-N-xiL2%>G%9^nuBS#g!pem=;ob(*5T>ZC*Szm=YO-2dgOB)C_Bkv^+&Q4 zPzlXvnZZ^Vfq8oJstRJB&iok_w$l=WDK9_9+IfO!J~4@{j_U-wNfYb% zTZMC<0mDbhnggRC^HEY#+~N8gONup86-1bZMmUk_4IJAB#MYU}x$Crk)vKM_H3{;D zP1{n5$IUs3(T|xTMq40u@~=)~6x3Se2wn9)ne7?v-4K35Gy$@ZkiHpRzxasV?;P|^ z&Lgm~CoS_blare>4~wl1RY0q`6qVQwPe^mb?wVpShQKOa>&K|liQhWZ&T;ix)`^2A z53vzO+m{J|mZ7S{92ymTUTI!X9m>V-{yo0NLCF&$(V1G!v9W=;f}^bgb6Sw0dCoIy z9sye866E3;etm;&$m26d=~TL zM=|t#4PWs`x_otle0lx+BXVyCPG#D#P)ox&VVrv)^L(F##FAVFbqT}lHrKibA#HoQFF#Q7!iM=#bABB z*s$E2#A7HIJ%sbR1P^8hdl4|d#v#CA^{i3B-H?mZ-SPt!&tc-#Ab*^oP|PurMt=nw zTZnM|rVsx823dhyAImXikZ+h)aO}p8u{bUWV65vg2DY_dzKVc6aWW3j)^3gg@MUy@ zILq8HoiA@-71<-yXh7{AivgQ$_!+ylIFto27|s_tVxRD(a*T1$XNgC6FwK3f#IN*P z;IBp~OeOJJ3{fjSV_aif}nwmM1SG%Tw&HQ^duIZee z=U2b^YhU}quVcTrxsi>@C!Y#8&y#Jm^A|07nzG2kNp7|buzC5>Q~Pk&2f(+$NqY*1 z6ie$X6P}cOT4H>|zBfh|Zvzi*l4Eu@j4_Mz2ifz~*r;Wb+O}$rUD{cI#%dS6DM`=d zl9^HRd9*#weHP%I$^VpNmrZ z_(f*iR5EK@NtQsUs;`$`ga*>W!I#;WYouS774o1*(9DI#!jw+kJ_RIP}{(V+YJ{ zg>O&KJzG&AugP_7hP&0$SfOw1^|SV_zuBw~{`;62I0UrQ=cTP+7BfZ+3;}f91)K>o zzVNy)Fr;nD`gcM^q!LWnU{Qekxc=(gwblX-PU&c}rr0!Nt-n3F)VBC_Gxt@u^1Ig4 zg9$%>1Nr9#ym#Lh%)Fvt;T9GRz6u!Q?FZJiha{OI%;NJL z*t(Ds!Qc{q=EsJ;ZoJ5x-;T=BedR?eHfO(W>o zcP(9AwL3P*Z7tzKheHRH*Vq7dO<@}#PW%Hv6T7C2i;Z_|P)@b3x(d-+%6lAN}H(AG-d%Tr>#))K?DlwbC=Y3QyK2p&6WceC5KMwySZvUW#@_ z=*e7_TYqkXE4IF!Z?2g~u2w@n!GBISGm{0!1%olau zxaJL}bdFauke)J^bgRF7A;pc7on;>L-XI8cE@*twTqc3Vk)K&K&y68G_MX0B*#%)g z_1gkXo`~VTA{AGg4x=UPt)))kFQ++_aq@pp74qV7b^UN~#N(^$*Q(s}PkjALPrqN# zBXGr1*OxorH_E-wBXYn=!>0_b3+EAEKWWkFNvN2}I8m7(Z}Fi>I#I?0gE- z!{NPP;9^SG5hrkxkKLT&IliLtH1EMkISZ)RW(Kz_$SB6HHJ0A3`~%Lj46s-D%-T-; z4%VC=aJ15`OZpzVfchH#aB&HXck^=t&By2U_0LKIo_xWI+ko@|Z>_3Twpqmil_XkQ zcEHr{*yEl**ljKEnycM>H!OlD7sK(C-00*}>7xA!fCG)t{i5}hclz)IRzk( zoMw`Bn!~YI0o~1&aifhk*fGgf3rHL>bk78kc`RXnNOOJlJ1c!<2!?1R(aK9njb5L4 zY4u-v+H$Do@JWGo>W_gsR5uR=zxVmiJ%2^a2M*jp8gvApKP*1;`(_i*;nwas5P0XV z?1sDMAf_tx6x8_rO`-|0lNF*cV|QW9X?wCeLxyJV;n82~SWW>)Rt90TD8XpwX% ztmV`FErQPKd>VJRJZLJA!x$g)zp?Z$Gnr=Sj2g}gx^5iBxp7ybCdM3Ef`?ambvqL-?R!YE=TBj9i9UYm%X`htbON;QDj{)HsA80T&|2J7Th|> zhgVU===uR*PgBFg!@LakFpz%j2w>}9RP9=;F-N!mgh#>eEC5!o4NY^nXIcUIt62J; z{*(R{`@LLd%Kl;ao;TLH*2dBEcLQb!X4hF*a{o~NqdpZqBCgT(hYin;1LAQ!KmF9# zf9m7k&Fq8CA51CgTOh34x}C5H(yYgVdHc(}aD7h?9|1w-(t2bAfu9cE5*MRD(VM@J(J8t9drn6;F192H`OAx8_2lhBC-Y4M-`+ruCb^Mo zdW6@HbZ>eLaHYS!*xQY@zKH@%Jp3|{wxyov%8Rp_fQS$OSRBKTNe?~J@Ez!5f~~ct zuY$%L0MUrGt)r!HuUBmj&GX#!R|a)sfOyorL0mU_TR(m9=EWlNFMr;B-|Od}Fzz34 z$bS%InjcU2N8)V=(fo`49Va2anab-_+<9t~q<1Q*`{Ce6%2d85q%PulFJ-z(7$pyhi>KB7e>;-z% zJjIQ9g@-3aJq(#;+%3Xp>IO9viRJfW<}H|-UDerq`#Hn~wYnY;_Nqcnc$)&9%{B7A zIKGF91Th3N-dxQ;j+}VtlXjswlAp3;X&{6+0sC%R>4)_f_)x#I*FpyiYvY~IVX<*> z7rP08<<$nKu|OSUZSbMxi?-M@d&IXjI`QK=>nBv{)tT^P(%Jm4IOaDzy7@;qM<=GX zh+OfV)DFpYZ%?$=fqLBAu8DKA>y(uRINyaZ52m?3Y5)oNs(%GElurChr_?7N2~fXLiHIQlZ!xclvMwf}SPZc=zGzO>)gNr1>qPqC8QMKrq103tQ*S zD`g#s$!r)xj2$>3Oxp`|K@~FmniiWL?^!x}?@fLIS0!-1;T*yqa zLtRt>I_>9=$x`;o)yvT%csFmZ% z3608}_|(H(u&-N80uaMEb?yzv{OSm2b3M}5_$&{;^sv;gRu|au$-lr5(hOgZJfLa2 z#?ASvKjOSZiEWHc09XA$Ha{qrR%vQBfdT=g?fMyS&W^3ogvKxdFcSx!+}Krme*TNV zzFF&UEkW?En2!IV!qqtG)A+0QMB&Ro4Pm6YYzJuQWu-?!<@T9k*@bnnu}I5diV#TK z$kD;uun$8WrMA$6J&$;U&Rpo=vC^2L&wbDEbJnm6og6wDTYTHDliV7fdPHn}M9_X2 zuBDtj6KED%>;_)*I0NEOPJG%TMwKU>U`(1WU%P;n8h0V&n>UeJxHkSv6#E8{emCuA z&>+=a$&I%g5S{AJNFayI>zG{Akquy`ejxC5HV4-~*ww{9 z3M~u%w8oDQzZ&!mtm?4|UO;?D>*O!OG=^S7j;JZ^q3hik=6+v)$b7LZ7i-_c(4{D7 zEiS!{k&l&s|C6tM^mlL64-U`I$RHZ_TvXtj1U@dBE5}8HN!yLz*?UKpp#ma~d$MC? zp}1%}*mG6|v14Os{SOa*Udf}|9!59TNjgMOo^8n(pgg zX?nC=bLrMk@v(RHSAM|I!tU5)(3zD4dTI!b)&w#LgYUC|su8cY>K>Zhq07UNwn-B+ zFLS|$+zE~3mbPGU}5^Gu;{3hk3a2IvozA0T|{pChf@ zz2|TBjayGb|_l!yK8V%1rJd zT^C*^vq^-y=-bD`)RX@-l4bz3O~4*;o<5jZm9wEZCs+zkFNF9R%z46ObvFOZc{4k9 z=1fjw62CvZ$+*CTs(^VOtqzPUe}rOagb}@wy3P@pPFBXlp7mws_ncjcAXp7+j{R_k zxgGImYz6@~?yygI24Jh(Y^#0v;~GkIGAb>7t$VIFTviS zG$dGz`h}+!MyRE22k(ex5-xPy&7X<0(gusAEu(%rm9wtZiXXd~mjACm_h&!;<%NB- zKD!-v4s7at`_h69QN1Re;b{wnPE2Li%L;iND}W-Zn7@tTBkcb3Aup&UqfC2He3;>x zI*D{V@ca03G8(|6tX3i(^M;q4I5_0 zMu?lxXz5y?qDNT{a0cM_W2WbE^9@`~`pu;|%x00_u|ws0F*96_12iW*+kV$h1pa&M z>ogb1H8sa3P&(tVc8!iP6*(EBkT!7`nM@UQT?tfcTfH0vc-O^T zdh;UwsfUi(b&+Fr2z$nx&#de5!UZ?cN%2E`Q`Ong6`U|pHF(GHHy*stYa(nKj50amB0;Ye{bXL8&Nv&UL|1qMI1{o~nUR$=fDI**rnoa&AxG}dhP{lGBo!&ef1AI3a$Fi}s z{uMnN2x3g+)|yoCo{IoO;j4Ok=2?sXbBgp8xFGS;%zywxZ>*_WCi({m#1^gEbIiA! zHO|dzd$CC4%UAaZnuk4tDD%P&Skb9TAfdp&w0vqjyLrdb35-SOYCzBSO{#44Q_W*j?<@HKeUC zYBX1|;fIgC^d8-Rvwrg@lhNw>n;X0#Iy_^8Y^(;mG++M9=YQx6KV8EA|M<)sEw9P{ zVk8K0+6a;tSL-}Iu@rugT1<`_=pEp_xQyn6kf<&0B8Gd5R={-x2g`owmv^Kwtj|7& zoj-s(akFru7qmfiH#62UqgWXQ?|;X9reYgpLzOWzy1Xo#*h%SttJxE9MJg0fY-8R$ zUtV~FijO+RXFdIh27WHAi{v>{54US|5N8Gfid;GKrvXr|wP4N_ZN6aPd4iuoK&<-&<40RXEzD{c6( zk5GXP6VvYBddcVFPWHpNC2+U6R(#EC>oH5OBgd`9F~rhr*E9J|&h0q=7o#K2^XA=r zu`h12k0qngS_!B3$tBBQ@5}rD^==vU zD3q&XmRG+oenA#^hViwyk054K5gi>@yD><%3qmRFp<*?09Ix&j?+LhvSerdsydW$o z!}l8}@PahQ#jg*}czWV@vW}zAx*E=nA#R)*6KSD7xiN{|F}+SnD4(|L!mtYcEnL;G z?G3rn19W3FAA*ukgP}sJ(r&0Ku?;esfckXQYi10|wGxhZg01T>9th2uWQg_IWk`%g zuWd5(XJ`66Ai#@BpOQKr+laIlg)Vv%pd{UY@!LZ3$^nVmd`*t)JNbYi&gw{?8V{FP z7k%nas6E1#Dm|9Vif8As5)1+Rb^=Zk8QjRNnTQ^mM1zfaO-#)^e4n(?Jh~b4 z)HX@_Cl^6G9gMLQn+lxAbgTXlv%0g62?D=2%~^usb}?WvkYyU$&M1bmL#sNmNSrf_cuujuMLs$=&1nC%H$u z0fmm;1;8X<9O33c{TDv@+8_USg8z_*{cLCfcjcZfdYhkP&`zPV5h%S;-ejr$*VR_=Xs2|VeoRYl#!YP$pepLUEr4H$Gv@n*O7xKK!Ijt#n)M_ z^2r+<0mdJ}9o`tmFLJQ+5vy2^H;pK4w)W&+a$wyg^yDd%-!KXwV$NQSxXEtqb%W*~ zAM-!_0K}XZ{Aw}Fqyqco1J0k9>DApsq31lRhE8#$j1>Px-R42gYfL{#m*TWML4i`D z)!P1IF`|WoY<9i>fSh$?vDZgWgn$*dlwmp@K*p_$HvmbgH7TJFa{Br)5G!UDkk+ln z?kwqkq01LVD)-s)cZKxPK$Cczz-S^-j>-?zToeVJV`N%v=-6e`{WDbihLhk;}l{RyPK_v!EH{vEly1gfI?N|fwghr zu-;m$jSYAXnB;@CPsp&6~#0<FYx6v;;oxKi6^Fn&wr2PBZ=Up^kfN<_>9fX6Tr2r9o&%da_Hn@hhao`- z@L)l9(S0Hi$e|ej$Ade*dgDifli&ZtQ*|b?K#J!VE-to*)&x%e4?YO^c`?p09a$dy zdu!myri|*|NJ_{&WTaClIpn|7qx5 zzJbF-g-c;tspiNyey6j-_4TdRUF{Rma&`vDCH$Y~z#dk&>uz8qqb&G_L z4!OY?JxsPUP*)x7lNc0fVr9>WF4Y1zh~`j6?ZsTNnLFD-!)(pcyOu~CzH-grw z2ZUc(k&$Pz&&5 z>7H~v_jl+4qX~NZC>X0~X0Sj^&v>Iu&kY6hadj?>LvC(d1Ll8#v5z7qVEDoHFa?xH zPQrshi^h&d@XK!`m}aaA2f?_jwY{$o5z_m{${l~0%di~a^P0z-T zCd1~EQ3M+WTS41X+k;c7c;ehOcb&B^r@FJDk0d5(e9O%n*(Tb;MFT0` z?DA@h!JU%G_G@m;9?7bsVi@;@ZchfL*jUKX$=tt8siXJqj7=&v0 z8E3jho)n4!2at`3!yX$cVWY*)ol9({Ny#FG=MNNPqHnDLZ+3;9H$vruB)`BO@ zY;byzSA!cX=P`Z1@RqNcb^B!k8Qm_FsSSyMIctNC9v@}(Y<}tU?K+6-IwY5y+VF#O zFOUR}Od5W2#Meynzogm47Xgs)@k??Z-Yga~KcJ^f#Q>lMV?yWxzFy=g7MP-&XQoXl zImN@lIur(ne+rI`DEw$6LZJi~i?)myO9QH)Frc_F)?im`S3k~kp>)pCroctN$y8TA zYa=(jX?7?y0{#2zAEX*5Z;d_2awE~2DXt#!*wi}~t&=2UFzp=-ed}+3%dvPgw_T%^ z!LoeoS(1TT@9gBK=imMl-~aK~R^?mm`&-LIG-x8yn@SE_+eguE3T**^6+b6s?O5x5 zWGlK@0{j6_W6M{2;-CZtx>TJQ^Kt1dqrNm%h@cH-Ba_o6{z6 z3u+FNz-loyf7o|`xa5)Rcg^M8nf>kB{$>vTsc}R_CatD$-(1*MExq}Nc@miQ9|4jp zXZ7174!xDoCdY#-XjOzEFoWU&V7jk=(u!x8=^BgUrF#u8fyxJUnJQx@#2Sq&JQ*ZX z4b`6*Cw%G_)4oRPbZB<35EmdW4y`xZ)y1rHqJgW)`az9fiHuj%;;1+JvMh=t4paV> zpYUMFZFGY(KeSkzjm)}!GGolq24HUh^6Mzk?TFk{yc&(MQ9!B!b++Qgx2lFhH8 zyy5(%uYUFEe+m6I4*q9+h`q@hXJXxQI(ZOdQZk(XIT;tcR(jrUlbWKt$n_(T@diX? z=hL5e*38f4IP|GOY7v7^ROx+!x-BA-@@`LDScpTJdt?-AF#FL_1363^gmv!|LL3@- zMjISyI9pz4#jOv(`Z@XYehyT<^l3o4(UPI-i;)HUB2b@@+@RR1ZzA0pxY<2_>39XYWqmo`Cb4h=IogCu`!J_07$HWX8`LKn~uZ%WVS32QemM;E@NEG5mb39UVWzkuy1fMrx1V|D5y3+xJk$yUoiW% zh=%V5sPt+wgAyOo91!uFasA90VQI^Vi%Kyw%p|>=LE~9+IjfU;i@WqL&DFlJjR;~; z)48cQkK-bPx+ZoP92@g~%yMI`4v&N6I(l6^xdjeIUC!+cXV18Igit?x!x0#8Y|`Ox zbBvW&oB0>10f@C1rozO&gnWW!x-#xH=yUE^Cu4H))uZ!p3a?)47k{R;FkWBnDA&0N zYCM=E;kh1+QE_chzC`6Zx0N!URi8dxc_0JaWWDH#F{Zf8e_-kc&$jK)hzQa^-OAi#$mSC0`pYEx zzOFYVDA6Rgqs%hK)>`(a)HuWDE^OGw?zk~_Eqk%HvhW%kY}dD&7cGndIAnck)bZgl zxVUDpU?}|}P7u|yb7m~{@a>ycBY^U|htX7}>&JdS->xOFJwJ_Lu;%ZO{8`(00b|b# zJF_uij(zK#G3nfD0jcLdECs67U>In-{>~J^I`N5h;z>^qG2rJ*U9r{1#z>!%Yj4!* z#YXr^0WCFQt(JZ5$_TF3$)^re)~03-$jc{ptM>Bd<@v`4{%v=>T}60KPU1|AYh?h) z(Vu0RO+Z~N?}iZigXF>#h@Y<(Y&fm}e7P+YzE3y9VUC-zJ(aevNduP#coz#lU zGe7d-#byr_DgN>Ie*7`dd`xTZ#OYr|_1{tloi%bYJRyeSFef&@sOaBXg^&JxtYh^( zQGq6?u^Fal{{5H|W)ffDPsow-z=Pw9jxkTT-efcoo(ymr-~SC+{MynNMO=8CWw#EuBGunZ|k}z4BYb(H6-TwG7}^-IO!W;=8XNO3guP5e4K`l z(R^_tN~h*bw1h*fj4!RuiZAwJWYll_u2~`TC*Je?Hi~iAn*h^x{gBaYp5tdJgWH-u ztUtc%{0&fzshOrri|OXA&KfeQojMUTucueP@+-ga(LYz>J2>R;$ad3L?1;Uf+=ht{>(c8tBXIRAx^V0Ztp&zb|c zG^o66=qfzAlQ+2ys2d+}aO$F6nlVPpF#wSRB=YF%$f3B-Hb-WwSr4_Dk^IIcfouIN zV?fxaMy{3cr8j=lilw+hhcmd77oo(T1O_3!ac~jCBw1s}Tj$aXy4GLsi4%#TtKa-D z1#^sW`B7A~aacFg?GaE*CGsCIbH?cCn>7cVAM5_1{tK`p`3H7=A{%j1@{!;MPe{Ks zoh(^EUsL8OCcpk=G0MtwG4QlSOAVHj%{q&__u%^%@Ask%&zl6}O)xr{@LN1=7O9n5 zKx~sKDPSEx_VwX-(B#Qz?*Zh924n^3J3zU5<6ub(i^+eq0H3i~aI?OQwsDj2Pb72) zIXN1KC&da>1B_7$A{9*iVSQ|xv$FKY1fC|1*Z?}Io%5nVrqHQBp8d}iiOK;S+HqdG zEt2LWLfOY*2H^A= zNO%tj09Sk>pkT_YPrjw?#mK%@;X#HqVQ8-$YJ(v+^k}_7q-W0lN^h+N3CMw8=JXos z`cYnixVLQ%xQIb#A*eUCYT(wP{K;NI>1(g($+cpNqSO5lw)%|+1G_n%^;bta{=CYs zJrgWbnr0BtKl;Yc|Ilv?;ydb|U*59lXz;}0fX#_v8Wo?owbWNr3%5{#-mnymIYo6C z^n7%q05lfaWwrO{=0=%Uan&FWAIVx+U0Yc1INcc9rEyptgN5IDdp>5hk60}?D+@gYad=(c{XnZO9j zr60PvJDxny8K+NH_y()qjLm=YV&Pq(0||*f@k0=|H=mJ93^2|ZC*Pju6MpzEB{)Pz zGqk4BsB!3PAKd0oFR&kzn?JVOz6CyN1w$aWtA723)Pz{cO#4LLsFh$1VHn}6e& z4&V-4)oofad`GAJD<8N+p3vKc(l%~k3&lD0So*zsn~-smP~jynZs=E#Tfo)4@{V(i z=e+KsQP{jjjqZ|*Q#zmlzJC7mH|TdX%uei*4CuZ*p_{~Bl!P&U{R|m-(cq(j6?D9% zuy}o<&dcb-Y~yujpO?Kanc=bal0vE$9R zQsmP??7ay(4M2@J>CZ)gvyKijXZftzdf`WNFf3bs%o8X*+K|RK^^>o8YZw2J>1f93 z@OH$D*y!rX_;6<&2&rAI23VLk#vO#mmrn2n!lAiThPfka(_9~lYqJlTua1L3i^Hrx z4u{=8laDs^coA>;PBHXN5M8k1PLk4ObBNiH;QX0WvN1f)-ynkE@#|W7CLq@W9zj@zBsc=HIcaLF{ZIKM5CfT@w(uq6bL!2HdE?% zVqmb5L`TxcN^II{)ANe`-~RBQ{OE5C>^tt>P<56`K-=nN(tPd(>Db&lj3xtaGUP*{`5P~b)eZ40A5v50fm*#C{5d|XpMq+PQg5t*44gV?FdSRiKXO|3-| zBO8oQg5(Eowg{ z%LrTBgjZkb!s0|^)|VOjx&pdte)Ess={5mF9Mm6a5e^#00AhXNOm}; z*j8hCdiHQPmVXuQ77HyhP^+;FKjJMS{5`3oe~O96?2FjE4DUfMayvr-jv0Ws})ZZs@|DNX*cjPF7+B-7xUw&`sI^LI^+DV0YW85)@^+epQN=3W~p6E z6))X^o?LGOHK7On-#+*87k+A_zAK%75WD{wctcnf7J+`>b^CWsP2QAq*mpuXKq2td zu?w%jag#kKN#4W|%XnYt=%bIGc7{0-jLB(q`?H>&sG2CO0J)588LWRz^!Pm$$ac~T zR9|Cxv+!DHT}Pdz$d=E$p+6YMpVMo+AmA|v9h+EwKsGu0w_QBVCO8i>BysYP+obB^ zSWE{wrq*gSAOWJW@l0Yu#esItrGKKK4BGp|lPzE#fzihU(Y!r^t-Pr_?!I8Ltjl+P z>Hzfqf|%ADD+6X0ltEi;mw(n2&)$#($%Eb+?Oxd43l2`c$oop6tH5A+K#Ue>jM~R$ zObZah!DR@Elf?NOfyRPw1rj~}EkJs6Qfv6fJ++P0))?N7`xFha325(7%gGU2t_d#- z_~?r`K?7(TdL|j&wBQ(N0pvdh^LKLT8hZuOPb766U-T2l3`Uo(y3b$v`d6O*OSAj# z9Q|lXMtgcf#@-WfE-KiR)93>hVt_FTOMr zr1nOhIX67~o{`{YXpUG zgq_eQ9wy>}w{4!8NV_~<+)gJh3m;8mk9hT#7pyv*?+LE3#tqWY=MA9=5rw_8O33eu z(QG~FgV9hK^Bl!;8*AfhGw+OMVk|kVpP1vL#$bZK>q_***H@ib2fLYG4=Ix;F_gaI zpxbqkl%d2hR*wN~>PHAQUY_1Qz5Zi=iRpKg~I zZ z0|+tO`?Dl(NY&|vjxU^M=xsS`LUdN-&kp8IDCXu5BcfeA0>;tm4Hq?T^4wIf3L!g7 zl0t5@9`OwT%2+oqbbzdyJ+q-#eJaQ7FnTC>`(WA!gR^a*xi5qKLu zJiLRW4X{J!JHh^rI!unRgw6Vyqfbt?XC5E3b6yX&0rVlLW_!qZX=mLtD1BoLa5SeI zZuJ#bD4H=Pf}-TOLC9?&_GT~LY6){)Gg1V9+Q2euPMh$9{rUOp-}w0-_%{;1i-$as zCCt>!EuT52-W*tzXm~wiAKp_a}WX^p-%tXxMqnW();#W@fcAOwi0jlF0ljm6!mB*D zFlv?maVeI>YJQoT@bsZmSDq4ke$!J2o;njBEh=WB&Z_Q^*o04eIEQP*2b|c_&=Jj2 z>x+T%o168Y_|T#+Pwv2>k4F1FPn^}Zfuro2{P(v8Sp>MESb`(&)03yQ1!`@<7PIW; zI@Vy6-k@N+*sEk+VC$<0;MUeKGoF-ObM1|LNnazP)4E1RtGSp}z=t>WvFI04hieRn zoI{z^9p4t9z~+X{hYt*zI>bi1z2|dU=x#k1 zShlwd;4rO-9L07MViU1^u?Oiw_ub&cFlI0i=cceXJY-~_K`>l!GsmZ&0vg!EaBzC+ z2gS(+A4X0x5<_Cp@bt0k!oq)M8rz&KH^_MHz|KpcDh9bWNq~FVZEpnQm`$jOGn=5B zAx>n>KVutxj1zyE>*InvHtVQB;Z4a9UYIVvM*iv9QFbxq<=9wFrD1AJ7RBt^S8j@0 zo{Y^M;zp@dJv{AXly8@R>(5f>f&_0|=;nci755FtbF*(M(QJ-FdM-x$(BZ~*)p&EP zs(OQg( zA)SvcW<9wJTqlDk0pHfn0$9xB+N%q1S* z@y$&NBtM*Y9^~2J*-Eilcrf?_uAd1v6ux8R1|D$ZXpU+41tFxLr9ZS7G^wA1jXu`F zwhrU6pBU+D0mu8Dz~_SBXE z;oB$SX^ptpE5CsAP2K3AwUv*Jrg?JO+{H@o`l~Q_uqqyQMLZ{yr_kcmjBm1>h(yn8 za-!?LfcR-+eX&DXFcJs7vDPN&rg?zoVXB4Ze7ydy{Bxv{d+471XyrPSkeQ$56-Xv7 zqzN-QU-5APMIz)2JpNV*5 zK`+oud2!LU%$eBm!;Rg$QncnK;FBA_`2!++L=cJ!Hw}j>#=;G6U*wb*Kahvpo7k=y zL&jWC(csHoPVu#+iiF~@H`7ds&Cg!^P3XG(7#!|uQYHe!_uoM=WsMULcbu7~#TL9V z<+L6SmB>1%iMa;1KZJ?^I6%k0-u|4C{LjzE(4>|T=!&OKu{V0xqBvaQi65e2Nkf%(u)&9H=s(daqc*ROxp49xY{=y78mO{@aV-U)io&(HtjPk-?T|CXfh z!Qq)}uIXLsXt%`lnQdsM@@;wYh1wb;zP$qAcmD%>06O^4v(3Ch^-ZVV}CW^gDN0r46R zT_y|B9ESW0)_&K72$$RjSjZZ#tnG?M})>S(mr4T|ghx3c0jM1<{Cf(?IS z7({+!>{_eHF?PSrUKQc9rQIblpeJIm0Kr`>ERA6bOw+)4{%*W0w*a)acLIt0^F?+W zU-Mw$n(o5dn7xOft0y(13)8O1N z%|A}t+Zy1W#4+m?|+>&^H9WlfR{NJ3Jy+V?697A%A!UZ;@~C~%#{=4 zaPn=Nq2)veJ2CiKU2y&&-T>GNnDk>fS8C%=9_aJ8Wo|a(Ow#HWWUdB^%(O7_1uq73 z%<~R)$(Wl`>(d+Im1oi-mRhqY1Y+y2`+J@Yf!pxKk!ROZw*Ocm)U*G95r6jWz6qdp z?&3s9?w9C|(nn9enuTX6ZV9}c69wRO>4 zav@E*;hX1Z$z}oM&TIA$x>u$hL8rO=p+NP#*X2_BranLkJv2`ensu{~G{ZY0Duy}e z=D;}#=lS_}UjN|7KZEys)%YQZ3+(2bFs?G=S-Bf6HojPl8N=(DH`&E%f(PvWf_vs2 zyYbxkVAl^fk(^KA`q&sd8*D{pm^ta1n!XIlbza5eZ}tF@=Emr0&V(qA=LiN!??4P_ z8~5trfHW;`w5}U};rQGvF;y`~*G0SmF&G}0UhKi|QdmX0 zb#CC?bZFjuLSvY(UbpF8GW(!%dNMa&jC{#4jNl5P75rHA3ao;W?rXlrRpYq%Zn%4Fa`SrM0Lj_3*G{l& z0a4@ptzy$5xr@FdpczZQoy(V(FaOF{o_=qb-;>V&9vSbZo0uu(V2NXHW1)E;a&fWv zbc7RLf6mmUbP<+uvD>r2(@@{SbZi1DqPuDtb3xC=(s&~R%q+n$;YGo@etMNPBpaed z-D|JcO!26kO&fySXKpt7IG7IF%SrATJBz61f?^|IM4R0>yK!`MZN@=6w*E&9QL9#; zEEcCw>n|b<0?v)jJRGw+@~5Q&(ph&c)`DMhFvvGgEzLXdLdFii7;i4}6}y1cNzQ5= zin@jfzzd9!3E&Mn<2~!W(ISEtp!*nR)-!R`+Z4j!j)qPdtc6kA>NA6P7N-dFwAiIw z0vds!W!|;qSkT%aBYR>FXM)up8yJo*jgiS5$K+2eBD9CmS}+1zz99Kp^@(#4Q$Hxg zyJ?lu+BCi(Q!QW0tfjeiU1Zh9oY|d^htO4S&d2Y9m!D4xPtX7R>HEL$%T@c{9pCU9 zFg86&kup7}%8!M{ovm@Q1~(J)?S<>({1hAa{_PP9Eczy348#%O$$=gck%OmrXwmaD zwp8_tYYrJxI62Up3yNGAKGo#kU+qcb;;Dp*LyL3{Vj-mo(3Khx3mt02$4%BkJceYN zfBM>BnI=zDRa5~}dpog)rXGCL=3?cC`&~wFK0G}s+DPP+kFEYv221A68Ih}1euMC_ zj=1SlKR@#MhJbeCnZV|Y40zH>w`;5#pvG;qjBy~piCdSL;3EaxO*Q8aMGJ*^@+XLm zwY15}(6vpx4eR*>=GyHj8wQl=(lBsNT(u+jQPz)64-;2Ib!Hehk@FRZzt}KGwBfWO zRi7M*((B zDMe51K)@(Iu`(A9m;v#PCa;H$1b=gDuFP%GY~I%N=RW!B=l{cazGvNB+3dhB$UX`2 zPEKAdgMNPp#KQP$>!Mr{915IQPy2=FsA}E)JC29l?-en&DJ(N}?K#O&y%pV1H-!0x zwAtB{D;(@BadXey)#@4smDhUDp5WNCGIe@_Y6}`Zyu7&SJuq>yG#X<%wK^(Vff%l= zS7Up%L7>0+qgBb_rej2^Y2^Z7{hSpxdz^+F5I|C=rP|g)kQvhkKZ-x7>Tlt zgW2<~Ewg+}AFe_-?rIhXXb6mw7|^qJlZav4$!83RNypK#3I;)?gof{NrHoTb^DmSn zoOci3(1(72qfY2soZue04N`i>`F{Oi*zn49Ch+H6cSy%d=d5gx+M@XE+p8XX) zW364#Vnt9^@VTYr-Pn!F^n=-B<;qEqc$pJA{Ag55r?HsNxr9*R*$l*b&V`@}`lwC#@)?Y`|3JJ;1x;aW$!+mJih@k>PBeVesGj zM~9Mw=W9Z#W1{d`caY{*+yaZA^N~1vqwnU57;ER_q^&E)WL+qKG*LwF$^S7R*x;+}|O=PNtYGu=(#`=iHUQ6wScE6cJJm!V$JcS>&H(7+Rbe(?mL<6(O z(U0Lex72PBEf!1l#VIHmLv0WBi*YEUch^DpMz72DsXNZ)W2<(9x>D=MXd6j%Ed7kb z$@)bale~!UWXQFx8tbPmhuP+09%zT(5alvCIc{!Cir#7u$q4X|Ud9GVuwDe$|Fz8K+%L8P$?YP$agzpy)~7kS$k}1Dxyzl61|ByYU#xHq!^5#R13m(I z10?p4)eWEgz!4Ld_6#U^IDLA|#Sz!RaIpZM+`93Z4-c>}=8U6npF>PebfJ#}Q!>lY zrz7V*2$vjceqd|}7e634qz@)quEikC{f>X)YY#FXNeP?p=*<`d;(Tl~7b5R(Si?{A z!i6Mr@CIQqoLgKTCIht4=LQpbC_oIZkoNw36icLCFBB4pbXB*eoN>;Pl~&wb7#V{ZH-U7gweFmglm9GiacCyO@ESL! zu41&@Ym8$zZ{wXHB;bS$&}zFzs>O_-@KV7y6F-nRy7BU73)IOo(!4nC8S2jo5sA%T(KAX8@Fyc{GEZ*WBGBhN&afFk zN=#}`9mYl=>|!#(oX&J+T;F1DS^+nII0r15Y5yvpnDLXwWUDsQG;?7vbOvjC$O%l^ zrVYFta^{Vf6uM&HBy?8v=*X`=ZoRX9VZJS~ik z(P{hu;)%n(?5sA2`YJ=hT??LB)fN+<=OC`wn#1Nt(1{bCUbTSU_5v{c*z%SCqtie6 zsUXF_QurAGb1*-XLX8Ua-`9vv7`74_m}(?KJQ?BoFnfSW zZZgE+1(5$en#(W=-o4}TkahD51^hfw!o@edz4+CM+B@`P82Lc*VZ|ynLD#pq;gtgO{c zbdwR$&=v^TCXe*77u2q4+}0hZ+Ceg$z2;hp)C5-5NE4w^FZ#_FgktbP&-$HAwi(Y# z9(fg)Z+(@bHlvl^)xy^{+KJ&>hfgS%#j44{T41{haQLH>YxXZ}_|Kw$?tc_;FN~I> z*-p~jFi4)0qA8f^#}xDZi>+}KEI#F-aoq71>cZA?<`g7>_=8Qq2%mYss(&haNCxP^ zO+>`xPxFR0dF%<;GlHM9MRtk724szy_7ED(Yh{@!i&c;pPsib^UpuTbk14aIjGn?d z#3wKQ+~*jouFOm@R3SZL8jeMRI=JSIg-t4L@{rb*=wKZI^difE_3NnihF4xPhWh<%osTp*p?;V<7+ePjvTb zYk_kEgUChwuKz*-Ih%sXC_fwOHf}5*CIY}FHL=N+|G*(PFH=Qw2SM`h6JOr)1jHKS z^CsFb9*HSEF-(tVo4$EKI8SIx36@&LV;-7)${>K58H0>LTBE@esFv$onpYO%sWHdV zrFNOG%AOlyW3!oG^RXT=>dVu6_fE8|#W?(k+T456Zhi%f5{<5dv|BGYi9??FI?X8l z9LTAvvwl2aO@_npK;_#fvJ$Gt3E&M%r~n@jIU(flFTC)1Jv3Hk#^PB$Bt!<;UZD`%};Lc+u4h;@00u>R^if&HmRM4IEM7Bd2{vrO&)98 z3Y2aJ&8_sK>-jRs=1K0ae&Xw2diwnn_cIv0Ie(sT3d&;l!~o9!ugBTGf?4TM%?P-TOsY3HKFmcu<3wuc5lBf7Wq9uPY056{iQ zB(ug18bdT#a?8T#-Ui#ZuxP3($FK{Ze*bUT?>NIOf;ps&?U}30ps`}-lYy8(Jr`h>OPq`wuH%BLi%6^0a|KWj5*Zxc2E?8qd;SYH zyofyzzPb)HR}227+blS4CNOCPqF+QYH4Y{wt?L>zQ*s2ApTqu-*H2G>HN(%e^jBPU)5G)F z9G#F+&Fz7=G>viiL3=|gzWWDTRm_hZoo-FZjac-3xn4jsD80_^6`e3ts^SSUwnKL= z6!-*j|1frK=}*vwH>b`<`=ZbK;UO99^yK2YSDOeYwN{{-h;<~CVdgy-t&RIV=FtDz zum1cO{!`JP-SJHmBTH65Qe3dJ>&<@t(X~%ci@9BRS-I~}`Co{&2q{3{+NNN;m?@gm z#_KQ9dWG-<_SP`IsU{z}TKH%};U%h=M9w@nn`0;MOuVs?ciQ|#zM%Y9QsMLj#K+Uk z;de72bw28)4oVxdHStD~xqoKCO;umIAkp?|!Thrt@&`-u6%w}_z}%&>X;9i5AFx(~ zg`b~yRV~NX%FUy8u=M;AW|Zu?51S)F(vlad{Hcc@%}Eh_zcbd0u?_n%Ws>G^KGB3b z=ShBS(ukqG_zH0xJ~y${wOA6Q#fK!Pl3phvGU)aY)%?JqRqj!Utvm#Tn@8)>c}38K zKY4=96rB3#C{Rm1vo=`4-*c=c8r7^1P_ea(QkA&f)4}+i1JM@`6q6m;j?Xa(c+Tvr z0jSYIU4+)7%#mzOf_IH;B;W)xHxpRJ(Hm^nAO6JGEZu))z`qXs@ssOkILHtClW4xV z{(ITAD1De|(F;hn-k`b&tIZQfUj8YQJB~$Dq`rDXVKpgRt_W)7CgkeK#Qg-C`1#t+ z>5~*#w9(BsnnEa`PfCrXt$_H^tu_}s#IVwalR%y*?w}9{YXD)3BPMIe7Xsn!McWe{ zWBlYz7P}_%l7P8?@LCZ3Tyo^+I(qr}|D5zjOE$#In}Ky|O-_D^<*a%!{(U0@MGTi z_(12SW^-41OmZhD@-Ld>#a$b`+8tC@?U7#!Ho*CIU74EGBO>CLKKaEj{L6uUrd{q`S5bCNSXehcm+U=Zv&OlvUYxzL1PR2= z9l+?G5+F#SazR^&y%~k%e1pR$K;{>AY%P}V{)Y~8v+!mIKE#PB4@#O(9*IG2yovW` zKDufU(-SCvZ|t5__|ZORv$=b7K!UK7KPdl-UVek|BqrNpx-d}M)XmT3%u5hCvMH$t z7z<(zh!1W`mH~A%B0<%Z!OfNU);OL2Y#@H1zQ_mNnG*{*bt6E(>mP_=;)7?-?ul?F zJT%(Q5!rAI1{Uk`H%L5iNiT0Ke3?RQXf3a!a{P@lB%Hgy%x$Yhoe)hMjVrI(a6n)C z$qQZTm#-o!a@D!(l8h@2Y){P06Px-|Pw&4j!o$(+tVig)$i<;@7|@GG`o_nBsXXnI zh~|@2aYILB_zs7DX}~=RFe3kaff&>d8XkKc8PSLryv96{y*&SD?VtT|pG}hZE-;&7 zSHjs~wanQd+%)*rSH7`#QOg5H@iX6->zNJUqD$-#rDJCU_u*v4acuKu)k#gn?L!{4>x^J;1g zHz^zvmCI<7)_{-vR(t#4IG?U_=%eFlhL)zu0eLd#F#4=%!m_6NU|i=PEt(x=b^wMa zO|r@t!Z=ue=0nL?C6{|_K+>S7Erkg-wAdD8vsGATW0lQb>p4GKqshGIti0xr7IT7a zN1nyF?#t1RO7J_kNRaue%1Ji#a5g3!a%13_*vCl)%jlOIEh5!P^p z?Rw+~W5U6>7L&&qO2+UcVPBn$v(}bl?D@rNmmiD{)~!qrOq_RpO!`0DC0}lgWPuj+ z^kCuCq+N*#R|h$8FpzkO8$LFq5aCHKzj#5nzEqK1kby}48TDy|3NIgg^ViCW%eOZW z^(i748hO%#89w8*-axQZkMshk79#Kobha@%0bYO8N4s#&542c>=D%~5HLy;zpcODOKDB zgQIP3VOx+|Ig;mupP2QX^=2w()?a>g$)$N#p=0<|cU6NWx5`p7Urx7vYNPf1uRix@ zKmO%`{*iR^nJLL+%w#zH5K7~O9js?GYP;_tV*2a6GmAlPWqCN~928OP)dq!=K?H}(nG zz^h08)ol`Z%Olq4YwYA`j^1HcBp{4LxoG>Ca1-HclU3eQF8DM@p`GMXnx-k~tv74apnOUQmNi*U(iZ zc3-nG(W!v(_pP4`(|>pBlV>1`kO%yoUonzEFwqnTV4uQb&v)0c+copiL7`_T19Ejy z++1hQ&94Gjn&Uo2aE^#~@_~b5OsN;qI_q(BSPap6F+_kI!Dqdod716#8H5{ZzUmBO zWE+Qg5Ni~fH%z9QG!FqB&1qOj3d(>ReNBao-hj2meWs3go=J5gtOoHjJ}=EdAJ*Us z!CF3owBeJexz={k*BIOaCSU7hKH&^ZjCr9`O*8QTXyY+dVW|+L2%WLEaIlegx5ET` z4|wvEbeyhVxy{j9jX8pu{^!sC&__SrSbucKH~wbLw`MZU%W-xst7e`HijN2`%_pyn z{DD6`_(`7Y*Kto;%NI8bS8Es9CzTd9B>fO4o;L=HZp7x`e`2PAu;SxS7r2@D@x>bi z3Ve*@lq9-8VGkOb%V8W(UOj1K7@KQr{Km}qZQfj>-8Ezm&nKUZp&-Tk4}VUK+d5?I z#48?{oNoMplG{si>c?<+JcYGabI$?!HB94B4|9n`7J{x}av;BVNk&`pqbfS-W5nZ6 zFGz_TbJMGJ&rxQOTfQ3i-(;&jGja?OYsw2dL9rq)*at;7lB1^AXv+ zvFD3#i!nvfrb@No&=&Upx;vX#Teqw%pS|xn_Z9`zAAy2IqX>c~HcV*v6B4zjHjN!x zHtmR#XiV&wO6(XVR1pxB&=6AAB>_#Ow5n_v6GB2vB+-rr6dDjvP{MCfQYV4Lrj-ZYyF$^X{iigd4 zsWK`IdS?PA!d)TST#-mmp7M8L%qfekcHLkE6wVQyT-iLih$Vmq+_vVP03xV;agDh@ z2Iay}1LAECyhWL_a&*atO{7Ep)Keq}1FSxY$rz*bf+95u(}TxNzIbn}F_+|u|F8!b zozux@ESAWNP+D;Kr3;hewb|O%FMb-%aIcH-&~T^A^n0-!fq>OI;b1FghWc)Vt`XtH z5=T5=6y4NLf|rC&_$_6~?ll2dC)@Fa&Y&;HpgK$CO}Hy0=w#h}HYKdY!R%xUQvQnKqAru<&k>lbpK ziPB%EFj4sCeHfGv5o}gGbN%9ki1AWy=8`G#S3-P@Xp56p6XSPddx()qhqe9GRPXzLO^cC`3AcVpC&FumJ?G}JtD+d%K#nDH^eKK*RcyhqjA2gbSc z4lnBajTJrksA6L&p-D4;#*sr$3OzQD10H*|5)@Ux5Wt&SX3faapeIHuPfpW|XaH`g z9YS4O29X(095k-2UoayRZ`_kV*7{xBkx!j`+Y=vq3n&4;8US%KYJU?HGQv+!Gv|&f z*B;;bUSB~s?p>{Ay$Hfqli;>4YVnXY)3KW=dIM+#{rmh~w_?>Z8eicBiAN7kT1Q3C zCqtlBB>ov^j)#qUb8atlO~AeT@cO_0zW4sDf-mqPr#4~pY@T*fAt@d%4y2>uWVy+q zrhG2bQG?+uj2*UQZ|)s?=NJ7|oRR13A-gT$tcI8egCBio=A8$mwIzZ+Q_x4OL&y?~ zIq+*cD@V<&p6>YX=B^y#mdPV}Yz-YMd?laY3AMu0LsIcbXTd3l<7xpor+3u*M& zsV09|@uS#MHXnwKPt7@3t>ZokoQ<3OvdNPc+OGI{BurB>BLFA%X>RS9{ZF6EjG1df@W>%2gxN*)E1-|&!9Fr5I5MU{RTSu)gBP}_Q|3bmw zd*#w#Ke+W%2-u9YABN#~)jM`o3?b}SYu#rKHe7VCyz=Cu7wQW;%BpPu1lzj=OEE=4 z$-L#*^n8}b&`n_z0JG1YH+VM+cv|G;xK2p}@JO-qp!5AFt#Yshk#Cs=?*+*uh4sQ! zkvYELK^~b9xT~+OtUV&ZEJq==B@i!CHxDr6R~}&;@;J8Yh-yM~qc3??o#EG2Axi<<@qSm;lOG{hHN7W)WlV zX0<&~7A8$*5Z zbPiAcO1D8~Y>17k5oqYJFS#;LEY}@WocPi-yGd*xohUcn;1j2BQZvjK?;!FOacr`s zspoTEG&ZE@P*Ep2bMPkuu_iv1VAF`(kG3>f7nC_QH$IOB#+RGi0iSt^tjD~xR>GYn zPUFOvvu9Sf24JcaV{nAihFw~G5NAuec}C6#2rqSsp1kV|Y{#-m2tjazaN|+Vfek)A z!@%r(f|wXF3U^d#$$hwui{}s48s<5))+HidLqdn81msyg(ko{|EY|TB1q;7`mCB3MJDE5beNj0sFRF_u^1;$M zUS$~#)(bG6{I#Ltn@2OmM;o@$n?K{^NEaC=7#pYDy(OOJI&y1RtsELMufIMqFt5xz zKrkEsXwu#IVU`Al`pLoo)Z+HI zWZ3dp-G#2aDz$|OJ*YTw{luwWnutcbt}=1H<}{*l)SiFS7S|Xq-w1EXbgNh6q?t&6CLa8QxZ|ml+E1O^eSS)kEbGM~E#x|es zjj8k8eX$3e9Cebgz`-$$n7c~iKe_SI4?bSO2HbXS#Jm@`i*yJI+r-%L<~*2I`25&} zdElrq_N6Vpc>bxME;hynq-!%~8e|2T%-luYNmOv5NRNNde{AS;C#DN>lZF^!gG(|d zY1mN;l*qSddV>=bQ9=c}n);7G;l_bBj|G{3=jVqaL99F18=QmJ2l_dOz2hgc0gW#p zw652VK{cU^@4RA&uDPPCv%`s9n0jQi`r&1|)B~#D<)p8T@(zcSD&^xU_|KO<;a^Uu zmm7ET6w9>dwy~kx`Iut>%w}j%PmFX;D#AE%9lvt_ZQ;0#YWf8|^7_n3r*leC+A=t+ zA`%xm{iq*xTuczK6n>f$lY2Dfu?W z3}*9MVo$Gn3ow?d;5vKdbr6pm!mOGLllzwO4XuT zPJ7f^M1k396F}y*t>XLy7;qr8<#CL#->ubxip&uwuC5#*==?e7lYi?0ZjonAdmbVs z3_9zg6A$9WOnjs2`K#R)LUzJP!)}kuS?|aLnsDt3UO0f$vhIH2?#tf)@gsOa2Kg^a zES^R~{5<;pM8>J47Z!RJEx^HMHf^)+yALb93LAq!yqkzU=KZ0<4N)QDF8*$eI`oQ} zvdWT#x$)QMG4qT{`QBZD^<~S%n2QqvHZ$5@d{<1dcM*97d&lDY zSpke&?ft-TxXhNEqcrCwiaB?^ecI#Qx4t};1F>w$X*h_3J3>AL%qb{WTrrUo%UBtI z{7vZ^6Bx3;&hu_!*!0ei3kwQj&OlzY(qdjcyfna3y60tJerIQH-t4Kurk4clnV0H1 zCPHFJvo?%F+;c!wQ_pZLjvzuucge8xoFbOQ-uL#5AB&YQV(lx3QsPWK-{41uN3RQL zk_>SbJRH{0sG>>eFPL{ z7av8jfa%Y|RJKyU}weV+E}9HHKEo+6dKcc6owoO#TWhlaG`Y~wj$}>UI{^2 z^KetaZdlW`<-#m3IlG5~s7>PvOg7Od7|fHB%FHK%QmU?|@|wh`;RioC zNHuXqCNXsqN01DSriEs$|U`y`p!aAOJK)UU>qKblnX?#UZZ?_T-G>*+=6 zpArnYkwza}sLUrp#;vQ#%uvzuCt08X7BOs@OksL42cff&5_2v6-07Ss{wq9Akc)(&xnw?{GGLNfTjXX~c0)Q0uc3c?nOK>5aeU zjvL?D0Yk@=r)*Z>j6li7fHpoH+$7MNMTtyb8$ZYmrslevx?N8&k>UvZyC>iK$=Bca zzw7YDIzDC5_9a5&CE)YY&%|@M$%Wka;_Ih@TMWu=GhyyGPTexX=oTk&T-AzG)WQvi z7R6M;F%P~QPHfqX5a+m?NtCTOK;%ho?o@6UJ^7py?AgUvPOC59P==fL;^2ocO<#rG z%#$Z@4(1n?_;6{Tm#7-%BB3{57JP=VI5&HF_$BnczuP}i1B}L^GtIT(&Mz$IVwwSqYcUeJBHjs&HdnLlGqjk$T>q6pCz zJ#l)E)}ml~2Tn zpZLL&V=G=uh)ZNQV`Y;wTIxva#%3iN?#LT)*#&Zl38xFnJrB!^v98uVePqRz0gva5 zJmLbYvcNJ$cK`6~>HWt>_`-Gf{Oz&(yj=5TP0qe0U<2?hB|}yOMIa%oLk*cx3fi2w z6de;8I01~6#mISOj$>6%FvSjjxfx3;A{O?N?T(8GZazE3duN2IEKJI;4T!l)NgLnB z;s&4{k%TKe5SxFFnDW5hKUagy%?WQfD)o8UOU=lam~@OkHuSzs-4DXbt2tObK&8#T zS7srlD<^;=4RZ2Kq~wK90FtD$586!$aqCh7?9p|ja%0QXyHs4|tDLO@&?#NqWJ0rN zqYq{_J~mw}YIVg@lLn?e6nP-m&%}J3L=6XV^n6@%>@hDv?Kf4+(8N)MVOng8iLLLO zl>u#|EwVY+hSO(@N{>Kd*8CZCd~%IIdyRT7>ZRCvz^0GFG9g}-H};Cxp-AIowAt7G zGC#E>u(amVapN!FIe)`+Q>C%d+_2!ZQNIZ%5q$E8KK{NRAI%Hb@xR#KBycYOa}93r z^t1MRvLaxicoJqjDb-}a${5pbWv4>%w(n0AwF`rn7kqhwGQKW=cvy3sF%iUQ3a%X& zX@R|~iH@n^z(M@1)(Y!47$k^>lb$s3-#gFhj80rHI75l5cQCN_A~(AbVBfERXk7gE zaA%B@AX;CDBl3+fVyX`IF3{q8u?3rN05ilQnrjCk~u0dmg`!aN#R#)bq} zZR8B##u}0|8PY=lxZRj%Qu`9kSP;;F0oK_-h_y1PY`}(^_>O!>QTDtpf4~?--@Mzy zwYK&%X^wh=K-k!J^;J1Z~ye+t%qOB+Wj&Y z1wX^&s`p}}56sG><3DLzU`hh6s+J@3-5adJCUpj130-!kyl^wZBob7K_kT?Efb>Un*vnFgf?8nDKir&!H{9&wIf zdboyF9(loae`16wwmgv$GtD_Y4>=fbvtYO)_JHMiD?#(dUA)#g5JbA@ zhrJWjBWIW&2L9NmKJleL%=krZ_wT&<@M{D|u1~+nD|63zg;q6%pU*9wWx|4*^zEI8 zgaYhO52?D3x!QW=6y&E)0f#3(`e4&YBm^_u+f^U&(F4P-7w2v`nD%7^JbA=_&k5t& z(D%YnAdec2RaWLj)tc2S21hvgI=eXblB09t*V-OXTd!yXpsFnuZZo+vMP8cN6ET*}!AmnxW@hx&xi?<%Y)d2lf~ToA@KQ{)$mb z=xl3KnUvaV!TACnZaH`3g28d)0c35N8eaq0IP_mp%a41D)0nj#J!=5IMpEXpDwYFp zGd^%!$2W88Ulu@l+<+SCWnW$WV5Hsp!HMRnhO$~S;Y*L5WtB5r6)9fkb=`~(MCWN zxL>*X;H%`u)+Yh@rlA{GoL}P~JP1_B4T9+8og*Ru%^;e|Ukb-_J{8p7b67)`~@HLsfT#-ziFjaW(cStfzR=ipZSwt_r4#zv3Mbe_wWAZ z!;kOAa{nyX$1^gU>{`~xM>e6Td;OYf5<`&AM=n$@cxsUg$AbH@hLJJ0V!T|a$&GPz z@blp6*_wqcMBYJQ!$yUU2ODfI9+m)tez93_@`AN5rm+~9IjN5oKJ%|E!W$pM1NPF# z9=Qn|(vR=3MR^<4>`qaHS1@CrI!~RxG@X(~Q5sa>x&^ z%-D!zJ{zpul9p>6mlyujvQI9!#C|Mv7B=>flA0r9yy=kwF`opCR2c^4$)M&)E>R}f znt*pw#z9?(!6zyl!*T++A!wAidPIo>Xpv9+#u=W7WNSZTCNU91kNE;J)@V4jxEVK@ z3k;kG?W$rqk*PPP&gyHby@o+y>xMLJM+L{Rhl5y~KrzW8dS!}{R^NW@&lx^ykUrLg zxdG;PUheKb_K}a=y&cgD-EuR2_v3H<+T0anT|NDhO^YJ*!O?|x`qg!rP<-1ImesJ& z4#+QYaQVgq15R6gtgLbLrPXk{X|dqhtjb%$+IsTf3TZ9Mjt7O0q<}!-xtmQd;>xt) zkPC{9uuK^{z&ECq)`E)+EVG#Lav9sP%mk@2UjH}~i;P+99oB;U;H!{f#!k0ZV-}e{ zQ3unp!WhveR)&bZ6HA}*Hhh&H;rc!98XjU>^@Ob5$q!rdB|hR{*1nvXk57B-%{yjL z5>UQ!i8D5>o3;&iBP%%;6$z{<6<$Z3=?FUVv=^S zjH2L6sUSwppV5ed^ILlk#sU$h1ERzBI5ZgISdV~d`0c3i*F+6As6*Dc=_j7?BW+pq zy{wYfd_%g4bLw>WFIA1 zYFVz$AkXeDPVR2F$hm8=*5TlpA1;WY+(Bindp@d=L7#>36HMM52k98@X!)2zW&QIy zOgx$X8#JKAksQJ`CJ-14b}R_4?Z(hW(3f4!8!TSDV2B4J?p$0I$wJxGC^$0H28>@A zq*=2LeGg2c)MaYp4>H2#CKrm8Un=} zL{-PR+We8I#Th>+!ae#NE$!;DUn8*SedH*Ghmp23{t;_BV>ekSm`AaenT?P7H;yPp z*w;kfwZfR%V@&YQon(p=WbpAQYH`ez+=$0gjq87G8bd9*#zA(z=9SDWUGv|07%0Ns z{r7zOpWpo|*cZLsf9U;Be&pTH-o0s{3I5spGBPnQ_Y6~1&n$(e(O+e@_EUH-ekzhX z6YfrUC@W!$g@ls{XQ|3b-6G&+>GggR{@6geAvOYzT-~#o$u$vqm0`onTiL?N=F&SS zHfS1)e*O1uWn#$&=)xrq4?1GgO#x%<;p8Q3({R&@pLg?e(=~~~JoLo}a|xRO zTs7^$AXAQRnsK7SoCpd@b(xTYqBb{!;!}&=)^e+@eW2|)j4M{pL%D{|bH(6}uoGvvI zN4&M3o5yQEDC&0!8hO?Hw3lu>fbPDN+gIo~?tK0hSoBKdq zF52J=D3ZpH4bsN1eTwB`5sW_Sn^v~^Yu)rLg1v_@u)lK3Sf>VlF@YUahdEBHATM-h zJv)h$jW01B9}_xkxRJ{sz+_hPRfsuB6+B$E*L0ne5WXO%IcPj9H7*MVV06Jw6V5Kb*ule(bC0 zy1EpHcWI&mvw2n=?g2iEzggU@gYiKECY5>Y^4$G{pZvZL{dA~bipFx~Ed0y2eklng z5lZ{&mo+DgLxK2G%~nF<+%H51-U3jBtjvs^b0@~8G!O33b_3jc)eH_EkZ&lN!=Ae< zHn6^-9vuew-p!6acC!?W$qiH#n;#~P(Ti03@Z= z2X^KLC*<%v&jhA?G6!k|8-_Y2m>0X;BTUB{;*sJ=CR+8HZ(o}nNj!E}{!UdB0X}HN z+YvM3pBCY|+WM&@#)l^_^ao%!h3&n1?w&sT#9P1g@V1*x78P&!Kg)Y%7WJkCEdm9i zIOwyG96*;rs?s-MJ8qR`JRU9F+RK50GIvpG<9+^~SR9~-J~ChCF^5-SdjR6lakBE2 zi;*t^Za>@b{0gM9wKFLR!&iTp(&l=R9+4M^3l7&^7&S*rP11+MSZkoI;W^(JYmX1? z8V`Rsvi_w}7cLy6J?i1w$B=uWa92yMrj9iPTCnkt5LrV4A0aiH{JXf337&(XjB8m& zB2J7>0*f6%AcsNHcM$?RZIcs?(gq@_*38if&X|}y!azGvY-6cyI**C^X@Zm{qp3L3;neZ zrx<(+J$DMbA^3jFTqKmaZ@RNE@@VZO;0e|z+4Pjq!p#Y@UZ*ZRHTU7~C2|qP@QypU z{3d}70!}jaOPV2z$rH*C16Iz751;Y4p@5rRDDK;4V zW6g*oF=vz=&Mv(g`BsNIIpmv-@ODp;4D8evko1wkZG^^9Tb%lrLNG}ntu^sQKwGW| zh|~8O6~>Ny^SGzZ(=I#i>&QXJ(Z-lS@J-N^PHyUhB258f>Q8d%&mA{%Y*puw;X312 zPNg8bVmxo5ut=(_>$ydakE)Lip(YmBWD0@0hj79#wG3G{!-nIk;_@#S!e(7b3fmcM?&|nJ$dr#2Ppt;Q>NeX44HZY zqG4g>;X=a_`RFub8u*YNf_HQ*4zBEfuxkZtG#~vLw z=oOnkF^o@nW_f~49DR`S%r{SpX$?3j8SEVrMdiZ86f>{?(MPr~lQ>&j z^!_Ro;F9-55vD9Ki0x!XZ?$|IV z1e(bh0l;HJ5&CN~0SfNj&QKOBfg~8_YZ{zPh*J^AF4QxnmQaID+l#z0kag-5zv%lV z!+1e59!otr%an1?lXWQlq=}rsmXY}Sg}m{Pf$<9k?qfp5iE+ua@t?v>T)~*1##nFy z5ay8{Gfg$n6nFx-d0QLB8{+&vgVXf=_ky*I%y5ytbUC0=| z_}$sa2sM8h=kI>*=aTx{DMm7U$me`s`>H0fHKTY}p5)sH$5TQEJZRH%(aFJ&%^kGF zl+2f4oH4#V;b8bELohe8{&#Wykp~wO3#u-F_obFHREl8p|Td^Tlbu|>XZgp|K(x~2QQXE z^&)3XYu!CpOd%LNQ#Tft32jJgKe0r7&EX{a_LwY}v=QUy_|jSJso;E%5gch4^2lK% z87UZfI!q5~CX+v?Zj9r27#2G$bpQu$(zNMNF3j>I{EJ`wRqy}a6~9dVqmAq*zwOz- zzkBzU*WbuX%%0GPC(k~VH~v4=)3%9muD7r*?@TNZh1yC@&phzbLBJ$UyG;0^=({j_ zjr9WO>h*-&5L|a-*j-#9keioOvlhoGps*tx-;Cvz03TBZ^*I<%c;v6`*=)?T7Y13- zpm8sAH_@H))ftev9I=+IT92!-78@r4V}}yik=JK8r0Dqp$bhyc4SwQGzPul$Idx#u z!+^9iHGT#F4nf8d?6eDiuXbRKt0oixeC3Xz!xwRRItPGUUKBjGmKlzGB88xFq9KQ& z0B2yBAFe7rujmIm)oU!kX*cGEXp+y_3maezn!nZ_mY0b>*I!~fab~d8#(xu66(&%7 zS+9Hz68FmC%w&8pu>Sa(@t9v+2R;lZs374zCw9l-e0cb-ANc6q8{_h&>K<)mME=^{ zD}VEyU%LC1H-9+=NV2?N{o04`pFDkU7n1eJ!3)E?k5nZW3B~aSCvOll=8a;`=mQw^ zTu5^*3}Mq(r}5V>_ACto`I=Z_di1;^bM zDD^;a9vNng+vd;RUU=Lbo5w=S6(HtGs}N#IB-l5&Olxlqav&-j@d+PU;`T=!5$=DD zB9;2D&557Q+)8~FJKePO7i$FnN`~CS_r>|1~OgJeBy_W*&!`uaJ z89D1wc=GGhF{=W)yv*{Yp_qV>du5>ovyb5>MlkcpEW_&rcXuLgF!>JUyLo8^+&P<4 z8gaHofxqPq$owPIMmX5w-N445I7sKQKQy2we4%;V@H4(g311g&RLDlIzdTVO>jiVg zP*4Dn@x2auT<$`U9fBdfzyGDkc zMgl+iv8SKT3HsZg`aS%Pvg%v#kxTrd(s!5AP*6YQuM>_x>VezPg{y}$JN zpzFD-!IUpaW3QufvbV)s4#XD)8+Kx4vF!VZ>v0zh_CR;tWtd6%`M@b(j}}|_iL{$W zY(vy@?KkeuipmZm-BPui| z9XEe~#lQ*9IJ7~22!sK>wMSUFT=U^7b^(C-H;( zz2Lxi*E%_8P)>aEu)Py&HdX}a2QzbkNFHrYZ2sXk(rk2%cw|!_@u@-c4?=!r*j zjJ)R}1IGCQky!EJG!JAI7z_5tYvWKm&j;km6T+Tjrvk=Kt}q1VKh~9N9ae7q6H2{6OvXGx43+!g0n0 z$Vm{D58-ydRsO_vcmL^s`~4sIiwk=h``_}8Y!kVA=h(&qcI)?uyh^hJDOzK%H!#>5&z3jw6SBjNd35p5*tx~lfH+EQ5)=WoYr_5cSG_cAZ)h55GzG7 zFYZpbJ58Ohi%&13r+)R^O$A*a{I@B2DKIT!x#>qFl;;5a=Bqw7%EsrD5yKlh-{g;o z9}p1VmS+2?^wA5h&aRw^4{x|#zvPKvG*KQs!D0eAG3E>1I8X+__ytxa!)-utOL|P? zw0^`9W#fSy?BlsqIv#zxm2DmyW9`v5F5`R7miSIhB!V!H;1;U==07<;0>OV1=a}PO zjuRh(!7`-9$AA9J_kZw@clPogSvLRA_TRtb?tk4qdHUzxedEdZzVTD}g`YQeA@Nr- z?w`E(58eCMGFo|-QJ=MaiIggdo-?v1#-8f31NszheGAS--{rmNgqJIi)7{U6O}P93 zAYZn0E(T6ENHz{OD8}3&fWsXJr0ICv`~H#Ih|AYI9hmF0i!kF*_+Ue13@bLbao{RV zeh#$hmajtW`+{--zJ!Bx^Ea17%#V#H{@RZ7$XLAa+Z*qxNMwm^H?g%R78Y`eq;;ZS zgym+cd+lO`54F`x<9m$cKeEBdQm{tU@3ca1rzO@Xaj|qZhQWINJfCaU`k$Z<{TVdY zCSblpsa%#o4eOZXY$zb`jiFh;^n<7>Y8bAL0J|37%`Dy-3n413T5YegcR{l3*|x44Vsf*~GemMxJ5_nTu{?hO%<- z5cHO#bqG&HyAfqnA3>c#jQO%q4MiO`-K6pRoE@=n2e`@8Sn!tKl4Hpky~4qx}z z-u?^uHSO1*z5mJkU;XkF*k@4+-IJa>w`eE41bXV!rqFBsXQMX@sa zIm_zh9O87G6K1zJL2P%GWwT*HEEiZW)M)d~rK)b?FAOQX-E@>emR4+z477o}i%z}r z>KWqWP>)S7qGAAeJqNcx>BNkrc4KE_MaRb30MZR9VVMDQ9qMFY8M_&&@FF`G$W3a3 z=gvo(d@N-6k1h@#$A4*Vp^TqzvHLrpdHn-_|9Sb#IA=Nkf3=_Z&ZnP#_36_;n)k8D@ZCE+Ri5KT+8!Pxbi?fwWx& zgz@kZvu7D= zqY!)s6AxW~$CE{lucD0~t9iNFjjTL;tfH?UgT*P0{YEVBPi4%3%{>tB*f!GhQIs1$ z!8*f^=Dhlc{GS}3)tDx}hkTAtSHzmHNa{~D@yFa8G63&gqoh#)LZ2S_tpF^x=#^u` zp9jy2*ch-B@T)(1!C;V-Q(vIqK}9ppwJSrlO;+9k`;m?K0!51{$B9QT2#kL>iAyT< zIp1(llQ;;_yw`xFEz4=Gd!)Bo-pNeLfym;aF$8tBnKDGJ1s7XnX?!?p`gG5&SU*+ zQ;0mM zfLW6ZU&MuyBKigv4$)yFB6($&7~dtxV2wZa$`PgBd>EK{--Op12C@1xfX3iC_Z+nb zmIe2v$3|x#1)CLgb8K*bal_< z^K5VA8)xk0SuFGW`*(9U_J{w?CqD2~D}LE~GXGs`f9!8OeE4&3zx7Qi`d_+#^~s;O zd+)oizLLLdcK=157SDg{%Lz{7#N=_G#pyNS0&X}4HlW*$swc8`+6QrCoW?`DS!PiB@go@N-o;WF>HmIV`Fs~7@r%_$mNK@-;-q$ zjQMFZdFlgQf4Ffr68wRuGxn)CZo`is28Y; zm793Vbqq$|cnYJQW2h~mP0cjBN#KTe7*2lmEBzxGCV8LkU*vC&{pD(ZZyc|R{VwP8 z4Ig=U?`MDU?QhJ*`3+eyU!UIz|N8q^-~GzFr}tla_w+6=LZ7_q`O4FJ-^ZEFEQ>~2;*F22Or{Ww4`5bl;FkDQSNA@M#VeVVz^F^JjOkRl7*?Sp|=4n5Rc zm*GdqCI{WA6O#$!M!$8$SM{;Nkoal4lW+XtRl_DDpaVBFVpWKLmFXhz;;X3VH*t#N zkj+RVaO?&Xcc$(~Zc>qyufOj{7x#Oi|381f^(=ScK4bs@002ovPDHLkV1lJWD8K*! literal 0 HcmV?d00001 diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_pressed.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_left_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..76efae02cfded30428679dd0f908715c0fc0f44b GIT binary patch literal 34649 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 Vy+b|WaFGB2002ovPDHLkV1l`ci75a8 literal 0 HcmV?d00001 diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_right_pressed.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_btn_right_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..f5bd232a6610e473e4accd62ef0c8c5445430431 GIT binary patch literal 23950 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 Qe-`@He;hB?T=04Le{dbMVgLXD literal 0 HcmV?d00001 diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_loading_nor.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/routing_loading_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff5309fab43668850bad18a5c5673fa0941f462 GIT binary patch literal 2221 zcmV;e2vYZnP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91OrQe*1ONa40RR91Pyhe`0JEvRV*mgM7fD1xRCodHoNK66MHI(9T59Dr zdnoxvtqe6t%@WJP!aih)QJBz!u&57-ls%wAKNUem1O`c95K0fr63hA!6(VLDl3`I~ zcFk^TYWHTE+D*Ov{+F{4`<^}f%*@{B?sGclELhCmYt~vb>wjkUUNf`r&Go1v>gecb zqC2<1bKnW^5cnj#2i^*=f!F48xpvC>C4lM)FM#*MHfly;UfrTa@J;Yq*q4@JaC%(< zN5H+|4ZcW)^xvpAz+MRjpY-yvx&RGyE`v`cMJZ%=gzF2k05f-Gl{`-;xO z;1OS=r26IPuy@;xh%+%d2%q6?Y&K{n)fjEADzCIsBWxOBlnX2&GKwEzRC%E>d#e;+ z!_3`DB^{p1+R^wlN4+j;{F<_x0ndcT!UN%B@bB;@_#>vsPRcksC$1ued_W3YXH##$ z082nU0gp7aqLDKhR@T0j@;QJzV9?udkfjxw+DYp(V(&F20bwB?mcb^lik;6!uo|0j z#TDG|GRV@3n$tRPv3Gt;68QZ%O!E3}!|palT1(I&d}(BB`koueQkL8BKQW~bCv&F} zMu6(fA}5bgB|WcR!bjo9A-EIB-i@jzmb{tR($laIL@7Ih)tXJurZlt&pwYUnxapIWeKi3uzAoIEMn>d_lLcA zJ6zt9*ChzVWHN;g_9M6>K_%BOA{)>B{6OYeF2=|Et~Ru#88revKW~GmV-G&|x%#k< zFdVtO5nbBrg_0>@y$|`*E)GIE|8o5Rfj$$Gxm*gU04(VXz@dQFPd6^)0$91;Wa>}E z7eRNxi>bRB{z6I?`jGmG*t}}dGgY5$5+aL}N7P-W1W*rU0;!x~urLFQrrt zr!umqkKWJ7lafZJiS*WXA{W3~oIJTH?Xjr=$aZwZ-9fE54Npn6p+lC~A5scoa+#9r z!v-m?m0UV^EJZu9rnG;UN{vvhd-aC>8{UEZA4(^(jxd~k%QX2BZx=gxj8}RuzAC#K z;?c^ZjhML12{bQq8DVnxf|u8*ax?Ye-;-x4*Le0y&xi$p^}VNE)v7CT^CIT{ofs^HZMln%_LYg3+DP| ztv|)B@b&N|a1*T8vo;35gx3Mo2FeDR5CA|eW__l&$xTDnK%jv@0|8$IVjucEle8V9 z-34uZwDAzH=(5H)uEVo z&6WyuK^%%ON&Bc2dY0C0zhQMSX!RT48<)7BWzYwE#TslFzF<^m;3`gQ z@7hildV^@B)T3#L0PCHyCu!|dHeXirJ{E6%1lS)IC0lh`dz=3(>su|2wF%S%<6flYc&&h6nKofp9I)vDSD*iDILJp5^W-w-9-WEr0H`2Z4Wa2r3fYzDY@LP z#L03O#s8ZQZ$z!5gFNgoadsZb1%T-`swDkT;yVh~`K3;iT1Y!; zY4?JVx>6#*0IDx;Zh~)sm8XSiCpW7Au4Z;I!ohh123Y6e;Bk0(*pcB{tASMpc|}F^ zUq7%8ezdC5Y|vkV9H(@mQroc+2Q;P~Nf)qWI|qHO@;{C^s(^sLXmDutG7Z*e5CI*h z?o;~tLm((sb}qh4DHPSs;@&p0!Y1?RjQ;$u8fYq=m=1@*QoriDwpewrH+fI0tpNf8K1?TXx_x@~i`w(9u+rqdMfKQ+PTSI5qFr`m3u zpRzQdQz7e)vom14cK^bm_VIm5pP_q^UNG=T_;Pp>th^~P(RXct+WPScdM9j+Sl}`oF!hoEn<%bDPgqcKp{|DnT|(8_nBQ*1z-fP5w^u6>Wv<{ zWmT;T!15941!DUGP^!D&4Z5fVRSjT_GUZpx;onLCq5N(Iy0&#;2^Z4bF60d00000NkvXXu0mjfUGxea literal 0 HcmV?d00001 diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_finish_task.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_finish_task.xml new file mode 100644 index 0000000000..485f92597d --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_finish_task.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_submit_issue.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_submit_issue.xml new file mode 100644 index 0000000000..c56f217b14 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/routing_btn_bg_submit_issue.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_loading.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_loading.xml new file mode 100644 index 0000000000..f019a97cfb --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_loading.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml index d0dd1cbcb5..823b8a5fe7 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml @@ -4,13 +4,27 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginTop="@dimen/dp_5" android:background="@drawable/routing_choose_line_shape_select_line_item_bg_normal"> + + - - + app:layout_constraintRight_toLeftOf="@+id/todayVerifyNumTextView" + tools:text="线路名称线路名称线路" /> \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_task_activity.xml similarity index 95% rename from OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml rename to OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_task_activity.xml index a3acc88b8a..95aa167e16 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_activity.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_task_activity.xml @@ -1,9 +1,11 @@ + android:background="@color/routing_verify_choose_line_bg" + tools:ignore="MissingDefaultResource"> + + + + + + + + - - - - - - - - - @@ -185,9 +184,10 @@ android:id="@+id/naviToEnd" android:layout_width="@dimen/dp_48" android:layout_height="@dimen/dp_48" + android:layout_marginEnd="@dimen/dp_40" android:src="@drawable/taxi_navi_icon" app:layout_constraintBottom_toBottomOf="@id/endStationName" - app:layout_constraintRight_toRightOf="@+id/cancelOrder" + app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@+id/endStationName" app:layout_goneMarginEnd="@dimen/dp_40" /> @@ -216,14 +216,13 @@ app:layout_constraintLeft_toLeftOf="@+id/startStationTag" app:layout_constraintTop_toBottomOf="@+id/endStationTag" /> - - - + app:layout_constraintLeft_toLeftOf="@+id/endStationName" + app:layout_constraintTop_toBottomOf="@+id/endStationName" /> 查看 选择任务 + 开始任务 任务列表 确认 暂无任务 From 6a31f56ddae4d487fd1a4616914763fc3dc41012 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Fri, 17 Nov 2023 20:21:56 +0800 Subject: [PATCH 04/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E9=80=89=E6=8B=A9=E8=B7=AF?= =?UTF-8?q?=E7=BA=BF=20=E9=87=8D=E5=A4=8D=E9=80=89=E6=8B=A9=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8CUI=E6=A0=B7=E5=BC=8F=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/routing/TaxiRoutingChooseLineAdapter.kt | 5 +++-- .../src/main/res/layout/routing_fragment.xml | 16 ++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt index 4514478d16..ae43cb3930 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt @@ -50,11 +50,12 @@ class TaxiRoutingChooseLineAdapter( notifyItemChanged(index) } } - mData[currentPosition].isChoosed = currentPosition != mLastChoosedLineIndex + val isCurrentItemSelected = !mData[currentPosition].isChoosed + mData[currentPosition].isChoosed = isCurrentItemSelected notifyItemChanged(currentPosition) mItemClickListener?.onItemClick( currentPosition, - currentPosition != mLastChoosedLineIndex + isCurrentItemSelected ) mLastChoosedLineIndex = currentPosition } diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml index 5647175544..7e48169c62 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml @@ -43,7 +43,7 @@ + tools:visibility="gone" /> + app:layout_constraintBottom_toBottomOf="parent" + tools:visibility="gone" /> + app:layout_constraintWidth_percent="0.55" /> Date: Mon, 20 Nov 2023 15:20:11 +0800 Subject: [PATCH 05/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=E7=AE=97?= =?UTF-8?q?=E8=B7=AF=E7=BB=93=E6=9E=9C=E5=8F=8D=E9=A6=88=E5=BC=B9=E6=A1=86?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/routing/TaxiRoutingFeedbackDialog.kt | 89 +++++++++++++++++++ .../taxi/ui/routing/TaxiRoutingFragment.kt | 21 +++++ .../res/drawable/bg_shape_dialog_no_title.xml | 4 + .../drawable/bg_shape_left_bottom_round.xml | 6 ++ .../bg_shape_left_right_bottom_round.xml | 5 ++ .../drawable/bg_shape_right_bottom_round.xml | 9 ++ .../layout/dialog_routing_feedback_result.xml | 61 +++++++++++++ .../src/main/res/values/strings.xml | 3 + 8 files changed, 198 insertions(+) create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_dialog_no_title.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_right_bottom_round.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml create mode 100644 OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt new file mode 100644 index 0000000000..b7de129128 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt @@ -0,0 +1,89 @@ +package com.mogo.och.taxi.ui.routing + +import android.content.Context +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.LifecycleObserver +import com.mogo.eagle.core.function.hmi.dialog.BaseFloatDialog +import com.mogo.och.taxi.R + +class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { + + private var commonConfirm: TextView? = null + private var commonCancel: TextView? = null + private var commonTips: TextView? = null + private var commonCloseIcon: ImageView? = null + private var clickListener: ClickListener? = null + + constructor(builder: Builder, context: Context) : super(context) { + commonTips?.text = builder.tipsStr + commonCancel?.text = builder.cancelStr + commonConfirm?.text = builder.confirmStr + } + + init { + setContentView(R.layout.dialog_routing_feedback_result) + + setCanceledOnTouchOutside(true) + + commonConfirm = findViewById(R.id.routing_common_confirm) + commonCancel = findViewById(R.id.routing_common_cancel) + commonTips = findViewById(R.id.routing_common_tips) + commonCloseIcon = findViewById(R.id.closeDialogIcon) + + commonCloseIcon?.setOnClickListener { + dismiss() + } + + commonConfirm?.setOnClickListener { + clickListener?.confirm() + dismiss() + } + + commonCancel?.setOnClickListener { + clickListener?.cancel() + dismiss() + } + } + + fun setClickListener(clickListener: ClickListener) { + this.clickListener = clickListener + } + + fun showDialog() { + if (isShowing) { + return + } + show() + } + + interface ClickListener { + fun confirm() + fun cancel() + } + + class Builder { + var tipsStr: String = "" + var confirmStr: String = "" + var cancelStr: String = "" + + fun tips(tips: String): Builder { + this.tipsStr = tips + return this + } + + fun confirmStr(commit: String): Builder { + this.confirmStr = commit + return this + } + + fun cancelStr(cancel: String): Builder { + this.cancelStr = cancel + return this + } + + fun build(context: Context): TaxiRoutingFeedbackDialog? { + return TaxiRoutingFeedbackDialog(this, context) + } + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 22c90c21fe..18c41878a2 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -6,12 +6,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.mogo.commons.mvp.BaseFragment +import com.mogo.eagle.core.function.main.MainMoGoApplication import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R import com.mogo.och.taxi.constant.TaxiDriverEventConst import kotlinx.android.synthetic.main.routing_fragment.btnChooseTask +import kotlinx.android.synthetic.main.routing_fragment.btnFinishTask import kotlinx.android.synthetic.main.routing_fragment.btnStartTask import kotlinx.android.synthetic.main.routing_fragment.finishSubmitIssueGroup import kotlinx.android.synthetic.main.routing_fragment.headerTitleContainer @@ -94,5 +96,24 @@ class TaxiRoutingFragment : BaseFragment() { btnChooseTask.visibility = View.GONE btnStartTask.visibility = View.GONE finishSubmitIssueGroup.visibility = View.VISIBLE + btnFinishTask.setOnClickListener { + showFeedbackDialog() + } + } + + private fun showFeedbackDialog() { + val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() + builder.cancelStr( + MainMoGoApplication.getApp() + .getString(R.string.routing_feedback_result_btn_not_sure) + ) + .confirmStr( + MainMoGoApplication.getApp() + .getString(R.string.routing_feedback_result_btn_sure) + ) + .tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint)) + activity?.also { + builder.build(it)?.showDialog() + } } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_dialog_no_title.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_dialog_no_title.xml new file mode 100644 index 0000000000..e6970921d5 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_dialog_no_title.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml new file mode 100644 index 0000000000..0a852f4062 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_right_bottom_round.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_right_bottom_round.xml new file mode 100644 index 0000000000..bd0ab9d1e1 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_right_bottom_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml new file mode 100644 index 0000000000..3b6f63de68 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml new file mode 100644 index 0000000000..de14625b26 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml b/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml index db87842190..0c01eb4938 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/values/strings.xml @@ -70,6 +70,9 @@ 起点: 终点: 往%1$s方向 + 线路可用 + 线路不可用 + 路线验证结束啦!点击下方按钮反馈验证结果吧 \ No newline at end of file From 69a853ecc2e3dcc35ef965ea33e6d46b042fef97 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Tue, 21 Nov 2023 10:49:15 +0800 Subject: [PATCH 06/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E7=AE=97=E8=B7=AF=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E5=8F=8D=E9=A6=88=E5=BC=B9=E6=A1=86=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4UI=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/drawable/bg_shape_left_bottom_round.xml | 2 +- .../src/main/res/drawable/bg_shape_right_bottom_round.xml | 2 +- .../src/main/res/layout/dialog_routing_feedback_result.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml index 0a852f4062..1188daedb2 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_left_bottom_round.xml @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml index 3b6f63de68..49c4e8d8f7 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/bg_shape_right_bottom_round.xml @@ -5,5 +5,5 @@ android:angle="180" android:endColor="#2F6EFF" android:startColor="#20AAFF" /> - + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml index de14625b26..2acf507da3 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/dialog_routing_feedback_result.xml @@ -40,7 +40,7 @@ android:gravity="center" android:text="@string/routing_feedback_result_btn_not_sure" android:textColor="#FFFFFFFF" - android:textSize="@dimen/dp_40" + android:textSize="@dimen/dp_50" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintWidth_percent="0.5" /> @@ -53,7 +53,7 @@ android:gravity="center" android:text="@string/routing_feedback_result_btn_sure" android:textColor="#FFFFFFFF" - android:textSize="@dimen/dp_40" + android:textSize="@dimen/dp_50" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintStart_toEndOf="@+id/routing_common_cancel" From 2eec82554348db075f3b33e1634ac6a420b71796 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Thu, 23 Nov 2023 21:36:16 +0800 Subject: [PATCH 07/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=9A=E4=B9=89=E5=8F=8A=E7=AE=A1=E7=90=86=E7=B1=BB?= =?UTF-8?q?=EF=BC=8CModel,=20ViewModel=20=E5=90=84=E5=B1=82=E6=AC=A1?= =?UTF-8?q?=E4=B9=8B=E9=97=B4=E4=BE=9D=E8=B5=96=E7=AD=89=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/AndroidManifest.xml | 2 +- .../com/mogo/och/taxi/bean/TaxiRoutingBean.kt | 39 +++++ .../bean/TaxiRoutingQueryLineResponse.java | 22 --- .../och/taxi/callback/ITaxiRoutingCallback.kt | 11 ++ .../och/taxi/network/TaxiRoutingServiceApi.kt | 75 +++++++++ .../taxi/network/TaxiRoutingServiceManager.kt | 130 +++++++++++++++ ...ty.kt => TaxiRoutingChooseLineActivity.kt} | 86 ++++++---- .../routing/TaxiRoutingChooseLineAdapter.kt | 10 +- .../routing/TaxiRoutingChooseLineViewModel.kt | 94 +++++++++++ .../taxi/ui/routing/TaxiRoutingFragment.kt | 83 +++++++--- .../routing/TaxiRoutingFragmentViewModel.kt | 53 ++++++ .../och/taxi/ui/routing/TaxiRoutingModel.kt | 154 ++++++++++++++++++ .../taxi/ui/routing/TaxiRoutingUiIntent.kt | 26 +++ .../och/taxi/ui/routing/TaxiRoutingUiState.kt | 23 +++ gradle.properties | 2 +- 15 files changed, 720 insertions(+), 90 deletions(-) create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt delete mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceApi.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt rename OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/{TaxiRoutingChooseTaskActivity.kt => TaxiRoutingChooseLineActivity.kt} (66%) create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt create mode 100644 OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt diff --git a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml index a7808094c9..3ab0402e38 100644 --- a/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml +++ b/OCH/taxi/unmanned-driver/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt new file mode 100644 index 0000000000..a19c466320 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt @@ -0,0 +1,39 @@ +package com.mogo.och.taxi.bean + +import com.mogo.eagle.core.data.BaseData + +data class GrayLineBean( + var lineId: Long?, //线路id + var lineName: String?, //线路名称 + var contrailId: Long?, //轨迹id + var carVerificationCount: Int?, //本次今日已验证次数 + var lineSuccessCount: Int?, //线路累计反馈可用次数 + var lineFailCount: Int?, //线路累计反馈不可用次数 + var isChoosed: Boolean = false //当前是否选中 +) + +data class ContrailBean( + var lineId: Long?, + var contrailId: Long?, + var csvFileUrl: String?, + var csvFileMd5: String?, + var txtFileUrl: String?, + var txtFileMd5: String?, + var version: Long? +) + +data class QueryGrayContrailListRsp(var data: MutableList?) : BaseData() +data class StartGrayContrailTaskReq(var sn: String, var contrailId: Long) +data class StartGrayContrailTaskRsp(var data: Long?) : BaseData() +data class QueryRoutingContrailByIdRsp(var data: ContrailBean?) : BaseData() +data class SubmitGrayLineIssueLocationReq(var grayId: Long, var gcjLon: Double, var gcjLat: Double) +data class EndGrayContrailTaskReq(var grayId: Long, var feedback: Int) //feedback 1:成功 2:失败 +data class StartGrayAndQueryContrailRsp( + var taskId: Long?, + var contrail: ContrailBean?, + var grayLineBean: GrayLineBean +) : BaseData() + + + + diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java deleted file mode 100644 index 7c3efdda76..0000000000 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingQueryLineResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.mogo.och.taxi.bean; - -import com.mogo.eagle.core.data.BaseData; - -import java.util.List; - -/** - * @author: wangmingjun - * @date: 2022/2/9 - */ -public class TaxiRoutingQueryLineResponse extends BaseData { - public List data; - - public static class Result { - public int lineId;//线路id - public String name;//线路名字 - public int todayVerifyNum;//本车今天验证次数 - public int historyVerifyTotalUsableNum;//历史累计验证可用次数 - public int historyVerifyTotalNotUsableNum;//历史累计验证不可用次数 - public boolean isChoosed;//当前是否选中 - } -} diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt new file mode 100644 index 0000000000..125e1c13c1 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt @@ -0,0 +1,11 @@ +package com.mogo.och.taxi.callback + +import com.mogo.och.taxi.bean.GrayLineBean +import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp + +interface ITaxiRoutingCallback { + fun onQueryRoutingGrayLineListSuccess(data: MutableList) + fun onQueryRoutingGrayLineListFailed(errorStr: String) + fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) + fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) +} diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceApi.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceApi.kt new file mode 100644 index 0000000000..f1857459e4 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceApi.kt @@ -0,0 +1,75 @@ +package com.mogo.och.taxi.network + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.BaseData +import com.mogo.och.taxi.bean.EndGrayContrailTaskReq +import com.mogo.och.taxi.bean.QueryGrayContrailListRsp +import com.mogo.och.taxi.bean.QueryRoutingContrailByIdRsp +import com.mogo.och.taxi.bean.StartGrayContrailTaskReq +import com.mogo.och.taxi.bean.StartGrayContrailTaskRsp +import com.mogo.och.taxi.bean.SubmitGrayLineIssueLocationReq +import io.reactivex.Observable +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.Headers +import retrofit2.http.POST +import retrofit2.http.Query + +interface TaxiRoutingServiceApi { + + /** + * 查询灰度线路列表 + */ + @Headers("Content-type:application/json;charset=UTF-8") + @GET("/och-taxi-cabin/api/business/v1/queryGrayContrailList") + fun queryRoutingGrayLineList( + @Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId, + @Header("ticket") ticket: String = MoGoAiCloudClientConfig.getInstance().token, + @Query("sn") sn: String? + ): Observable + + /** + * 开始一个路线的灰度任务 + */ + @Headers("Content-type:application/json;charset=UTF-8") + @POST("/och-taxi-cabin/api/business/v1/startGray") + fun startGrayTask( + @Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId, + @Header("ticket") ticket: String = MoGoAiCloudClientConfig.getInstance().token, + @Body data: StartGrayContrailTaskReq + ): Observable + + /** + * 根据id查询灰度轨迹详情 + */ + @Headers("Content-type:application/json;charset=UTF-8") + @GET("/och-taxi-cabin/api/business/v1/gray/contrail") + fun queryRoutingContrailById( + @Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId, + @Header("ticket") ticket: String = MoGoAiCloudClientConfig.getInstance().token, + @Query("id") contrailId: Long + ): Observable + + /** + * 上报路线打点 + */ + @Headers("Content-type:application/json;charset=UTF-8") + @POST("/och-taxi-cabin/api/business/v1/saveDotDetail") + fun submitGrayLineIssueLocation( + @Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId, + @Header("ticket") ticket: String = MoGoAiCloudClientConfig.getInstance().token, + @Body data: SubmitGrayLineIssueLocationReq + ): Observable + + /** + * 结束一个路线的灰度任务 + */ + @Headers("Content-type:application/json;charset=UTF-8") + @POST("/och-taxi-cabin/api/business/v1/endGray") + fun endGrayTask( + @Header("appId") appId: String = MoGoAiCloudClientConfig.getInstance().serviceAppId, + @Header("ticket") ticket: String = MoGoAiCloudClientConfig.getInstance().token, + @Body data: EndGrayContrailTaskReq + ): Observable +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt new file mode 100644 index 0000000000..3047ebd492 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt @@ -0,0 +1,130 @@ +package com.mogo.och.taxi.network + +import android.content.Context +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.BaseData +import com.mogo.eagle.core.network.MoGoRetrofitFactory +import com.mogo.och.common.module.biz.constant.OchCommonConst +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback +import com.mogo.och.common.module.biz.network.OchCommonSubscribeImpl +import com.mogo.och.common.module.biz.network.interceptor.transformTry +import com.mogo.och.taxi.bean.EndGrayContrailTaskReq +import com.mogo.och.taxi.bean.GrayLineBean +import com.mogo.och.taxi.bean.QueryGrayContrailListRsp +import com.mogo.och.taxi.bean.QueryRoutingContrailByIdRsp +import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp +import com.mogo.och.taxi.bean.StartGrayContrailTaskReq +import com.mogo.och.taxi.bean.StartGrayContrailTaskRsp +import com.mogo.och.taxi.bean.SubmitGrayLineIssueLocationReq +import io.reactivex.Observable + +object TaxiRoutingServiceManager { + + private var mRoutingServiceApi: TaxiRoutingServiceApi = + MoGoRetrofitFactory.getInstance(OchCommonConst.getBaseUrl()).create( + TaxiRoutingServiceApi::class.java + ) + + /** + * 查询灰度路线列表 + */ + fun queryRoutingGrayLineList( + context: Context, + callback: OchCommonServiceCallback + ) { + mRoutingServiceApi.queryRoutingGrayLineList( + sn = MoGoAiCloudClientConfig.getInstance().sn + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryRoutingGrayLineList")) + } + + /** + * 开始一个灰度任务 + */ + fun startGrayTask( + context: Context, + data: StartGrayContrailTaskReq, + callback: OchCommonServiceCallback + ) { + mRoutingServiceApi.startGrayTask(data = data).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "startGrayTask")) + } + + /** + * 通过id查询轨迹详情 + */ + fun queryRoutingContrailById( + context: Context, + contrailId: Long, + callback: OchCommonServiceCallback + ) { + mRoutingServiceApi.queryRoutingContrailById(contrailId = contrailId).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryRoutingContrailById")) + } + + /** + * 上报线路打点 + */ + fun submitGrayLineIssueLocation( + context: Context, + data: SubmitGrayLineIssueLocationReq, + callback: OchCommonServiceCallback + ) { + mRoutingServiceApi.submitGrayLineIssueLocation(data = data).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "submitGrayLineIssueLocation")) + } + + /** + * 结束一个灰度任务 + */ + fun endGrayTask( + context: Context, + data: EndGrayContrailTaskReq, + callback: OchCommonServiceCallback + ) { + mRoutingServiceApi.endGrayTask(data = data).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "endGrayTask")) + } + + fun startGrayTaskAndQueryRoutingContrail( + context: Context, + sn: String, + contrailId: Long, + grayLineBean: GrayLineBean, + callback: OchCommonServiceCallback + ) { + val data = StartGrayContrailTaskReq(sn = sn, contrailId = contrailId) + var taskId: Long + mRoutingServiceApi.startGrayTask(data = data) + .flatMap { startGrayRsp -> + if (startGrayRsp.data == null) { + taskId = -1L + val result = StartGrayAndQueryContrailRsp( + taskId = taskId, + contrail = null, + grayLineBean = grayLineBean + ) + return@flatMap Observable.just(result) + } + taskId = startGrayRsp.data!! + return@flatMap mRoutingServiceApi.queryRoutingContrailById(contrailId = contrailId) + .map { queryRoutingContrailRsp -> + val result = StartGrayAndQueryContrailRsp( + taskId = taskId, + contrail = queryRoutingContrailRsp.data, + grayLineBean = grayLineBean + ) + result + } + } + .transformTry() + .subscribe( + OchCommonSubscribeImpl( + context, + callback, + "startGrayTaskAndQueryRoutingContrail" + ) + ) + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt similarity index 66% rename from OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt rename to OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt index 1a43045ead..4bef569900 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseTaskActivity.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt @@ -7,24 +7,34 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R -import com.mogo.och.taxi.bean.TaxiRoutingQueryLineResponse +import com.mogo.och.taxi.bean.GrayLineBean import com.mogo.och.taxi.constant.TaxiDriverEventConst import kotlinx.android.synthetic.main.routing_choose_task_activity.btnChooseLineSubmit import kotlinx.android.synthetic.main.routing_choose_task_activity.btnClose import kotlinx.android.synthetic.main.routing_choose_task_activity.chooseLineListView import kotlinx.android.synthetic.main.routing_no_data_common_view.noDataContainer +import kotlinx.coroutines.flow.map -class TaxiRoutingChooseTaskActivity : AppCompatActivity() { +class TaxiRoutingChooseLineActivity : AppCompatActivity() { companion object { - const val TAG = "TaxiRoutingChooseTaskActivity" + const val TAG = "TaxiRoutingChooseLineActivity" + } + + private val mViewModel: TaxiRoutingChooseLineViewModel by lazy { + ViewModelProvider( + this, + ViewModelProvider.NewInstanceFactory() + )[TaxiRoutingChooseLineViewModel::class.java] } private val mLoadingDialog: TaxiRoutingLoadingDialog by lazy { @@ -34,14 +44,16 @@ class TaxiRoutingChooseTaskActivity : AppCompatActivity() { } private lateinit var mChooseLineListAdapter: TaxiRoutingChooseLineAdapter private lateinit var mLinearLayoutManager: LinearLayoutManager - private val mRoutingLineList: MutableList = ArrayList() - private var mCurrentChosenLineId: Int? = -1 + private val mRoutingLineList: MutableList = ArrayList() + private var mCurrentChosenPosition: Int = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.routing_choose_task_activity) initWindowParams() initView() + initViewListener() + initViewModelObserver() loadData() } @@ -69,20 +81,27 @@ class TaxiRoutingChooseTaskActivity : AppCompatActivity() { mChooseLineListAdapter.setOnLineItemClickListener(object : TaxiRoutingChooseLineAdapter.OnChooseLineItemClickListener { override fun onItemClick(position: Int, close: Boolean) { - mCurrentChosenLineId = mRoutingLineList[position].lineId + mCurrentChosenPosition = position } }) + } + private fun initViewListener() { btnClose.setOnClickListener { finish() } btnChooseLineSubmit.setOnClickListener { - if (mCurrentChosenLineId == -1) { + if (mCurrentChosenPosition == -1) { ToastUtils.showLong("请先选择任务") return@setOnClickListener } - ToastUtils.showLong("当前选择的路线LineId:$mCurrentChosenLineId") + ToastUtils.showLong("当前选择的路线contrailId:$mCurrentChosenPosition") mLoadingDialog.showLoading() + val chosenItem = mRoutingLineList[mCurrentChosenPosition] + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.StartTaskAndQueryContrail(chosenItem) + ) + // TODO UiThreadHandler.postDelayed({ mLoadingDialog.hideLoading() FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) @@ -93,6 +112,26 @@ class TaxiRoutingChooseTaskActivity : AppCompatActivity() { } } + private fun initViewModelObserver() { + lifecycleScope.launchWhenStarted { + mViewModel.uiStateFlow.map { it.routingUiState }.collect { routingUiState -> + CallerLogger.d( + TAG, + "uiStateFlow-initViewModelObserver: $routingUiState" + ) + when (routingUiState) { + is RoutingUIState.Init -> { + showEmptyView() + } + + is RoutingUIState.ShowGrayLineList -> { + onRoutingGrayLineListChanged(routingUiState.data) + } + } + } + } + } + private fun showEmptyView() { chooseLineListView.visibility = View.GONE btnChooseLineSubmit.visibility = View.GONE @@ -105,41 +144,18 @@ class TaxiRoutingChooseTaskActivity : AppCompatActivity() { noDataContainer.visibility = View.GONE } - /** - * 初始化数据 - */ private fun loadData() { - //TODO - for (i in 1..10) { - val result = TaxiRoutingQueryLineResponse.Result() - result.lineId = i - result.name = "路线名称$i" - result.todayVerifyNum = 2 - result.historyVerifyTotalUsableNum = 5 - result.historyVerifyTotalNotUsableNum = 1 - result.isChoosed = false - mRoutingLineList.add(result) - } - if (mRoutingLineList.isEmpty()) { - showEmptyView() - } else { - showRecyclerView() - mChooseLineListAdapter.notifyDataSetChanged() - } + mViewModel.sendUiIntent(TaxiRoutingUiIntent.QueryRoutingGrayLineList) } - fun onRoutingLineDataChanged(data: TaxiRoutingQueryLineResponse?) { - if (data?.data?.isNotEmpty() == true) { + private fun onRoutingGrayLineListChanged(data: MutableList) { + if (data.isNotEmpty()) { showRecyclerView() mRoutingLineList.clear() - mRoutingLineList.addAll(data.data) + mRoutingLineList.addAll(data) mChooseLineListAdapter.notifyDataSetChanged() } else { showEmptyView() } } - - override fun onDestroy() { - super.onDestroy() - } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt index ae43cb3930..501cc62945 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineAdapter.kt @@ -8,11 +8,11 @@ import android.view.ViewGroup import androidx.appcompat.widget.AppCompatTextView import androidx.recyclerview.widget.RecyclerView import com.mogo.och.taxi.R -import com.mogo.och.taxi.bean.TaxiRoutingQueryLineResponse +import com.mogo.och.taxi.bean.GrayLineBean class TaxiRoutingChooseLineAdapter( private val mContext: Context, - private val mData: List + private val mData: List ) : RecyclerView.Adapter() { companion object { @@ -32,10 +32,10 @@ class TaxiRoutingChooseLineAdapter( override fun onBindViewHolder(holder: SwitchLineViewHolder, position: Int) { val currentPosition = holder.bindingAdapterPosition val data = mData[currentPosition] - holder.lineNameTextView.text = data.name - holder.todayVerifyNumTextView.text = "本车今日已验证:${data.todayVerifyNum}次" + holder.lineNameTextView.text = data.lineName + holder.todayVerifyNumTextView.text = "本车今日已验证:${data.carVerificationCount}次" holder.historyVerifyNumTextView.text = - "路线累计反馈${data.historyVerifyTotalUsableNum}可用,${data.historyVerifyTotalNotUsableNum}不可用" + "路线累计反馈${data.lineSuccessCount}可用,${data.lineFailCount}不可用" if (data.isChoosed) { holder.itemView.setBackgroundResource(R.drawable.routing_choose_line_shape_select_line_item_bg_selected) } else { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt new file mode 100644 index 0000000000..b616f28e18 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt @@ -0,0 +1,94 @@ +package com.mogo.och.taxi.ui.routing + +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.taxi.base.BaseViewModel +import com.mogo.och.taxi.base.IUiIntent +import com.mogo.och.taxi.bean.GrayLineBean +import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp +import com.mogo.och.taxi.callback.ITaxiRoutingCallback + +class TaxiRoutingChooseLineViewModel : BaseViewModel(), + ITaxiRoutingCallback { + + private val TAG = SceneConstant.M_TAXI + "TaxiRoutingChooseLineViewModel" + + init { + TaxiRoutingModel.addTaxiRoutingListener(TAG, this) + } + + override fun initUiState(): TaxiRoutingUiState { + return TaxiRoutingUiState(RoutingUIState.Init) + } + + override fun handleIntent(intent: IUiIntent) { + when (intent) { + is TaxiRoutingUiIntent.QueryRoutingGrayLineList -> { + TaxiRoutingModel.queryRoutingGrayLineList() + } + + is TaxiRoutingUiIntent.StartTaskAndQueryContrail -> { + val contrailId = intent.grayLineBean.contrailId + TaxiRoutingModel.startGrayTaskAndQueryRoutingContrail( + contrailId ?: -1L, + intent.grayLineBean + ) + } + } + } + + override fun onQueryRoutingGrayLineListSuccess(data: MutableList) { + sendUiState { + copy( + routingUiState = RoutingUIState.ShowGrayLineList(data) + ) + } + } + + override fun onQueryRoutingGrayLineListFailed(errorStr: String) { +// sendUiState { +// copy( +// routingUiState = RoutingUIState.Init +// ) +// } + //TODO + val data: MutableList = mutableListOf() + for (i in 1..15) { + val result = GrayLineBean( + lineId = i + 1L, + lineName = "路线名称$i", + contrailId = i + 1L, + carVerificationCount = i, + lineSuccessCount = i, + lineFailCount = i, + isChoosed = false + ) + data.add(result) + } + sendUiState { + copy( + routingUiState = RoutingUIState.ShowGrayLineList(data) + ) + } + } + + override fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) { + sendUiState { + copy( + routingUiState = RoutingUIState.RoutingTask( + grayId = data.taskId, + grayLineBean = data.grayLineBean, + contrailBean = data.contrail + ) + ) + } + } + + override fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) { + + } + + override fun onCleared() { + super.onCleared() + TaxiRoutingModel.removeTaxiRoutingListener(TAG) + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 18c41878a2..1462cdc8c5 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -1,12 +1,12 @@ package com.mogo.och.taxi.ui.routing -import android.content.Intent import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import com.mogo.commons.mvp.BaseFragment import com.mogo.eagle.core.function.main.MainMoGoApplication +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.och.common.module.utils.FlowBus @@ -20,11 +20,12 @@ import kotlinx.android.synthetic.main.routing_fragment.headerTitleContainer import kotlinx.android.synthetic.main.routing_fragment.mCurrentTaskLayout import kotlinx.android.synthetic.main.routing_fragment.noDataContainer import kotlinx.android.synthetic.main.routing_fragment.taskTitleTv +import kotlinx.coroutines.flow.map class TaxiRoutingFragment : BaseFragment() { companion object { - const val TAG = SceneConstant.M_TAXI + "RoutingFragment" + const val TAG = SceneConstant.M_TAXI + "TaxiRoutingFragment" fun newInstance(): TaxiRoutingFragment { val args = Bundle() @@ -34,39 +35,69 @@ class TaxiRoutingFragment : BaseFragment() { } } + private val mViewModel: TaxiRoutingFragmentViewModel by lazy { + ViewModelProvider( + this, + ViewModelProvider.NewInstanceFactory() + )[TaxiRoutingFragmentViewModel::class.java] + } + override fun getLayoutId(): Int { return R.layout.routing_fragment } override fun getTagName(): String { - return "RoutingFragment" + return "TaxiRoutingFragment" } override fun initViews() { - btnChooseTask.setOnClickListener { - val intent = Intent(context, TaxiRoutingChooseTaskActivity::class.java) - startActivity(intent) - } - showChooseTaskView() - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { initEventBus() - return super.onCreateView(inflater, container, savedInstanceState) + initViewListener() + initViewModelObserver() } private fun initEventBus() { - FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) - .register(this) { taskId -> - ToastUtils.showLong("接收到taskId:$taskId") - showCurrentLineTaskContentView() + FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) + .register(this) { task -> + ToastUtils.showLong("接收到taskId:${task.grayId}") + mViewModel.sendUiIntent(TaxiRoutingUiIntent.ShowRoutingTask(task)) } } + private fun initViewListener() { + btnChooseTask.setOnClickListener { + mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartChooseLineAction) + } + } + + private fun initViewModelObserver() { + lifecycleScope.launchWhenStarted { + mViewModel.uiStateFlow.map { it.routingUiState }.collect { routingUiState -> + CallerLogger.d( + TAG, + "uiStateFlow-initViewModelObserver: $routingUiState" + ) + when (routingUiState) { + is RoutingUIState.Init -> { + showChooseTaskView() + } + + is RoutingUIState.RoutingTask -> { + showCurrentLineTaskContentView(routingUiState) + } + + is RoutingUIState.ShowFinishTaskButton -> { + showFinishTaskView() + } + + is RoutingUIState.ShowFeedbackDialog -> { + showFeedbackDialog() + } + } + } + } + } + private fun showChooseTaskView() { noDataContainer.visibility = View.VISIBLE mCurrentTaskLayout.visibility = View.GONE @@ -77,17 +108,17 @@ class TaxiRoutingFragment : BaseFragment() { finishSubmitIssueGroup.visibility = View.GONE } - private fun showCurrentLineTaskContentView() { + private fun showCurrentLineTaskContentView(data: RoutingUIState.RoutingTask) { noDataContainer.visibility = View.GONE mCurrentTaskLayout.visibility = View.VISIBLE headerTitleContainer.visibility = View.VISIBLE - taskTitleTv.text = "测试任务测试任务" + taskTitleTv.text = data.grayLineBean.lineName btnChooseTask.visibility = View.GONE btnStartTask.visibility = View.VISIBLE btnStartTask.setOnClickListener { - showFinishTaskView() + mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartTaskAction) } finishSubmitIssueGroup.visibility = View.GONE } @@ -97,7 +128,7 @@ class TaxiRoutingFragment : BaseFragment() { btnStartTask.visibility = View.GONE finishSubmitIssueGroup.visibility = View.VISIBLE btnFinishTask.setOnClickListener { - showFeedbackDialog() + mViewModel.sendUiIntent(TaxiRoutingUiIntent.ShowFeedbackDialog) } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt new file mode 100644 index 0000000000..fbd9b4aab6 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -0,0 +1,53 @@ +package com.mogo.och.taxi.ui.routing + +import android.content.Context +import android.content.Intent +import com.mogo.commons.AbsMogoApplication +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.taxi.base.BaseViewModel +import com.mogo.och.taxi.base.IUiIntent + +class TaxiRoutingFragmentViewModel : BaseViewModel() { + + companion object { + const val TAG = SceneConstant.M_TAXI + "TaxiRoutingFragmentViewModel" + } + + private val mContext: Context + get() = AbsMogoApplication.getApp().applicationContext + + override fun initUiState(): TaxiRoutingUiState { + return TaxiRoutingUiState(RoutingUIState.Init) + } + + override fun handleIntent(intent: IUiIntent) { + when (intent) { + is TaxiRoutingUiIntent.StartChooseLineAction -> { + val intent = Intent(mContext, TaxiRoutingChooseLineActivity::class.java) + mContext?.startActivity(intent) + } + + is TaxiRoutingUiIntent.ShowRoutingTask -> { + val task = intent.routingTask + sendUiState { + copy( + routingUiState = RoutingUIState.RoutingTask( + task.grayLineBean, + task.contrailBean, + task.grayId + ) + ) + } + } + + is TaxiRoutingUiIntent.StartTaskAction -> { + //TODO 启动自动驾驶 + sendUiState { + copy( + routingUiState = RoutingUIState.ShowFinishTaskButton + ) + } + } + } + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt new file mode 100644 index 0000000000..de6ccc7914 --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt @@ -0,0 +1,154 @@ +package com.mogo.och.taxi.ui.routing + +import android.content.Context +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.commons.AbsMogoApplication +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.GsonUtils +import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback +import com.mogo.och.taxi.bean.GrayLineBean +import com.mogo.och.taxi.bean.QueryGrayContrailListRsp +import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp +import com.mogo.och.taxi.callback.ITaxiRoutingCallback +import com.mogo.och.taxi.network.TaxiRoutingServiceManager +import java.util.concurrent.ConcurrentHashMap + +object TaxiRoutingModel { + private val TAG = SceneConstant.M_TAXI + TaxiRoutingModel::class.java.simpleName + + private val mContext: Context + get() = AbsMogoApplication.getApp().applicationContext + + private val mTaxiRoutingCallbackMap: ConcurrentHashMap = + ConcurrentHashMap() + + + fun addTaxiRoutingListener(tag: String, listener: ITaxiRoutingCallback) { + if (mTaxiRoutingCallbackMap.containsKey(tag)) { + return + } + mTaxiRoutingCallbackMap[tag] = listener + } + + fun removeTaxiRoutingListener(tag: String) { + if (!mTaxiRoutingCallbackMap.containsKey(tag)) { + return + } + mTaxiRoutingCallbackMap.remove(tag) + } + + fun queryRoutingGrayLineList() { + TaxiRoutingServiceManager.queryRoutingGrayLineList(mContext, + object : OchCommonServiceCallback { + override fun onSuccess(data: QueryGrayContrailListRsp) { + CallerLogger.d( + TAG, + "queryRoutingGrayLineList onSuccess: data=${GsonUtils.toJson(data)}" + ) + val result = mutableListOf() + data.data?.also { + result.addAll(it) + } + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onQueryRoutingGrayLineListSuccess(result) + } + } + + override fun onFail(code: Int, msg: String?) { + CallerLogger.d( + TAG, + "queryRoutingGrayLineList onFail: code=$code, msg=$msg" + ) + ToastUtils.showShort("查询灰度线路列表异常, 请稍后重试, code=$code") + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onQueryRoutingGrayLineListFailed( + msg ?: "查询灰度线路列表异常, 请稍后重试" + ) + } + } + + override fun onError() { + super.onError() + var hintStr = "" + if (!NetworkUtils.isConnected(mContext)) { + hintStr = "网络出现异常,请稍后重试" + ToastUtils.showShort(hintStr) + } else { + hintStr = "查询灰度线路列表异常, 请稍后重试" + ToastUtils.showShort(hintStr) + } + CallerLogger.d( + TAG, + "queryRoutingGrayLineList onError, msg=$hintStr" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onQueryRoutingGrayLineListFailed(hintStr) + } + } + }) + } + + fun startGrayTaskAndQueryRoutingContrail(contrailId: Long, grayLineBean: GrayLineBean) { + TaxiRoutingServiceManager.startGrayTaskAndQueryRoutingContrail( + mContext, + sn = MoGoAiCloudClientConfig.getInstance().sn, + contrailId = contrailId, + grayLineBean = grayLineBean, + object : OchCommonServiceCallback { + override fun onSuccess(data: StartGrayAndQueryContrailRsp) { + CallerLogger.d( + TAG, + "startGrayTaskAndQueryRoutingContrail onSuccess: data=${ + GsonUtils.toJson( + data + ) + }" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onStartGrayTaskAndQueryContrailSuccess(data) + } + } + + override fun onFail(code: Int, msg: String?) { + CallerLogger.d( + TAG, + "startGrayTaskAndQueryRoutingContrail onFail: code=$code, msg=$msg" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onStartGrayTaskAndQueryContrailFailed( + msg ?: "startGrayTaskAndQueryRoutingContrail onFail" + ) + } + } + + override fun onError() { + super.onError() + var hintStr = "" + if (!NetworkUtils.isConnected(mContext)) { + hintStr = "网络出现异常,请稍后重试" + ToastUtils.showShort(hintStr) + } else { + hintStr = "开始任务并查询轨迹详情异常, 请稍后重试" + ToastUtils.showShort(hintStr) + } + CallerLogger.d( + TAG, + "startGrayTaskAndQueryRoutingContrail onError, msg=$hintStr" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onStartGrayTaskAndQueryContrailFailed(hintStr) + } + } + } + ) + } +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt new file mode 100644 index 0000000000..f6c285633a --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt @@ -0,0 +1,26 @@ +package com.mogo.och.taxi.ui.routing + +import com.mogo.och.taxi.base.IUiIntent +import com.mogo.och.taxi.bean.GrayLineBean + +sealed class TaxiRoutingUiIntent : IUiIntent { + + //打开选择路线页面 + object StartChooseLineAction : TaxiRoutingUiIntent() + + //查询灰度线路列表 + object QueryRoutingGrayLineList : TaxiRoutingUiIntent() + + //开始一个任务并查询此任务对应的轨迹详情 + data class StartTaskAndQueryContrail(val grayLineBean: GrayLineBean) : TaxiRoutingUiIntent() + + //展示Routing任务信息 + data class ShowRoutingTask(val routingTask: RoutingUIState.RoutingTask) : + TaxiRoutingUiIntent() + + //开始任务 + object StartTaskAction : TaxiRoutingUiIntent() + + //展示结束任务反馈弹框 + object ShowFeedbackDialog : TaxiRoutingUiIntent() +} \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt new file mode 100644 index 0000000000..69c83eccee --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt @@ -0,0 +1,23 @@ +package com.mogo.och.taxi.ui.routing + +import com.mogo.och.taxi.base.IUiState +import com.mogo.och.taxi.bean.ContrailBean +import com.mogo.och.taxi.bean.GrayLineBean + +data class TaxiRoutingUiState(val routingUiState: RoutingUIState) : IUiState + +sealed class RoutingUIState { + object Init : RoutingUIState() + + data class RoutingTask( + val grayLineBean: GrayLineBean?, + val contrailBean: ContrailBean?, + val grayId: Long? + ) : RoutingUIState() + + object ShowFinishTaskButton : RoutingUIState() + object ShowFeedbackDialog : RoutingUIState() + data class ShowGrayLineList(var data: MutableList) : RoutingUIState() +} + + diff --git a/gradle.properties b/gradle.properties index b50da3f97c..ca1408ea13 100644 --- a/gradle.properties +++ b/gradle.properties @@ -163,7 +163,7 @@ TAXI_DRIVER_VERSION=6.1.2 TAXI_PASSENGER_VERSION=5.1.0 # 出租车模式司机端版本号 -TAXIUNMANNED_DRIVER_VERSION=6.1.2 +TAXIUNMANNED_DRIVER_VERSION=6.2.2 # 出租车模式乘客端端版本号 TAXIUNMANNED_PASSENGER_VERSION=5.1.0 From 2c33619e03259b44f0506cfc965717b4a5d66ac8 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Fri, 24 Nov 2023 21:22:16 +0800 Subject: [PATCH 08/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E8=81=94=E8=B0=83=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=87=AA=E9=A9=BE=EF=BC=8C=E9=AB=98=E5=BE=B7=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/och/taxi/bean/TaxiRoutingBean.kt | 38 ++- .../och/taxi/callback/ITaxiRoutingCallback.kt | 4 + .../taxi/constant/TaxiDriverEventConst.java | 2 +- .../taxi/network/TaxiRoutingServiceManager.kt | 4 + .../com/mogo/och/taxi/ui/base/TaxiFragment.kt | 16 +- .../mogo/och/taxi/ui/base/TaxiPresenter.java | 3 + .../routing/TaxiRoutingChooseLineActivity.kt | 26 +- .../routing/TaxiRoutingChooseLineViewModel.kt | 59 +++-- .../ui/routing/TaxiRoutingFeedbackDialog.kt | 21 +- .../taxi/ui/routing/TaxiRoutingFragment.kt | 199 +++++++++++++-- .../routing/TaxiRoutingFragmentViewModel.kt | 91 ++++++- .../och/taxi/ui/routing/TaxiRoutingModel.kt | 232 +++++++++++++++++- .../taxi/ui/routing/TaxiRoutingUiIntent.kt | 12 +- .../och/taxi/ui/routing/TaxiRoutingUiState.kt | 16 +- 14 files changed, 638 insertions(+), 85 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt index a19c466320..3411b14cdb 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiRoutingBean.kt @@ -9,17 +9,35 @@ data class GrayLineBean( var carVerificationCount: Int?, //本次今日已验证次数 var lineSuccessCount: Int?, //线路累计反馈可用次数 var lineFailCount: Int?, //线路累计反馈不可用次数 - var isChoosed: Boolean = false //当前是否选中 + var isChoosed: Boolean = false, //当前是否选中 + var startSite: RoutingSite?, + var endSite: RoutingSite? +) + +data class RoutingSite( + var siteId: Long, + var siteName: String, + var gcjLat: Double, + var gcjLon: Double, + var wgs84Lon: Double, + var wgs84Lat: Double ) data class ContrailBean( - var lineId: Long?, - var contrailId: Long?, - var csvFileUrl: String?, - var csvFileMd5: String?, - var txtFileUrl: String?, - var txtFileMd5: String?, - var version: Long? + var lineId: Long = -1L, + var lineName: String = "", + var contrailId: Long = -1L, + var csvFileUrl: String = "", + var csvFileMd5: String = "", + var txtFileUrl: String = "", + var txtFileMd5: String = "", + var contrailSaveTime: Long = -1L, + var csvFileUrlDPQP: String = "", + var csvFileMd5DPQP: String = "", + var txtFileUrlDPQP: String = "", + var txtFileMd5DPQP: String = "", + var contrailSaveTimeDPQP: Long = -1L, + var version: Long = -1L ) data class QueryGrayContrailListRsp(var data: MutableList?) : BaseData() @@ -34,6 +52,10 @@ data class StartGrayAndQueryContrailRsp( var grayLineBean: GrayLineBean ) : BaseData() +enum class EndGrayTaskFeedbackType(var type: Int) { + USABLE_YES(1), + USABLE_NO(2) +} diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt index 125e1c13c1..980921759f 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt @@ -8,4 +8,8 @@ interface ITaxiRoutingCallback { fun onQueryRoutingGrayLineListFailed(errorStr: String) fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) + fun onSubmitGrayLineIssueLocationSuccess() + fun onSubmitGrayLineIssueLocationFailed(errorStr: String) + fun onSubmitEndTaskSuccess() + fun onSubmitEndTaskFailed(errorStr: String) } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java index e7bb8bdc2f..ed2c9f757d 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiDriverEventConst.java @@ -15,6 +15,6 @@ public interface TaxiDriverEventConst { } interface RoutingActivityEvent { - String EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID = "event_type_get_chosen_line_task_id"; + String EVENT_TYPE_GET_CHOSEN_LINE_TASK = "event_type_get_chosen_line_task"; } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt index 3047ebd492..aaa1b5c288 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/network/TaxiRoutingServiceManager.kt @@ -105,6 +105,8 @@ object TaxiRoutingServiceManager { contrail = null, grayLineBean = grayLineBean ) + result.code = startGrayRsp.code + result.msg = startGrayRsp.msg return@flatMap Observable.just(result) } taskId = startGrayRsp.data!! @@ -115,6 +117,8 @@ object TaxiRoutingServiceManager { contrail = queryRoutingContrailRsp.data, grayLineBean = grayLineBean ) + result.code = queryRoutingContrailRsp.code + result.msg = queryRoutingContrailRsp.msg result } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index 18ecb7806e..e53a9b617d 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -163,9 +163,9 @@ class TaxiFragment : BaseTaxiTabFragment(), if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { UiThreadHandler.post { if (isTrue) { - showRoutingFragment() + showRoutingFragment() } else { - showTaskFragment() + showTaskFragment() } } } @@ -272,8 +272,12 @@ class TaxiFragment : BaseTaxiTabFragment(), fun onNaviToEnd(isAmap: Boolean, isShow: Boolean) { if (isAmap) { - if (null == taskTabFragment || taskTabFragment!!.get() == null) return - taskTabFragment!!.get()!!.onNaviToEndStationByAMap(isShow) + if (MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingVerifyMode) { + showAmapNaviToStationFragment(isShow) + } else { + if (null == taskTabFragment || taskTabFragment!!.get() == null) return + taskTabFragment!!.get()!!.onNaviToEndStationByAMap(isShow) + } } else if (isShow) { //使用routing数据 showRoutingToStationFragment(true) } else { @@ -304,8 +308,8 @@ class TaxiFragment : BaseTaxiTabFragment(), if (it.order != null && it.order!!.orderStatus >= TaxiOrderStatusEnum.ArriveAtStart.code) it.order!!.orderLine else - it.lineId - ,true) + it.lineId, true + ) } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java index 8fc079b3bb..ab3e77109b 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java @@ -20,6 +20,7 @@ import com.mogo.och.taxi.callback.ITaxiOrderStatusCallback; import com.mogo.och.taxi.constant.TaxiCarServingStatusManager; import com.mogo.och.taxi.constant.TaxiDriverRoleEnum; import com.mogo.och.taxi.constant.TaxiUnmannedConst; +import com.mogo.och.taxi.ui.routing.TaxiRoutingModel; import com.mogo.och.taxi.ui.task.TaxiTaskModel; /** @@ -51,6 +52,8 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS TaxiTaskModel.INSTANCE.setADASStatusCallback(this); TaxiTaskModel.INSTANCE.setControllerStatusCallback(this); TaxiTaskModel.INSTANCE.setOrderStatusCallback(this); + TaxiRoutingModel.INSTANCE.setControllerStatusCallback(this); + TaxiRoutingModel.INSTANCE.setOrderStatusCallback(this); } private void releaseListeners() { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt index 4bef569900..3d092a4711 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt @@ -13,7 +13,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration import com.mogo.eagle.core.utilcode.util.ToastUtils -import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R import com.mogo.och.taxi.bean.GrayLineBean @@ -101,14 +100,6 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { mViewModel.sendUiIntent( TaxiRoutingUiIntent.StartTaskAndQueryContrail(chosenItem) ) - // TODO - UiThreadHandler.postDelayed({ - mLoadingDialog.hideLoading() - FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) - .post(this.lifecycleScope, 1000) - mChooseLineListAdapter.setOnLineItemClickListener(null) - finish() - }, 3000L) } } @@ -127,6 +118,23 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { is RoutingUIState.ShowGrayLineList -> { onRoutingGrayLineListChanged(routingUiState.data) } + + is RoutingUIState.HideChooseLineLoading -> { + mLoadingDialog.hideLoading() + if (routingUiState.isCosePage) { + mChooseLineListAdapter.setOnLineItemClickListener(null) + finish() + } + } + + is RoutingUIState.PostRoutingTaskResult -> { + FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK) + .post(this, RoutingUIState.RoutingTask( + grayLineBean = routingUiState.grayLineBean, + contrailBean = routingUiState.contrailBean, + grayId = routingUiState.grayId + )) + } } } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt index b616f28e18..8977f56aa0 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt @@ -1,6 +1,7 @@ package com.mogo.och.taxi.ui.routing import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.och.taxi.base.BaseViewModel import com.mogo.och.taxi.base.IUiIntent import com.mogo.och.taxi.bean.GrayLineBean @@ -45,46 +46,58 @@ class TaxiRoutingChooseLineViewModel : BaseViewModel = mutableListOf() - for (i in 1..15) { - val result = GrayLineBean( - lineId = i + 1L, - lineName = "路线名称$i", - contrailId = i + 1L, - carVerificationCount = i, - lineSuccessCount = i, - lineFailCount = i, - isChoosed = false - ) - data.add(result) - } + ToastUtils.showShort(errorStr) sendUiState { copy( - routingUiState = RoutingUIState.ShowGrayLineList(data) + routingUiState = RoutingUIState.Init ) } } override fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) { + if (data.taskId == -1L) { + onStartGrayTaskAndQueryContrailFailed("开始任务失败, 请稍后重试") + return + } sendUiState { copy( - routingUiState = RoutingUIState.RoutingTask( - grayId = data.taskId, + routingUiState = RoutingUIState.PostRoutingTaskResult( grayLineBean = data.grayLineBean, - contrailBean = data.contrail + contrailBean = data.contrail, + grayId = data.taskId + ) + ) + } + sendUiState { + copy( + routingUiState = RoutingUIState.HideChooseLineLoading( + isCosePage = true ) ) } } override fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) { + ToastUtils.showShort(errorStr) + sendUiState { + copy( + routingUiState = RoutingUIState.HideChooseLineLoading( + isCosePage = false + ) + ) + } + } + override fun onSubmitGrayLineIssueLocationSuccess() { + } + + override fun onSubmitGrayLineIssueLocationFailed(errorStr: String) { + } + + override fun onSubmitEndTaskSuccess() { + } + + override fun onSubmitEndTaskFailed(errorStr: String) { } override fun onCleared() { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt index b7de129128..dfd851184e 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFeedbackDialog.kt @@ -13,12 +13,13 @@ class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { private var commonCancel: TextView? = null private var commonTips: TextView? = null private var commonCloseIcon: ImageView? = null - private var clickListener: ClickListener? = null + private var clickListener: TaxiRoutingFeedBackDialogClickListener? = null constructor(builder: Builder, context: Context) : super(context) { commonTips?.text = builder.tipsStr commonCancel?.text = builder.cancelStr commonConfirm?.text = builder.confirmStr + clickListener = builder.clickListener } init { @@ -46,10 +47,6 @@ class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { } } - fun setClickListener(clickListener: ClickListener) { - this.clickListener = clickListener - } - fun showDialog() { if (isShowing) { return @@ -57,7 +54,13 @@ class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { show() } - interface ClickListener { + fun hideDialog() { + if (isShowing) { + dismiss() + } + } + + interface TaxiRoutingFeedBackDialogClickListener { fun confirm() fun cancel() } @@ -66,6 +69,7 @@ class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { var tipsStr: String = "" var confirmStr: String = "" var cancelStr: String = "" + var clickListener: TaxiRoutingFeedBackDialogClickListener? = null fun tips(tips: String): Builder { this.tipsStr = tips @@ -82,6 +86,11 @@ class TaxiRoutingFeedbackDialog : BaseFloatDialog, LifecycleObserver { return this } + fun clickListener(listener: TaxiRoutingFeedBackDialogClickListener): Builder { + this.clickListener = listener + return this + } + fun build(context: Context): TaxiRoutingFeedbackDialog? { return TaxiRoutingFeedbackDialog(this, context) } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 1462cdc8c5..997388a043 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -4,25 +4,38 @@ import android.os.Bundle import android.view.View import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import com.amap.api.navi.model.NaviLatLng import com.mogo.commons.mvp.BaseFragment +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager import com.mogo.eagle.core.function.main.MainMoGoApplication import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.common.module.map.AmapNaviToDestinationModel +import com.mogo.och.common.module.map.ICommonNaviChangedCallback import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R +import com.mogo.och.taxi.bean.EndGrayTaskFeedbackType import com.mogo.och.taxi.constant.TaxiDriverEventConst +import com.mogo.och.taxi.utils.TaskUtils import kotlinx.android.synthetic.main.routing_fragment.btnChooseTask import kotlinx.android.synthetic.main.routing_fragment.btnFinishTask import kotlinx.android.synthetic.main.routing_fragment.btnStartTask +import kotlinx.android.synthetic.main.routing_fragment.btnSummitIssue +import kotlinx.android.synthetic.main.routing_fragment.endStationName import kotlinx.android.synthetic.main.routing_fragment.finishSubmitIssueGroup import kotlinx.android.synthetic.main.routing_fragment.headerTitleContainer import kotlinx.android.synthetic.main.routing_fragment.mCurrentTaskLayout +import kotlinx.android.synthetic.main.routing_fragment.naviToEnd +import kotlinx.android.synthetic.main.routing_fragment.naviToStart import kotlinx.android.synthetic.main.routing_fragment.noDataContainer +import kotlinx.android.synthetic.main.routing_fragment.startStationName import kotlinx.android.synthetic.main.routing_fragment.taskTitleTv +import kotlinx.android.synthetic.main.routing_fragment.taskTripInfo import kotlinx.coroutines.flow.map -class TaxiRoutingFragment : BaseFragment() { +class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { companion object { const val TAG = SceneConstant.M_TAXI + "TaxiRoutingFragment" @@ -35,6 +48,8 @@ class TaxiRoutingFragment : BaseFragment() { } } + private var mFeedbackDialog: TaxiRoutingFeedbackDialog? = null + private val mViewModel: TaxiRoutingFragmentViewModel by lazy { ViewModelProvider( this, @@ -57,7 +72,7 @@ class TaxiRoutingFragment : BaseFragment() { } private fun initEventBus() { - FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK_ID) + FlowBus.with(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK) .register(this) { task -> ToastUtils.showLong("接收到taskId:${task.grayId}") mViewModel.sendUiIntent(TaxiRoutingUiIntent.ShowRoutingTask(task)) @@ -80,6 +95,7 @@ class TaxiRoutingFragment : BaseFragment() { when (routingUiState) { is RoutingUIState.Init -> { showChooseTaskView() + AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() } is RoutingUIState.RoutingTask -> { @@ -87,11 +103,15 @@ class TaxiRoutingFragment : BaseFragment() { } is RoutingUIState.ShowFinishTaskButton -> { - showFinishTaskView() + showFinishTaskView(routingUiState.routingTask) } is RoutingUIState.ShowFeedbackDialog -> { - showFeedbackDialog() + showFeedbackDialog(routingUiState.grayId) + } + + is RoutingUIState.DismissFeedbackDialog -> { + hideFeedbackDialog() } } } @@ -113,38 +133,179 @@ class TaxiRoutingFragment : BaseFragment() { mCurrentTaskLayout.visibility = View.VISIBLE headerTitleContainer.visibility = View.VISIBLE - taskTitleTv.text = data.grayLineBean.lineName + taskTitleTv.text = data.grayLineBean?.lineName btnChooseTask.visibility = View.GONE btnStartTask.visibility = View.VISIBLE btnStartTask.setOnClickListener { - mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartTaskAction) + mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartTaskAction(data)) } finishSubmitIssueGroup.visibility = View.GONE + + naviToStart.visibility = View.VISIBLE + naviToEnd.visibility = View.INVISIBLE + + data.grayLineBean?.startSite?.also { + initStartNaviToStationParam( + false, + it.gcjLat, + it.gcjLon + ) + naviToStart.setOnClickListener { + showNaviToEndStationFragment(true) + } + } + + startStationName.text = data.grayLineBean?.startSite?.siteName + endStationName.text = data.grayLineBean?.endSite?.siteName } - private fun showFinishTaskView() { + private fun showFinishTaskView(routingTask: RoutingUIState.RoutingTask) { btnChooseTask.visibility = View.GONE btnStartTask.visibility = View.GONE finishSubmitIssueGroup.visibility = View.VISIBLE btnFinishTask.setOnClickListener { - mViewModel.sendUiIntent(TaxiRoutingUiIntent.ShowFeedbackDialog) + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.ShowFeedbackDialog( + routingTask.grayId ?: -1 + ) + ) + } + btnSummitIssue.setOnClickListener { + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.SubmitGrayLineIssueLocation( + routingTask.grayId ?: -1L + ) + ) + } + + naviToStart.visibility = View.INVISIBLE + naviToEnd.visibility = View.VISIBLE + routingTask.grayLineBean?.endSite?.also { + initStartNaviToStationParam( + false, + it.gcjLat, + it.gcjLon + ) + naviToEnd.setOnClickListener { + showNaviToEndStationFragment(true) + } } } - private fun showFeedbackDialog() { - val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() - builder.cancelStr( - MainMoGoApplication.getApp() - .getString(R.string.routing_feedback_result_btn_not_sure) - ) - .confirmStr( + private fun showFeedbackDialog(grayId: Long) { + if (mFeedbackDialog == null) { + val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() + builder.cancelStr( + MainMoGoApplication.getApp() + .getString(R.string.routing_feedback_result_btn_not_sure) + ).confirmStr( MainMoGoApplication.getApp() .getString(R.string.routing_feedback_result_btn_sure) - ) - .tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint)) - activity?.also { - builder.build(it)?.showDialog() + ).tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint)) + .clickListener(object : + TaxiRoutingFeedbackDialog.TaxiRoutingFeedBackDialogClickListener { + override fun confirm() { + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.SubmitEndTask( + grayId, + EndGrayTaskFeedbackType.USABLE_YES + ) + ) + } + + override fun cancel() { + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.SubmitEndTask( + grayId, + EndGrayTaskFeedbackType.USABLE_NO + ) + ) + } + }) + activity?.also { + mFeedbackDialog = builder.build(it) + mFeedbackDialog?.showDialog() + } + } else { + activity?.also { + mFeedbackDialog?.showDialog() + } } } + + private fun hideFeedbackDialog() { + mFeedbackDialog?.hideDialog() + } + + /** + * 显示/隐藏 前往任务目的地的导航 + * + * @param isShow + */ + private fun showNaviToEndStationFragment(isShow: Boolean) { +// FlowBus.with(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_START_NAVI_TO_END_STATION) +// .post(this.lifecycleScope, isShow) + TaxiRoutingModel.startNaviToEndStationByAMap(isShow) + } + + private fun initStartNaviToStationParam( + isVoicePlay: Boolean, + stationLat: Double, + stationLng: Double + ) { + AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() + val mCurLatitude = + CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02().latitude + val mCurLongitude = + CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02().longitude + CallerLogger.d( + TAG, + "currentLocation, lat=$mCurLatitude, lon=$mCurLongitude" + ) + val startNaviLatLng = NaviLatLng(mCurLatitude, mCurLongitude) + val endNaviLatLng = NaviLatLng(stationLat, stationLng) + AmapNaviToDestinationModel.getInstance(context).initAMapNavi(startNaviLatLng, endNaviLatLng) + AmapNaviToDestinationModel.getInstance(context).setVoiceIsMute(isVoicePlay) + AmapNaviToDestinationModel.getInstance(context).setTaxiNaviChangedCallback(this) + } + + override fun onCurrentNaviDistAndTimeChanged(meters: Int, timeInSecond: Long) { + updateCurrentTaskTripInfo(meters.toLong(), timeInSecond) + } + + override fun reInitNaviAmap(isPlay: Boolean, isRestart: Boolean) { + CallerLogger.d(TAG, "isPlay = $isPlay, isRestart=$isRestart") + if (!isRestart) { +// FlowBus.with(TaxiDriverEventConst.TaxiFragmentEvent.EVENT_TYPE_SHOW_AMAP_NAVI_TO_STATION_FRAGMENT) +// .post(this.lifecycleScope, false) + TaxiRoutingModel.startNaviToEndStationByAMap(false) + return + } + } + + /** + * 剩余里程和剩余时间 + * @param meters 米 + * @param timeInSecond 秒 + */ + private fun updateCurrentTaskTripInfo(meters: Long, timeInSecond: Long) { + UiThreadHandler.post { + CallerLogger.d( + TAG, + "updateCurrentTaskTripInfo, taskUtil, ${ + TaskUtils.getCurrentTaskTripHtml( + meters, + timeInSecond + ) + }" + ) + taskTripInfo.text = TaskUtils.getCurrentTaskTripHtml(meters, timeInSecond) + } + } + + override fun onDestroyView() { + AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() + super.onDestroyView() + } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt index fbd9b4aab6..8465751e2f 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -3,16 +3,26 @@ package com.mogo.och.taxi.ui.routing import android.content.Context import android.content.Intent import com.mogo.commons.AbsMogoApplication +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.och.taxi.base.BaseViewModel import com.mogo.och.taxi.base.IUiIntent +import com.mogo.och.taxi.bean.GrayLineBean +import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp +import com.mogo.och.taxi.callback.ITaxiRoutingCallback -class TaxiRoutingFragmentViewModel : BaseViewModel() { +class TaxiRoutingFragmentViewModel : BaseViewModel(), + ITaxiRoutingCallback { companion object { const val TAG = SceneConstant.M_TAXI + "TaxiRoutingFragmentViewModel" } + init { + TaxiRoutingModel.addTaxiRoutingListener(TAG, this) + } + private val mContext: Context get() = AbsMogoApplication.getApp().applicationContext @@ -41,13 +51,88 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { - //TODO 启动自动驾驶 + val grayLineBean = intent.routingTask.grayLineBean + val contrailBean = intent.routingTask.contrailBean + if (grayLineBean == null || contrailBean == null) { + ToastUtils.showShort("灰度线路或轨迹信息异常,请稍后再试") + return + } + TaxiRoutingModel.startAutoPilot(grayLineBean!!, contrailBean!!) sendUiState { copy( - routingUiState = RoutingUIState.ShowFinishTaskButton + routingUiState = RoutingUIState.ShowFinishTaskButton(intent.routingTask) ) } } + + is TaxiRoutingUiIntent.SubmitGrayLineIssueLocation -> { + val grayId = intent.grayId + val currentLocation = + CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02() + TaxiRoutingModel.submitGrayLineIssueLocation( + grayId, + currentLocation.longitude, + currentLocation.latitude + ) + } + + is TaxiRoutingUiIntent.ShowFeedbackDialog -> { + sendUiState { + copy( + routingUiState = RoutingUIState.ShowFeedbackDialog( + intent.grayId, + System.currentTimeMillis() + ) + ) + } + } + + is TaxiRoutingUiIntent.SubmitEndTask -> { + TaxiRoutingModel.endGrayTask(intent.grayId, intent.type) + } } } + + override fun onQueryRoutingGrayLineListSuccess(data: MutableList) { + } + + override fun onQueryRoutingGrayLineListFailed(errorStr: String) { + } + + override fun onStartGrayTaskAndQueryContrailSuccess(data: StartGrayAndQueryContrailRsp) { + } + + override fun onStartGrayTaskAndQueryContrailFailed(errorStr: String) { + } + + override fun onSubmitGrayLineIssueLocationSuccess() { + ToastUtils.showShort("上报问题打点成功") + } + + override fun onSubmitGrayLineIssueLocationFailed(errorStr: String) { + ToastUtils.showShort("上报问题打点失败:$errorStr") + } + + override fun onSubmitEndTaskSuccess() { + ToastUtils.showLong("结束任务成功") + sendUiState { + copy( + routingUiState = RoutingUIState.Init + ) + } + } + + override fun onSubmitEndTaskFailed(errorStr: String) { + ToastUtils.showLong("结束任务失败") + sendUiState { + copy( + routingUiState = RoutingUIState.DismissFeedbackDialog + ) + } + } + + override fun onCleared() { + TaxiRoutingModel.removeTaxiRoutingListener(TAG) + super.onCleared() + } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt index de6ccc7914..572e522c01 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingModel.kt @@ -1,19 +1,34 @@ package com.mogo.och.taxi.ui.routing import android.content.Context +import android.text.TextUtils import com.mogo.cloud.passport.MoGoAiCloudClientConfig import com.mogo.commons.AbsMogoApplication +import com.mogo.eagle.core.data.BaseData +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters +import com.mogo.eagle.core.data.config.FunctionBuildConfig +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager +import com.mogo.eagle.core.network.utils.GsonUtil import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.GsonUtils import com.mogo.eagle.core.utilcode.util.NetworkUtils import com.mogo.eagle.core.utilcode.util.ToastUtils import com.mogo.och.common.module.biz.network.OchCommonServiceCallback +import com.mogo.och.common.module.manager.autopilotmanager.OCHAdasAbilityManager +import com.mogo.och.taxi.bean.ContrailBean +import com.mogo.och.taxi.bean.EndGrayContrailTaskReq +import com.mogo.och.taxi.bean.EndGrayTaskFeedbackType import com.mogo.och.taxi.bean.GrayLineBean import com.mogo.och.taxi.bean.QueryGrayContrailListRsp import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp +import com.mogo.och.taxi.bean.SubmitGrayLineIssueLocationReq +import com.mogo.och.taxi.callback.ITaxiControllerStatusCallback +import com.mogo.och.taxi.callback.ITaxiOrderStatusCallback import com.mogo.och.taxi.callback.ITaxiRoutingCallback +import com.mogo.och.taxi.constant.TaxiUnmannedConst import com.mogo.och.taxi.network.TaxiRoutingServiceManager +import com.mogo.och.taxi.ui.debug.DebugView import java.util.concurrent.ConcurrentHashMap object TaxiRoutingModel { @@ -25,7 +40,6 @@ object TaxiRoutingModel { private val mTaxiRoutingCallbackMap: ConcurrentHashMap = ConcurrentHashMap() - fun addTaxiRoutingListener(tag: String, listener: ITaxiRoutingCallback) { if (mTaxiRoutingCallbackMap.containsKey(tag)) { return @@ -40,6 +54,18 @@ object TaxiRoutingModel { mTaxiRoutingCallbackMap.remove(tag) } + private var mControllerStatusCallback: ITaxiControllerStatusCallback? = null + + fun setControllerStatusCallback(callback: ITaxiControllerStatusCallback?) { + mControllerStatusCallback = callback + } + + private var mOrderStatusCallback: ITaxiOrderStatusCallback? = null + + fun setOrderStatusCallback(callback: ITaxiOrderStatusCallback?) { + mOrderStatusCallback = callback + } + fun queryRoutingGrayLineList() { TaxiRoutingServiceManager.queryRoutingGrayLineList(mContext, object : OchCommonServiceCallback { @@ -77,10 +103,8 @@ object TaxiRoutingModel { var hintStr = "" if (!NetworkUtils.isConnected(mContext)) { hintStr = "网络出现异常,请稍后重试" - ToastUtils.showShort(hintStr) } else { hintStr = "查询灰度线路列表异常, 请稍后重试" - ToastUtils.showShort(hintStr) } CallerLogger.d( TAG, @@ -134,10 +158,8 @@ object TaxiRoutingModel { var hintStr = "" if (!NetworkUtils.isConnected(mContext)) { hintStr = "网络出现异常,请稍后重试" - ToastUtils.showShort(hintStr) } else { hintStr = "开始任务并查询轨迹详情异常, 请稍后重试" - ToastUtils.showShort(hintStr) } CallerLogger.d( TAG, @@ -151,4 +173,204 @@ object TaxiRoutingModel { } ) } + + fun submitGrayLineIssueLocation(grayId: Long, gcjLon: Double, gcjLat: Double) { + val submit = SubmitGrayLineIssueLocationReq(grayId, gcjLon, gcjLat) + TaxiRoutingServiceManager.submitGrayLineIssueLocation( + mContext, + submit, + object : OchCommonServiceCallback { + override fun onSuccess(data: BaseData?) { + CallerLogger.d( + TAG, + "submitGrayLineIssueLocation onSuccess: data=${ + GsonUtils.toJson( + data + ) + }" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitGrayLineIssueLocationSuccess() + } + } + + override fun onFail(code: Int, msg: String?) { + CallerLogger.d( + TAG, + "submitGrayLineIssueLocation onFail: code=$code, msg=$msg" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitGrayLineIssueLocationFailed( + msg ?: "submitGrayLineIssueLocation onFail" + ) + } + } + + override fun onError() { + super.onError() + var hintStr = "" + if (!NetworkUtils.isConnected(mContext)) { + hintStr = "网络出现异常,请稍后重试" + } else { + hintStr = "上报问题打点异常, 请稍后重试" + } + CallerLogger.d( + TAG, + "submitGrayLineIssueLocation onError, msg=$hintStr" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitGrayLineIssueLocationFailed(hintStr) + } + } + } + ) + } + + fun endGrayTask(grayId: Long, type: EndGrayTaskFeedbackType) { + val submit = EndGrayContrailTaskReq(grayId, type.type) + TaxiRoutingServiceManager.endGrayTask( + mContext, + submit, + object : OchCommonServiceCallback { + override fun onSuccess(data: BaseData?) { + CallerLogger.d( + TAG, + "endGrayTask onSuccess: data=${ + GsonUtils.toJson( + data + ) + }" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitEndTaskSuccess() + } + } + + override fun onFail(code: Int, msg: String?) { + CallerLogger.d( + TAG, + "endGrayTask onFail: code=$code, msg=$msg" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitEndTaskFailed( + msg ?: "endGrayTask onFail" + ) + } + } + + override fun onError() { + super.onError() + var hintStr = "" + if (!NetworkUtils.isConnected(mContext)) { + hintStr = "网络出现异常,请稍后重试" + } else { + hintStr = "上报结束任务异常, 请稍后重试" + } + CallerLogger.d( + TAG, + "endGrayTask onError, msg=$hintStr" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onSubmitEndTaskFailed(hintStr) + } + } + }) + } + + fun startAutoPilot(grayLineBean: GrayLineBean, contrailBean: ContrailBean) { + if (grayLineBean.startSite == null || grayLineBean.endSite == null) { + CallerLogger.e(TAG, "start site or end site is null") + DebugView.printErrorMsg("[启自驾] 当前订单不存在或异常!") + ToastUtils.showShort("当前订单不存在或异常!") + return + } + //根据开关和后台是否发布轨迹启动自驾 + if (FunctionBuildConfig.isPassStartAutopilotCommand && TextUtils.isEmpty( + contrailBean.csvFileUrl + ) + ) { + ToastUtils.showLong("无发布轨迹, 请发布后重试") + DebugView.printErrorMsg("[启自驾] 无发布轨迹, 请发布后重试") + CallerLogger.e( + TAG, "isPassStartAutopilotCommand = " + + FunctionBuildConfig.isPassStartAutopilotCommand + + "busRoutesResult.csvFileUrl = " + contrailBean.csvFileUrl + ) + return + } + if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().autopilotAbilityStatus) { + DebugView.printErrorMsg("[启自驾] ${OCHAdasAbilityManager.getInstance().autopilotUnAbilityReason}") + ToastUtils.showLong( + OCHAdasAbilityManager.getInstance().autopilotUnAbilityReason + + ", 请稍候重试" + ) + return + } + + val parameters = initAutopilotControlParameters(grayLineBean, contrailBean) + if (null == parameters) { + CallerLogger.e(TAG, "AutopilotControlParameters is empty.") + return + } + + CallerAutoPilotControlManager.startAutoPilot(parameters) + DebugView.printInfoMsg("[启自驾] 调用成功") + CallerLogger.d( + TAG, "start autopilot with parameter: %s", + GsonUtil.jsonFromObject(parameters) + ) + mControllerStatusCallback?.startOpenAutopilot() + } + + private fun initAutopilotControlParameters( + grayLineBean: GrayLineBean, + contrailBean: ContrailBean + ): AutopilotControlParameters? { + val parameters = AutopilotControlParameters() + val startWgsLon = grayLineBean.startSite!!.wgs84Lon + val startWgsLat = grayLineBean.startSite!!.wgs84Lat + val endWgsLon = grayLineBean.endSite!!.wgs84Lon + val endWgsLat = grayLineBean.endSite!!.wgs84Lat + parameters.vehicleType = TaxiUnmannedConst.BUSINESSTYPE + parameters.startName = + grayLineBean.startSite!!.siteName // 8.10 拼音首字母大写 改为直接传中文 + parameters.endName = + grayLineBean.endSite!!.siteName // 8.10 拼音首字母大写 改为直接传中文 + parameters.startLatLon = + AutopilotControlParameters.AutoPilotLonLat(startWgsLat, startWgsLon) + parameters.endLatLon = AutopilotControlParameters.AutoPilotLonLat(endWgsLat, endWgsLon) + if (parameters.autoPilotLine == null) { + parameters.autoPilotLine = AutopilotControlParameters.AutoPilotLine( + contrailBean.lineId, + contrailBean.lineName, + contrailBean.csvFileUrl, + contrailBean.csvFileMd5, + contrailBean.txtFileUrl, + contrailBean.txtFileMd5, + contrailBean.contrailSaveTime, + TaxiUnmannedConst.BUSINESSTYPE.toString(), + contrailBean.csvFileUrlDPQP, + contrailBean.csvFileMd5DPQP, + contrailBean.txtFileUrlDPQP, + contrailBean.txtFileMd5DPQP, + contrailBean.contrailSaveTimeDPQP + ) + } + return parameters + } + + /** + * 显示/隐藏 前往任务目的地的导航 + * + * @param isShow + */ + fun startNaviToEndStationByAMap(isShow: Boolean) { + mOrderStatusCallback?.onNaviToEnd(true, isShow) + } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt index f6c285633a..f2459f9e57 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt @@ -1,6 +1,7 @@ package com.mogo.och.taxi.ui.routing import com.mogo.och.taxi.base.IUiIntent +import com.mogo.och.taxi.bean.EndGrayTaskFeedbackType import com.mogo.och.taxi.bean.GrayLineBean sealed class TaxiRoutingUiIntent : IUiIntent { @@ -19,8 +20,15 @@ sealed class TaxiRoutingUiIntent : IUiIntent { TaxiRoutingUiIntent() //开始任务 - object StartTaskAction : TaxiRoutingUiIntent() + data class StartTaskAction(val routingTask: RoutingUIState.RoutingTask) : TaxiRoutingUiIntent() + + //问题打点 + data class SubmitGrayLineIssueLocation(val grayId: Long) : TaxiRoutingUiIntent() //展示结束任务反馈弹框 - object ShowFeedbackDialog : TaxiRoutingUiIntent() + data class ShowFeedbackDialog(val grayId: Long) : TaxiRoutingUiIntent() + + //结束任务 + data class SubmitEndTask(val grayId: Long, val type: EndGrayTaskFeedbackType) : + TaxiRoutingUiIntent() } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt index 69c83eccee..9aef55856b 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiState.kt @@ -9,15 +9,25 @@ data class TaxiRoutingUiState(val routingUiState: RoutingUIState) : IUiState sealed class RoutingUIState { object Init : RoutingUIState() + data class ShowGrayLineList(var data: MutableList) : RoutingUIState() + + data class HideChooseLineLoading(var isCosePage: Boolean) : RoutingUIState() + + data class PostRoutingTaskResult( + val grayLineBean: GrayLineBean?, + val contrailBean: ContrailBean?, + val grayId: Long? + ) : RoutingUIState() + data class RoutingTask( val grayLineBean: GrayLineBean?, val contrailBean: ContrailBean?, val grayId: Long? ) : RoutingUIState() - object ShowFinishTaskButton : RoutingUIState() - object ShowFeedbackDialog : RoutingUIState() - data class ShowGrayLineList(var data: MutableList) : RoutingUIState() + data class ShowFinishTaskButton(val routingTask: RoutingTask) : RoutingUIState() + data class ShowFeedbackDialog(val grayId: Long, val currentTimestamp: Long) : RoutingUIState() + object DismissFeedbackDialog : RoutingUIState() } From eec68fe3bc1e7ab05d9fe990a143c030c01c5339 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Mon, 27 Nov 2023 21:50:18 +0800 Subject: [PATCH 09/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E4=B8=BB=E7=AE=97=E8=B7=AF=E9=AA=8C=E8=AF=81=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=85=B3=E9=94=AE=E8=8A=82=E7=82=B9=E6=97=A5?= =?UTF-8?q?=E5=BF=97=EF=BC=8C=E4=BC=98=E5=8C=96=E7=9B=B8=E5=85=B3=E5=B8=83?= =?UTF-8?q?=E5=B1=80UI=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=BA=92=E6=96=A5=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/och/taxi/ui/debug/DebugView.kt | 80 +++++++++++++++++-- .../routing/TaxiRoutingChooseLineActivity.kt | 3 +- .../routing/TaxiRoutingChooseLineViewModel.kt | 4 + .../taxi/ui/routing/TaxiRoutingFragment.kt | 19 ++++- .../routing/TaxiRoutingFragmentViewModel.kt | 13 ++- .../och/taxi/ui/routing/TaxiRoutingModel.kt | 20 ++++- .../taxi_operation_status_bg_disabled.xml | 10 +++ .../taxi_operation_status_bg_selector_new.xml | 5 ++ .../layout/routing_choose_line_list_item.xml | 57 +++++++------ .../src/main/res/layout/routing_fragment.xml | 19 +++-- .../main/res/layout/taxi_base_fragment.xml | 2 +- .../src/main/res/layout/taxi_debug_order.xml | 18 ++++- 12 files changed, 198 insertions(+), 52 deletions(-) create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_disabled.xml create mode 100755 OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt index fd63f93a6a..041b821113 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt @@ -16,10 +16,14 @@ import android.widget.TextView import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.mogo.commons.module.status.IMogoStatusChangedListener +import com.mogo.commons.module.status.MogoStatusManager +import com.mogo.commons.module.status.StatusDescriptor import com.mogo.commons.utils.MogoAnalyticUtils import com.mogo.eagle.core.function.main.MainMoGoApplication import com.mogo.eagle.core.network.utils.GsonUtil import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.util.AppUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.utils.DateTimeUtil import com.mogo.och.taxi.R @@ -30,6 +34,8 @@ import com.mogo.och.taxi.constant.TaskStatusEnum import com.mogo.och.taxi.constant.TaskTypeEnum import com.mogo.och.taxi.constant.TaxiOrderStatusEnum import com.mogo.och.taxi.ui.task.TaxiTaskModel +import kotlinx.android.synthetic.main.taxi_debug_order.view.btnContainer +import kotlinx.android.synthetic.main.taxi_debug_order.view.currentBusinessModeTextView import kotlinx.android.synthetic.main.taxi_debug_order.view.currentCarStatus import kotlinx.android.synthetic.main.taxi_debug_order.view.currentDataTimestamps import kotlinx.android.synthetic.main.taxi_debug_order.view.currentLineId @@ -39,6 +45,7 @@ import kotlinx.android.synthetic.main.taxi_debug_order.view.currentOrderTrajecto import kotlinx.android.synthetic.main.taxi_debug_order.view.currentStatus import kotlinx.android.synthetic.main.taxi_debug_order.view.currentTaskType import kotlinx.android.synthetic.main.taxi_debug_order.view.debugLogHistoryTextView +import kotlinx.android.synthetic.main.taxi_debug_order.view.debugLogTitleTextView import kotlinx.android.synthetic.main.taxi_debug_order.view.orderEndSiteInfo import kotlinx.android.synthetic.main.taxi_debug_order.view.orderNo import kotlinx.android.synthetic.main.taxi_debug_order.view.orderPreLoadLines @@ -46,13 +53,15 @@ import kotlinx.android.synthetic.main.taxi_debug_order.view.orderStartSiteInfo import kotlinx.android.synthetic.main.taxi_debug_order.view.orderStatus import kotlinx.android.synthetic.main.taxi_debug_order.view.taskEndSite import kotlinx.android.synthetic.main.taxi_debug_order.view.taskStartSite +import kotlinx.android.synthetic.main.taxi_debug_order.view.unmanedTaskOrderContainer import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch public class DebugView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr, defStyleRes), ITaxiTaskWithOrderCallback { +) : LinearLayout(context, attrs, defStyleAttr, defStyleRes), ITaxiTaskWithOrderCallback, + IMogoStatusChangedListener { companion object { const val TAG = "DebugView" private const val ANALYTICS_EVENT_TYPE_DRIVER_UNMANNED_OPERATION_PROCESS_KEY_NODE_LOG = @@ -67,7 +76,7 @@ public class DebugView @JvmOverloads constructor( } fun printWarnMsg(msg: String) { - printMsg("Warn $msg", MainMoGoApplication.getApp().getColor(R.color.background_warn)) + printMsg("Warn $msg", MainMoGoApplication.getApp().getColor(R.color.background_debug)) trackEvent("Warn", msg) } @@ -104,7 +113,10 @@ public class DebugView @JvmOverloads constructor( val map: MutableMap = HashMap() map["level"] = level map["msg"] = msg - MogoAnalyticUtils.track(ANALYTICS_EVENT_TYPE_DRIVER_UNMANNED_OPERATION_PROCESS_KEY_NODE_LOG, map) + MogoAnalyticUtils.track( + ANALYTICS_EVENT_TYPE_DRIVER_UNMANNED_OPERATION_PROCESS_KEY_NODE_LOG, + map + ) } } @@ -128,9 +140,11 @@ public class DebugView @JvmOverloads constructor( init { initBroadcastReceiver() LayoutInflater.from(context).inflate(R.layout.taxi_debug_order, this, true) - debugLogHistoryTextView.setMovementMethod(ScrollingMovementMethod.getInstance()) + debugLogHistoryTextView.movementMethod = ScrollingMovementMethod.getInstance() visibility = GONE logHistoryTextView = debugLogHistoryTextView + + initView() } private fun initBroadcastReceiver() { @@ -142,8 +156,7 @@ public class DebugView @JvmOverloads constructor( fun toggleOrderDebugView() { visibility = if (visibility == View.VISIBLE) View.GONE else View.VISIBLE - val data = TaxiTaskModel.getCurrentTaskWithOrder() - initViewByData(data) + initView() } private fun initTaskWithOrderDataListener() { @@ -154,17 +167,49 @@ public class DebugView @JvmOverloads constructor( TaxiTaskModel.removeTaskWithOrderListener(TAG) } + private fun initCurrentBusinessModeListener() { + MogoStatusManager.getInstance() + .registerStatusChangedListener( + TAG, StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE, this + ) + } + + private fun removeCurrentBusinessModeListener() { + MogoStatusManager.getInstance().unregisterStatusChangedListener( + TAG, + StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE, + this + ) + } + override fun onAttachedToWindow() { super.onAttachedToWindow() initTaskWithOrderDataListener() + initCurrentBusinessModeListener() } override fun onDetachedFromWindow() { super.onDetachedFromWindow() removeTaskWithOrderDataListener() + removeCurrentBusinessModeListener() } - private fun initViewByData(data: QueryCurrentTaskRespBean.Result?) { + private fun initView() { + initCurrentBusinessMode() + initViewByTaskData(TaxiTaskModel.getCurrentTaskWithOrder()) + initDebugLogTextViewTitle() + } + + private fun initCurrentBusinessMode() { + val isRoutingVerifyMode = + MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingVerifyMode + currentBusinessModeTextView.text = + "当前业务模式:${if (isRoutingVerifyMode) "自主算路验证模式" else "无人化运营流程模式"}" + } + + private fun initViewByTaskData(data: QueryCurrentTaskRespBean.Result?) { + //release包下隐藏Mock按钮,避免司机误操作 + btnContainer.visibility = if (AppUtils.isAppDebug()) View.INVISIBLE else View.VISIBLE val curContrail = TaxiTaskModel.getCurrentTaskTrajectory() currentDataTimestamps.text = "【当前数据返回时间】${currentDateTimeString()}" currentCarStatus.text = @@ -194,9 +239,16 @@ public class DebugView @JvmOverloads constructor( "【当前任务Stop信息】StopMd5=${curContrail?.txtFileMd5}, StopDPQPMd5=${curContrail?.txtFileMd5DPQP}" } + private fun initDebugLogTextViewTitle() { + val isRoutingVerifyMode = + MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingVerifyMode + debugLogTitleTextView.text = + if (isRoutingVerifyMode) "自主算路验证模式关键节点日志(司机端)" else "无人化运营流程关键节点日志(司机端)" + } + override fun onTaskWithOrderDataChanged(taskWithOrder: QueryCurrentTaskRespBean.Result?) { d(TAG, "onTaskWithOrderDataChanged") - initViewByData(taskWithOrder) + initViewByTaskData(taskWithOrder) } override fun onTaskCompleted(result: QueryCurrentTaskRespBean.Result?) { @@ -234,4 +286,16 @@ public class DebugView @JvmOverloads constructor( override fun onTaskTripInfoLocalCalculateChanged(meters: Long, timeInSecond: Long) { } + + override fun onStatusChanged(descriptor: StatusDescriptor?, isTrue: Boolean) { + if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { + UiThreadHandler.post { + initCurrentBusinessMode() + initDebugLogTextViewTitle() + unmanedTaskOrderContainer.visibility = if (isTrue) View.GONE else View.VISIBLE + debugLogHistoryTextView.maxLines = if (isTrue) 30 else 15 + } + printInfoMsg("[当前业务模式变化] afterValue=${if (isTrue) "自主算路验证模式" else "无人化运营流程模式"}") + } + } } \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt index 3d092a4711..498430527b 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt @@ -17,6 +17,7 @@ import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R import com.mogo.och.taxi.bean.GrayLineBean import com.mogo.och.taxi.constant.TaxiDriverEventConst +import com.mogo.och.taxi.ui.debug.DebugView import kotlinx.android.synthetic.main.routing_choose_task_activity.btnChooseLineSubmit import kotlinx.android.synthetic.main.routing_choose_task_activity.btnClose import kotlinx.android.synthetic.main.routing_choose_task_activity.chooseLineListView @@ -94,7 +95,7 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { ToastUtils.showLong("请先选择任务") return@setOnClickListener } - ToastUtils.showLong("当前选择的路线contrailId:$mCurrentChosenPosition") + DebugView.printInfoMsg("[选择灰度任务] 当前选择 mCurrentChosenPosition=$mCurrentChosenPosition, ") mLoadingDialog.showLoading() val chosenItem = mRoutingLineList[mCurrentChosenPosition] mViewModel.sendUiIntent( diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt index 8977f56aa0..9f48d57ca1 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt @@ -7,6 +7,7 @@ import com.mogo.och.taxi.base.IUiIntent import com.mogo.och.taxi.bean.GrayLineBean import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp import com.mogo.och.taxi.callback.ITaxiRoutingCallback +import com.mogo.och.taxi.ui.debug.DebugView class TaxiRoutingChooseLineViewModel : BaseViewModel(), ITaxiRoutingCallback { @@ -47,6 +48,7 @@ class TaxiRoutingChooseLineViewModel : BaseViewModel(TaxiDriverEventConst.RoutingActivityEvent.EVENT_TYPE_GET_CHOSEN_LINE_TASK) .register(this) { task -> - ToastUtils.showLong("接收到taskId:${task.grayId}") mViewModel.sendUiIntent(TaxiRoutingUiIntent.ShowRoutingTask(task)) } } @@ -144,6 +144,8 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToStart.visibility = View.VISIBLE naviToEnd.visibility = View.INVISIBLE + updateStartAndEndStationPointByStatus(false) + updateCurrentTaskTripInfo(0,0) data.grayLineBean?.startSite?.also { initStartNaviToStationParam( @@ -181,6 +183,9 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToStart.visibility = View.INVISIBLE naviToEnd.visibility = View.VISIBLE + updateStartAndEndStationPointByStatus(true) + updateCurrentTaskTripInfo(0,0) + routingTask.grayLineBean?.endSite?.also { initStartNaviToStationParam( false, @@ -193,6 +198,16 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { } } + private fun updateStartAndEndStationPointByStatus(isGoingToStation: Boolean) { + if (isGoingToStation) {// 即将到达的站点 + startPoint.setImageResource(R.drawable.taxi_driver_circle_blue_big) + endPoint.setImageResource(R.drawable.taxi_driver_circle_green_big) + } else {// 到达站点 或 已经经过的站点 + startPoint.setImageResource(R.drawable.taxi_driver_circle_green_big) + endPoint.setImageResource(R.drawable.taxi_driver_circle_blue_big) + } + } + private fun showFeedbackDialog(grayId: Long) { if (mFeedbackDialog == null) { val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt index 8465751e2f..f9eeb017d5 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -11,6 +11,7 @@ import com.mogo.och.taxi.base.IUiIntent import com.mogo.och.taxi.bean.GrayLineBean import com.mogo.och.taxi.bean.StartGrayAndQueryContrailRsp import com.mogo.och.taxi.callback.ITaxiRoutingCallback +import com.mogo.och.taxi.ui.debug.DebugView class TaxiRoutingFragmentViewModel : BaseViewModel(), ITaxiRoutingCallback { @@ -33,11 +34,13 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { + DebugView.printInfoMsg("[选择任务] 跳转到选择任务列表") val intent = Intent(mContext, TaxiRoutingChooseLineActivity::class.java) mContext?.startActivity(intent) } is TaxiRoutingUiIntent.ShowRoutingTask -> { + DebugView.printInfoMsg("[选择任务] 展示当前选择任务,刷新UI") val task = intent.routingTask sendUiState { copy( @@ -51,12 +54,15 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { + DebugView.printInfoMsg("[开始任务] 准备开始任务") val grayLineBean = intent.routingTask.grayLineBean val contrailBean = intent.routingTask.contrailBean if (grayLineBean == null || contrailBean == null) { ToastUtils.showShort("灰度线路或轨迹信息异常,请稍后再试") + DebugView.printErrorMsg("[开始任务] 灰度线路或轨迹信息异常,请稍后再试") return } + DebugView.printInfoMsg("[启自驾] 准备启动自驾") TaxiRoutingModel.startAutoPilot(grayLineBean!!, contrailBean!!) sendUiState { copy( @@ -66,6 +72,7 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { + DebugView.printInfoMsg("[上报打点] 准备上报打点") val grayId = intent.grayId val currentLocation = CallerChassisLocationGCJ02ListenerManager.getChassisLocationGCJ02() @@ -77,6 +84,7 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { + DebugView.printInfoMsg("[结束任务] 展示结束任务弹框") sendUiState { copy( routingUiState = RoutingUIState.ShowFeedbackDialog( @@ -88,6 +96,7 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { + DebugView.printInfoMsg("[结束任务] 准备结束任务,grayId=${intent.grayId}, type=${intent.type.name}") TaxiRoutingModel.endGrayTask(intent.grayId, intent.type) } } @@ -106,11 +115,11 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { override fun onSuccess(data: QueryGrayContrailListRsp) { @@ -74,6 +75,7 @@ object TaxiRoutingModel { TAG, "queryRoutingGrayLineList onSuccess: data=${GsonUtils.toJson(data)}" ) + DebugView.printInfoMsg("[查询灰度路线] 请求success,dataSize=${data?.data?.size}") val result = mutableListOf() data.data?.also { result.addAll(it) @@ -89,6 +91,7 @@ object TaxiRoutingModel { TAG, "queryRoutingGrayLineList onFail: code=$code, msg=$msg" ) + DebugView.printErrorMsg("[查询灰度路线] 请求fail, code=$code, msg=$msg, sn=${MoGoAiCloudClientConfig.getInstance().sn}") ToastUtils.showShort("查询灰度线路列表异常, 请稍后重试, code=$code") mTaxiRoutingCallbackMap.forEach { val listener = it.value @@ -108,8 +111,9 @@ object TaxiRoutingModel { } CallerLogger.d( TAG, - "queryRoutingGrayLineList onError, msg=$hintStr" + "queryRoutingGrayLineList onError, msg=$hintStr, sn=${MoGoAiCloudClientConfig.getInstance().sn}" ) + DebugView.printErrorMsg("[查询灰度路线] 请求error, msg=$hintStr") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onQueryRoutingGrayLineListFailed(hintStr) @@ -119,6 +123,7 @@ object TaxiRoutingModel { } fun startGrayTaskAndQueryRoutingContrail(contrailId: Long, grayLineBean: GrayLineBean) { + DebugView.printInfoMsg("[开始灰度任务&查询轨迹详情] 准备发送请求,contrailId=${contrailId}, lineId=${grayLineBean.lineId}") TaxiRoutingServiceManager.startGrayTaskAndQueryRoutingContrail( mContext, sn = MoGoAiCloudClientConfig.getInstance().sn, @@ -134,6 +139,7 @@ object TaxiRoutingModel { ) }" ) + DebugView.printInfoMsg("[开始灰度任务&查询轨迹详情] 请求success,taskId=${data.taskId}, contrailId=${contrailId}, lineId=${grayLineBean.lineId}") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onStartGrayTaskAndQueryContrailSuccess(data) @@ -145,6 +151,7 @@ object TaxiRoutingModel { TAG, "startGrayTaskAndQueryRoutingContrail onFail: code=$code, msg=$msg" ) + DebugView.printErrorMsg("[开始灰度任务&查询轨迹详情] 请求fail, code=$code, msg=$msg, contrailId=${contrailId}, lineId=${grayLineBean.lineId}") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onStartGrayTaskAndQueryContrailFailed( @@ -163,8 +170,9 @@ object TaxiRoutingModel { } CallerLogger.d( TAG, - "startGrayTaskAndQueryRoutingContrail onError, msg=$hintStr" + "startGrayTaskAndQueryRoutingContrail onError, msg=$hintStr, contrailId=${contrailId}, lineId=${grayLineBean.lineId}" ) + DebugView.printErrorMsg("[开始灰度任务&查询轨迹详情] 请求error, msg=$hintStr") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onStartGrayTaskAndQueryContrailFailed(hintStr) @@ -175,6 +183,7 @@ object TaxiRoutingModel { } fun submitGrayLineIssueLocation(grayId: Long, gcjLon: Double, gcjLat: Double) { + DebugView.printInfoMsg("[上报打点] 准备发送请求,grayId=$grayId, gcjLon=$gcjLon, gcjLat=$gcjLat") val submit = SubmitGrayLineIssueLocationReq(grayId, gcjLon, gcjLat) TaxiRoutingServiceManager.submitGrayLineIssueLocation( mContext, @@ -189,6 +198,7 @@ object TaxiRoutingModel { ) }" ) + DebugView.printInfoMsg("[上报打点] 准备success,grayId=$grayId, gcjLon=$gcjLon, gcjLat=$gcjLat") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitGrayLineIssueLocationSuccess() @@ -200,6 +210,7 @@ object TaxiRoutingModel { TAG, "submitGrayLineIssueLocation onFail: code=$code, msg=$msg" ) + DebugView.printErrorMsg("[上报打点] 请求fail, code=$code, msg=$msg, grayId=$grayId") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitGrayLineIssueLocationFailed( @@ -220,6 +231,7 @@ object TaxiRoutingModel { TAG, "submitGrayLineIssueLocation onError, msg=$hintStr" ) + DebugView.printErrorMsg("[上报打点] 请求error, msg=$hintStr, grayId=$grayId") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitGrayLineIssueLocationFailed(hintStr) @@ -230,6 +242,7 @@ object TaxiRoutingModel { } fun endGrayTask(grayId: Long, type: EndGrayTaskFeedbackType) { + DebugView.printInfoMsg("[结束灰度任务] 准备发送请求,grayId=$grayId, type=${type.type}, typeName=${type.name}") val submit = EndGrayContrailTaskReq(grayId, type.type) TaxiRoutingServiceManager.endGrayTask( mContext, @@ -244,6 +257,7 @@ object TaxiRoutingModel { ) }" ) + DebugView.printInfoMsg("[结束灰度任务] 请求success,grayId=$grayId, type=${type.type}, typeName=${type.name}") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitEndTaskSuccess() @@ -255,6 +269,7 @@ object TaxiRoutingModel { TAG, "endGrayTask onFail: code=$code, msg=$msg" ) + DebugView.printErrorMsg("[结束灰度任务] 请求fail, code=$code, msg=$msg, grayId=$grayId, type=${type.type}, typeName=${type.name}") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitEndTaskFailed( @@ -275,6 +290,7 @@ object TaxiRoutingModel { TAG, "endGrayTask onError, msg=$hintStr" ) + DebugView.printErrorMsg("[结束灰度任务] 请求error, msg=$hintStr, grayId=$grayId, type=${type.type}, typeName=${type.name}") mTaxiRoutingCallbackMap.forEach { val listener = it.value listener.onSubmitEndTaskFailed(hintStr) diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_disabled.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_disabled.xml new file mode 100644 index 0000000000..25386e2c3c --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_disabled.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml new file mode 100755 index 0000000000..8c100f97eb --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml index 823b8a5fe7..bfa94a26f9 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml @@ -7,48 +7,55 @@ android:layout_marginTop="@dimen/dp_5" android:background="@drawable/routing_choose_line_shape_select_line_item_bg_normal"> + + - - + app:layout_constraintTop_toBottomOf="@+id/switchLineNameTextView" + tools:text="本车今日已验证:1次" /> \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml index 7e48169c62..48772aa129 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml @@ -17,16 +17,19 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> - diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_base_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_base_fragment.xml index d990f1b3fe..92d39f3331 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_base_fragment.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_base_fragment.xml @@ -232,7 +232,7 @@ android:layout_height="102dp" android:layout_marginLeft="48dp" android:layout_marginBottom="@dimen/module_mogo_och_margin_bottom" - android:background="@drawable/taxi_operation_status_bg" + android:background="@drawable/taxi_operation_status_bg_selector_new" android:drawableLeft="@drawable/shape_size_operation_out" android:drawablePadding="10dp" android:elevation="@dimen/dp_10" diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_debug_order.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_debug_order.xml index 646b94ab4e..e56f833b6c 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_debug_order.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/taxi_debug_order.xml @@ -1,13 +1,23 @@ - + android:layout_height="wrap_content" + android:text="当前业务模式:" + android:textColor="@android:color/white" + android:textSize="@dimen/dp_24" /> + + Date: Tue, 28 Nov 2023 16:16:48 +0800 Subject: [PATCH 10/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20opt:=20=E4=BC=98=E5=8C=96=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E5=88=87=E6=8D=A2=E4=BA=92=E6=96=A5=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=90=AF=E8=87=AA=E9=A9=BE=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E4=BC=98=E5=8C=96=E9=80=89=E6=8B=A9=E8=B7=AF?= =?UTF-8?q?=E7=BA=BFitem=20UI=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/taxi/ui/base/BaseTaxiTabFragment.kt | 21 +++--- .../com/mogo/och/taxi/ui/base/TaxiFragment.kt | 1 + .../mogo/och/taxi/ui/base/TaxiPresenter.java | 7 +- .../routing/TaxiRoutingChooseLineActivity.kt | 2 +- .../taxi/ui/routing/TaxiRoutingFragment.kt | 2 +- .../routing/TaxiRoutingFragmentViewModel.kt | 7 ++ .../och/taxi/ui/routing/TaxiRoutingModel.kt | 17 +++++ .../taxi/ui/routing/TaxiRoutingUiIntent.kt | 4 +- .../taxi/ui/task/TaxiCurrentTaskViewModel.kt | 11 +++ .../mogo/och/taxi/ui/task/TaxiTaskModel.kt | 29 ++++++- .../layout/routing_choose_line_list_item.xml | 75 +++++++++---------- .../src/main/res/layout/routing_fragment.xml | 4 +- .../core/function/hmi/ui/MoGoHmiProvider.kt | 4 + .../function/hmi/ui/setting/SOPSettingView.kt | 2 +- .../api/hmi/warning/IMoGoHmiProvider.kt | 5 ++ .../function/call/hmi/CallerHmiManager.kt | 7 ++ .../module/status/IMogoStatusManager.java | 12 ++- .../module/status/MogoStatusManager.java | 10 +++ .../module/status/StatusDescriptor.java | 9 ++- 19 files changed, 163 insertions(+), 66 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt index 39364027fa..a34b987022 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt @@ -201,21 +201,22 @@ abstract class BaseTaxiTabFragment> : MvpFragment - if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { - UiThreadHandler.post { - module_mogo_och_operation_status.isEnabled = !isTrue - } - } - } +// 20231128 如果设置enable=false, 需要切图,所以先不设置了 +// MogoStatusManager.getInstance() +// .registerStatusChangedListener(TAG, StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE +// ) { descriptor, isTrue -> +// if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { +// UiThreadHandler.post { +// module_mogo_och_operation_status.isEnabled = !isTrue +// } +// } +// } taxi_close_navi_icon.setOnClickListener { showAmapNaviToStationFragment(false) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index e53a9b617d..d6fe659f2c 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -262,6 +262,7 @@ class TaxiFragment : BaseTaxiTabFragment(), null ) } + MogoStatusManager.getInstance().setTaxiUnmanedDriverTakingOrders(TAG, inOperation) } override fun onMapLoaded() {} diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java index ab3e77109b..7cf4e7c07b 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiPresenter.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.lifecycle.LifecycleOwner; import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.module.status.MogoStatusManager; import com.mogo.commons.mvp.Presenter; import com.mogo.eagle.core.data.map.MogoLocation; import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; @@ -79,7 +80,11 @@ public class TaxiPresenter extends Presenter implements ITaxiADASS * 开启自动驾驶 自驾模式 */ public void startAutoPilot() { - TaxiTaskModel.INSTANCE.startAutopilotByClick(); + if (MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingVerifyMode()) { + TaxiRoutingModel.INSTANCE.startAutoPilotByClick(); + } else { + TaxiTaskModel.INSTANCE.startAutopilotByClick(); + } } // 登出 diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt index 498430527b..e9c72c0f2a 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineActivity.kt @@ -154,7 +154,7 @@ class TaxiRoutingChooseLineActivity : AppCompatActivity() { } private fun loadData() { - mViewModel.sendUiIntent(TaxiRoutingUiIntent.QueryRoutingGrayLineList) + mViewModel.sendUiIntent(TaxiRoutingUiIntent.QueryRoutingGrayLineList(System.currentTimeMillis())) } private fun onRoutingGrayLineListChanged(data: MutableList) { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 5a70da3abe..038ca5f52d 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -81,7 +81,7 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { private fun initViewListener() { btnChooseTask.setOnClickListener { - mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartChooseLineAction) + mViewModel.sendUiIntent(TaxiRoutingUiIntent.StartChooseLineAction(System.currentTimeMillis())) } } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt index f9eeb017d5..8afde1aa64 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -3,6 +3,7 @@ package com.mogo.och.taxi.ui.routing import android.content.Context import android.content.Intent import com.mogo.commons.AbsMogoApplication +import com.mogo.commons.module.status.MogoStatusManager import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils @@ -51,6 +52,8 @@ class TaxiRoutingFragmentViewModel : BaseViewModel { @@ -63,6 +66,7 @@ class TaxiRoutingFragmentViewModel : BaseViewModel = ConcurrentHashMap() @@ -299,6 +302,20 @@ object TaxiRoutingModel { }) } + fun updateCurrentGrayLineAndContrail(grayLineBean: GrayLineBean?, contrailBean: ContrailBean?) { + currentGrayLineBean = grayLineBean + currentContrailBean = contrailBean + } + + fun startAutoPilotByClick() { + if (currentGrayLineBean == null || currentContrailBean == null) { + CallerLogger.e(TAG, "startAutoPilotByClick 异常,currentGrayLineBean == null || currentContrailBean == null") + DebugView.printErrorMsg("[启自驾] startAutoPilotByClick 异常,currentGrayLineBean == null || currentContrailBean == null") + return + } + startAutoPilot(currentGrayLineBean!!, currentContrailBean!!) + } + fun startAutoPilot(grayLineBean: GrayLineBean, contrailBean: ContrailBean) { if (grayLineBean.startSite == null || grayLineBean.endSite == null) { CallerLogger.e(TAG, "start site or end site is null") diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt index f2459f9e57..6a39b3f763 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingUiIntent.kt @@ -7,10 +7,10 @@ import com.mogo.och.taxi.bean.GrayLineBean sealed class TaxiRoutingUiIntent : IUiIntent { //打开选择路线页面 - object StartChooseLineAction : TaxiRoutingUiIntent() + data class StartChooseLineAction(val currentTimestamp: Long) : TaxiRoutingUiIntent() //查询灰度线路列表 - object QueryRoutingGrayLineList : TaxiRoutingUiIntent() + data class QueryRoutingGrayLineList(val currentTimestamp: Long) : TaxiRoutingUiIntent() //开始一个任务并查询此任务对应的轨迹详情 data class StartTaskAndQueryContrail(val grayLineBean: GrayLineBean) : TaxiRoutingUiIntent() diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt index 15ded8c048..3e1ecede02 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt @@ -1,6 +1,7 @@ package com.mogo.och.taxi.ui.task import com.mogo.commons.AbsMogoApplication +import com.mogo.commons.module.status.MogoStatusManager import com.mogo.eagle.core.data.BaseData import com.mogo.eagle.core.data.config.FunctionBuildConfig import com.mogo.eagle.core.data.map.MogoLocation @@ -229,6 +230,12 @@ class TaxiCurrentTaskViewModel : BaseViewModel(), d(TAG, "onTaskWithOrderChanged = result = " + GsonUtil.jsonFromObject(result)) DebugView.printInfoMsg("[查询TaskWithOrder信息] 更新数据, 刷新UI") updateTaskAndOrderUi(result) + // 设置task执行相关状态,切换模式时判断使用 + if (result == null || result.taskType == TaskTypeEnum.None.code) { + MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false) + } else { + MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, true) + } } override fun onTaskStarted(result: QueryCurrentTaskRespBean.Result?) { @@ -318,6 +325,8 @@ class TaxiCurrentTaskViewModel : BaseViewModel(), VoiceNotice.showNotice("已取消行程") //取消自驾,D档位会溜车 map3.6.0 修改 TaxiTaskModel.cancelAutopilot() + // 设置task执行相关状态,切换模式时判断使用 + MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false) } override fun onOrderArriveAtEnd(orderNo: String) { @@ -339,6 +348,8 @@ class TaxiCurrentTaskViewModel : BaseViewModel(), TaxiTaskModel.startPrepareTaskDelay(CallerUnmannedListenerManager.getPullTime().toLong(), it.siteId) } + // 设置task执行相关状态,切换模式时判断使用 + MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false) } override fun onStartAutopilot(postDelayTime: Long) { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt index 5ffa7094c5..b523d54472 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt @@ -31,7 +31,11 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant -import com.mogo.eagle.core.utilcode.util.* +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.eagle.core.utilcode.util.DrivingDirectionUtils +import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager import com.mogo.och.common.module.biz.common.socketmessage.data.OCHOperationalMessage import com.mogo.och.common.module.biz.constant.LoginStatusManager @@ -48,9 +52,22 @@ import com.mogo.och.common.module.manager.distancemamager.TrajectoryAndDistanceM import com.mogo.och.common.module.map.AmapNaviToDestinationModel import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil.coordinateConverterWgsToGcjLocations import com.mogo.och.common.module.voice.VoiceNotice -import com.mogo.och.taxi.bean.* -import com.mogo.och.taxi.callback.* -import com.mogo.och.taxi.constant.* +import com.mogo.och.taxi.bean.PrepareTaskRespBean +import com.mogo.och.taxi.bean.QueryCarOrderByNoRespBean +import com.mogo.och.taxi.bean.QueryCurrentTaskRespBean +import com.mogo.och.taxi.bean.StartServiceRespBean +import com.mogo.och.taxi.bean.TrajectoryListRespBean +import com.mogo.och.taxi.callback.IOCHTaxiAutopilotPlanningCallback +import com.mogo.och.taxi.callback.ITaxiADASStatusCallback +import com.mogo.och.taxi.callback.ITaxiCarServiceCallback +import com.mogo.och.taxi.callback.ITaxiControllerStatusCallback +import com.mogo.och.taxi.callback.ITaxiOrderStatusCallback +import com.mogo.och.taxi.callback.ITaxiTaskWithOrderCallback +import com.mogo.och.taxi.constant.TaskStatusEnum +import com.mogo.och.taxi.constant.TaskTypeEnum +import com.mogo.och.taxi.constant.TaxiCarServingStatusManager +import com.mogo.och.taxi.constant.TaxiOrderStatusEnum +import com.mogo.och.taxi.constant.TaxiUnmannedConst import com.mogo.och.taxi.constant.TaxiUnmannedConst.Companion.BUSINESSTYPE import com.mogo.och.taxi.network.TaxiTaskWithOrderServiceManager import com.mogo.och.taxi.ui.debug.DebugView @@ -1406,6 +1423,10 @@ object TaxiTaskModel { mCurrentTaskWithOrder = null mDriveToNearestStationTask = null DebugView.printInfoMsg("[登出] 退出登陆") + MogoStatusManager.getInstance().setTaxiUnmanedDriverPerformTask(TAG, false) + MogoStatusManager.getInstance().setTaxiUnmanedDriverTakingOrders(TAG, false) + MogoStatusManager.getInstance().setTaxiUnmanedDriverLineRoutingPerformTask(TAG, false) + MogoStatusManager.getInstance().setTaxiUnmanedDriverLineRoutingVerifyMode(TAG, false) } //导航去订单终点目的地 diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml index bfa94a26f9..d7b1c6849a 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml @@ -1,61 +1,56 @@ - + android:paddingStart="@dimen/dp_78" + android:paddingEnd="@dimen/dp_78" + android:layout_marginTop="@dimen/dp_8" + android:background="@drawable/routing_choose_line_shape_select_line_item_bg_normal" + android:orientation="vertical"> - + android:layout_marginEnd="@dimen/dp_20"> - + - \ No newline at end of file + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml index 48772aa129..7e0db62f44 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml @@ -20,9 +20,7 @@ Date: Tue, 28 Nov 2023 21:18:19 +0800 Subject: [PATCH 11/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20opt:=20=E4=BC=98=E5=8C=96=20=E6=8E=A5?= =?UTF-8?q?=E5=8D=95=20=E6=8C=89=E9=92=AE=E7=BD=AE=E7=81=B0=20=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E5=B1=95=E7=A4=BA=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/taxi/ui/base/BaseTaxiTabFragment.kt | 11 -------- .../com/mogo/och/taxi/ui/base/TaxiFragment.kt | 24 ++++++++++++++++++ .../taxi_autopilot_text_color_selector.xml | 3 ++- .../drawable-xhdpi/taxi_out_btn_disable.png | Bin 0 -> 2217 bytes .../shape_size_operation_out_disable.xml | 7 +++++ .../src/main/res/layout/routing_fragment.xml | 10 +++++--- 6 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/taxi_out_btn_disable.png create mode 100644 OCH/taxi/unmanned-driver/src/main/res/drawable/shape_size_operation_out_disable.xml diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt index a34b987022..8a4be834c4 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt @@ -12,7 +12,6 @@ import androidx.fragment.app.FragmentTransaction import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.mogo.commons.AbsMogoApplication import com.mogo.commons.module.status.MogoStatusManager -import com.mogo.commons.module.status.StatusDescriptor import com.mogo.commons.mvp.IView import com.mogo.commons.mvp.MvpFragment import com.mogo.commons.mvp.Presenter @@ -207,16 +206,6 @@ abstract class BaseTaxiTabFragment> : MvpFragment -// if (StatusDescriptor.TAXI_UNMANED_DRIVER_LINE_ROUTING_VERIFY_MODE == descriptor) { -// UiThreadHandler.post { -// module_mogo_och_operation_status.isEnabled = !isTrue -// } -// } -// } taxi_close_navi_icon.setOnClickListener { showAmapNaviToStationFragment(false) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index d6fe659f2c..5edb67d7cc 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -167,6 +167,7 @@ class TaxiFragment : BaseTaxiTabFragment(), } else { showTaskFragment() } + updateOperationBtnStatusOnModeChange(isTrue) } } } @@ -265,6 +266,29 @@ class TaxiFragment : BaseTaxiTabFragment(), MogoStatusManager.getInstance().setTaxiUnmanedDriverTakingOrders(TAG, inOperation) } + private fun updateOperationBtnStatusOnModeChange(isRoutingVerifyMode: Boolean) { + if (MogoStatusManager.getInstance().isTaxiUnmanedDriverTakingOrders) { + return + } + module_mogo_och_operation_status.isEnabled = !isRoutingVerifyMode + val isBtnEnable = module_mogo_och_operation_status.isEnabled + if (isBtnEnable) { + module_mogo_och_operation_status.setCompoundDrawablesWithIntrinsicBounds( + resources.getDrawable(R.drawable.shape_size_operation_out), + null, + null, + null + ) + } else { + module_mogo_och_operation_status.setCompoundDrawablesWithIntrinsicBounds( + resources.getDrawable(R.drawable.shape_size_operation_out_disable), + null, + null, + null + ) + } + } + override fun onMapLoaded() {} fun updateAutopilotStatus(status: Int) { diff --git a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml index 16cef94271..a5d1f74aec 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml @@ -1,4 +1,5 @@ - + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/taxi_out_btn_disable.png b/OCH/taxi/unmanned-driver/src/main/res/drawable-xhdpi/taxi_out_btn_disable.png new file mode 100644 index 0000000000000000000000000000000000000000..779e39d482cdbef02ae70796f6f64850fec5f3b7 GIT binary patch literal 2217 zcmV;a2v+xrP)Px-V@X6oRA@uZT77U-R~7%AyKfhvm8lS^w4^0KAT^E-qymL;#uP)9qT|p|s`aC- z*6)vY)UoO?j(<3vD)vKBTeZ{L7FvktjFn2E;5bfeY7~b*)V7!wOB+it5=lsCvhN<} zzI*T6``*5{`!?A?@668b`?%+v-#Nc??z!(RVFH7h=K+`l;9LMS0TD@47{D-qej<9Q zR+%*!!OZgktOam>t%_>A{}_P1M06zUyv#tDxf#IK07O>dle|v?*hxf(v&hK=gqhC) z@C5*#5qcWHKL8A6QBuP_uLp1mfY+HhMF8I?qEppmWCe0LfYnCWaR3hx(MUDn6S>aJ zGXQ)9z#Gl{CyD4lHCb7K+yp>*OO0(r^n5kJlex~!3jkbeWDF6}oz>)31;Wg#I(^az z8U^q@B2pD*$_6tlyS@Zqx>0fu5%pJ6m<7mX0N!PU{EdiyIb{eO!OXk?K&v_R1QGpl zvOqozK$TrJeoaJ&&Jd8d0eGL$b%cl>oG=h(E&%v4fSeI>2N9`7Ysv>RtHt(aqsRxa zg^0$|6j!7cGcN|P$xMEQh<-Zd2%_}55x|?wsU1Z0+(dz_1JGtBXDWmB1j@{A+5Za> zJvLDwp9gTBnf!Aida<5{R+Gid7XkRFxo?n&eo!+IW}Xe;GiKtehNG%&IAepERXe0| zbed86BO)3|G9Wcan0bY15Y@bAh^Xs~A&BP5MgT45lxifOt`*1!0W36=b`#OTvjk)r zfGdseULx9_83;40=I|>{lXw>qojglGW&-%4(XE=u?-G&vj*LWVG4mn-A24?wC!)L0 z1_-N@nLp(;kq;BmKeGb40>E-}b2ky~JIg>i0IW1N{E3JjPXuC`w08nn3P9~W>OQ2Y zck0XjR!V}?(tKCCR({VA1P(Qvi{BHG45-D-YXGdOr}c3I1A84XnT(GEbHLd7zK^Ho zHPC(wM77LnLo=yijSoE?H$K6zvZ%OVt3=EXJR?rcn@zV{AYXSH!MR68}>wlk1q#(_<)(m&~<>ctXINRxs7g0<%DZ?}Lly z(rybxRV-Dx!r_L#r{`JRe)nz+3=YHdJP7m2dm{MVFl#1mxTYPgOBze_D;e*2e`sg~ z-`VmIdXKye;Z1{QWC~9p=M^A?z*}0I@S%+z@N%Axj1S1102JqZaiHa5deQ=UGk~ko zO6Ij6+k%0?AqX#D0wR0H_y%i`^ zUKAdFc{a;uJ-DVo%^tN z|I<#SJ>(UDAkreFT1Wc|tY~XBiLPC)fXvQ|Esc#d8a9n1s1GqL&R&OkwVxzx$2Wk(VfzdO)_N4g$QjfSSKz*QUC(LBE~TDBQu z%NFKtQ*uKfr%v-HBAfKaZ%oK`i{iV%e8Ub$FrF+yq$p5jZ#i+GQsa=7w39w}9vQlf<( zkMUmT0U(1+*R%@HB^{?kC8HFt;2!U&KT`uRF$*;t~IYrI(#BF3lhD_owJRh=wty>Uirl$npNUFzMR z2&DJld?f?R!YCw_%WCazTosYu9p(RGCpw= z6!%ubLxCjTr^<5V#q%I>4nY>q5%;Zap}s^Q>SXUxZXP3C?n|lOs#2O)BGid*XR|!s zsqj=Kx%^5n1T*``$;%&j@6zb|_p0v@mC)yp@n(xW^gs?>O%3!+{QP8(f7Ly{8N&Q0 zA=s1)_{CyZ=c;KHb-m_*?CSQ*oW@dgb*`%HwAUbzaR-QAY*~8s0n+;l-$I1EOPd_9 z?c($6|Hpw}JmufQLhG`P&h(tvw*Kvvb!Cdkzxuh;=iomgc8t;pwl+19`cFz-$FA;T zr<7FEB``WXDz;wVURhTrAbov2W8A|!$ymSwC*&CREV_`6))j#f_UNB^##qr`Cz%$I rD?t) literal 0 HcmV?d00001 diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/shape_size_operation_out_disable.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/shape_size_operation_out_disable.xml new file mode 100644 index 0000000000..13ce8bb87d --- /dev/null +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/shape_size_operation_out_disable.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml index 7e0db62f44..fb9ef5ed94 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_fragment.xml @@ -20,9 +20,9 @@ + app:layout_constraintTop_toBottomOf="@+id/taskTitleTv" + app:layout_constraintBottom_toBottomOf="parent"/> From 18345765fe5ca5848b47e6f4a92f3b8311985b9e Mon Sep 17 00:00:00 2001 From: aibingbing Date: Wed, 29 Nov 2023 15:13:34 +0800 Subject: [PATCH 12/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=E5=88=87=E6=8D=A2=E6=A8=A1=E5=BC=8F=E6=97=B6=20fragme?= =?UTF-8?q?nt=E7=BB=91=E5=AE=9A=E7=9A=84viewmodel=E4=B8=8D=E8=B5=B7?= =?UTF-8?q?=E4=BD=9C=E7=94=A8=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index 5edb67d7cc..7b8e89450c 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -177,7 +177,8 @@ class TaxiFragment : BaseTaxiTabFragment(), val transaction: FragmentTransaction = childFragmentManager.beginTransaction() if (routingVerifyFragment?.get()?.isVisible == true) { routingVerifyFragment?.get()?.also { - transaction.hide(it) + transaction.remove(it) + routingVerifyFragment = null } } if (taskTabFragment?.get() == null) { @@ -193,7 +194,8 @@ class TaxiFragment : BaseTaxiTabFragment(), val transaction: FragmentTransaction = childFragmentManager.beginTransaction() if (taskTabFragment?.get()?.isVisible == true) { taskTabFragment?.get()?.also { - transaction.hide(it) + transaction.remove(it) + taskTabFragment = null } } if (routingVerifyFragment?.get() == null) { From 4a7d84accdff67948e1789921cd8676d9f8c1711 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Wed, 29 Nov 2023 15:24:16 +0800 Subject: [PATCH 13/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=E5=88=87=E6=8D=A2=E6=A8=A1=E5=BC=8F=E6=97=B6=20?= =?UTF-8?q?=E6=8E=A5=E5=8D=95=E6=8C=89=E9=92=AE=20icon=E6=9C=AA=E7=BD=AE?= =?UTF-8?q?=E7=81=B0=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt index 7b8e89450c..e3d408f378 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/TaxiFragment.kt @@ -265,6 +265,7 @@ class TaxiFragment : BaseTaxiTabFragment(), null ) } + updateOperationBtnStatusOnModeChange(MogoStatusManager.getInstance().isTaxiUnmanedDriverLineRoutingVerifyMode) MogoStatusManager.getInstance().setTaxiUnmanedDriverTakingOrders(TAG, inOperation) } From 37e6028086e68156c8c893982a0282e33f87f1ce Mon Sep 17 00:00:00 2001 From: aibingbing Date: Wed, 29 Nov 2023 16:50:20 +0800 Subject: [PATCH 14/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20=E5=AE=8C=E6=88=90=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=90=8E=20=E9=9A=90=E8=97=8F=E5=AF=BC=E8=88=AA?= =?UTF-8?q?=E5=B0=8F=E5=9C=B0=E5=9B=BE=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt index 8afde1aa64..0603a5e2b9 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -136,6 +136,7 @@ class TaxiRoutingFragmentViewModel : BaseViewModel Date: Thu, 30 Nov 2023 15:14:32 +0800 Subject: [PATCH 15/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=88=B0=E7=BB=88=E7=82=B9?= =?UTF-8?q?=E5=90=8E=20=E4=B8=BB=E5=8A=A8=E5=BC=B9=E5=87=BA=20=E7=BB=93?= =?UTF-8?q?=E6=9D=9F=E4=BB=BB=E5=8A=A1=E5=BC=B9=E6=A1=86=EF=BC=9B=20refact?= =?UTF-8?q?or:=20=E7=AE=97=E8=B7=AF=E6=A8=A1=E5=BC=8F=E4=B8=8B=20=E6=8E=A5?= =?UTF-8?q?=E5=8D=95=E6=8C=89=E9=92=AE=20=E4=BF=AE=E6=94=B9=E6=88=90?= =?UTF-8?q?=E7=BD=AE=E7=81=B0UI=EF=BC=8C=E4=BD=86=E6=98=AF=E4=BE=9D?= =?UTF-8?q?=E7=84=B6=E5=8F=AF=E7=82=B9=E5=87=BB=EF=BC=8C=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E6=97=B6=E6=8F=90=E7=A4=BAtoast;=20fix:=20=E5=88=B0=E8=BE=BE?= =?UTF-8?q?=E7=BB=88=E7=82=B9=E5=90=8E=20=E9=9C=80=E8=A6=81=E4=B8=BB?= =?UTF-8?q?=E5=8A=A8=E5=8F=96=E6=B6=88=E8=87=AA=E5=8A=A8=E9=A9=BE=E9=A9=B6?= =?UTF-8?q?=EF=BC=8C=E5=90=A6=E5=88=99=E4=BC=9A=E4=B8=80=E7=9B=B4=E5=9C=A8?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=A9=BE=E9=A9=B6=E7=8A=B6=E6=80=81=E5=92=8C?= =?UTF-8?q?D=E6=8C=A1=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/taxi/callback/ITaxiRoutingCallback.kt | 2 + .../och/taxi/ui/base/BaseTaxiTabFragment.kt | 2 +- .../com/mogo/och/taxi/ui/base/TaxiFragment.kt | 4 +- .../routing/TaxiRoutingChooseLineViewModel.kt | 6 + .../routing/TaxiRoutingFragmentViewModel.kt | 52 +++++- .../och/taxi/ui/routing/TaxiRoutingModel.kt | 160 +++++++++++++++++- .../taxi_autopilot_text_color_selector.xml | 4 +- .../taxi_operation_status_bg_selector_new.xml | 4 +- 8 files changed, 222 insertions(+), 12 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt index 980921759f..22fcb34e93 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/callback/ITaxiRoutingCallback.kt @@ -12,4 +12,6 @@ interface ITaxiRoutingCallback { fun onSubmitGrayLineIssueLocationFailed(errorStr: String) fun onSubmitEndTaskSuccess() fun onSubmitEndTaskFailed(errorStr: String) + fun onAutoPilotArriveAtEndStation(grayId: Long?) + fun onGDMapArriveAtEndStation(grayId: Long?) } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt index a2aac8167a..4855ec3b86 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/base/BaseTaxiTabFragment.kt @@ -200,7 +200,7 @@ abstract class BaseTaxiTabFragment> : MvpFragment(), if (MogoStatusManager.getInstance().isTaxiUnmanedDriverTakingOrders) { return } - module_mogo_och_operation_status.isEnabled = !isRoutingVerifyMode - val isBtnEnable = module_mogo_och_operation_status.isEnabled + module_mogo_och_operation_status.isChecked = !isRoutingVerifyMode + val isBtnEnable = module_mogo_och_operation_status.isChecked if (isBtnEnable) { module_mogo_och_operation_status.setCompoundDrawablesWithIntrinsicBounds( resources.getDrawable(R.drawable.shape_size_operation_out), diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt index 9f48d57ca1..f6f733248e 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingChooseLineViewModel.kt @@ -104,6 +104,12 @@ class TaxiRoutingChooseLineViewModel : BaseViewModel { DebugView.printInfoMsg("[开始任务] 准备开始任务") val grayLineBean = intent.routingTask.grayLineBean val contrailBean = intent.routingTask.contrailBean + val grayId = intent.routingTask.grayId if (grayLineBean == null || contrailBean == null) { ToastUtils.showShort("灰度线路或轨迹信息异常,请稍后再试") DebugView.printErrorMsg("[开始任务] 灰度线路或轨迹信息异常,请稍后再试") return } DebugView.printInfoMsg("[启自驾] 准备启动自驾") - TaxiRoutingModel.updateCurrentGrayLineAndContrail(grayLineBean, contrailBean) + TaxiRoutingModel.updateCurrentGrayLineAndContrail( + grayLineBean, + contrailBean, + grayId + ) TaxiRoutingModel.startAutoPilot(grayLineBean!!, contrailBean!!) + //添加到站监听 + TaxiRoutingModel.addAutoPilotStatusListener() + TaxiRoutingModel.addGDMapCurrentLocationListener() sendUiState { copy( routingUiState = RoutingUIState.ShowFinishTaskButton(intent.routingTask) @@ -133,10 +142,13 @@ class TaxiRoutingFragmentViewModel : BaseViewModel = ConcurrentHashMap() @@ -69,6 +79,131 @@ object TaxiRoutingModel { mOrderStatusCallback = callback } + fun addAutoPilotStatusListener() { + CallerAutoPilotStatusListenerManager.addListener(TAG, mMogoAutopilotStatusListener) + } + + fun removeAutoPilotStatusListener() { + CallerAutoPilotStatusListenerManager.removeListener(TAG) + } + + //MAP到站监听 + private val mMogoAutopilotStatusListener: IMoGoAutopilotStatusListener = + object : IMoGoAutopilotStatusListener { + override fun onAutopilotIpcConnectStatusChanged(status: Int, reason: String?) { + } + + override fun onAutopilotGuardian(guardianInfo: MogoReportMsg.MogoReportMessage?) { + } + + override fun onAutopilotStatusResponse(state: Int) { + } + + override fun onAutopilotArriveAtStation(arrivalNotification: MessagePad.ArrivalNotification?) { + CallerLogger.i( + TAG, + "onAutopilotArriveAtStation = ${arrivalNotification.toString()}" + ) + DebugView.printInfoMsg("[MAP到站通知] 上报到站,location=${arrivalNotification?.endLocation}") + + val endSiteLat: Double? = currentGrayLineBean?.endSite?.gcjLat + val endSiteLon: Double? = currentGrayLineBean?.endSite?.gcjLon + val mapEndSiteLatWgs: Double? = arrivalNotification?.endLocation?.latitude + val mapEndSiteLonWgs: Double? = arrivalNotification?.endLocation?.longitude + if (endSiteLon != null && endSiteLat != null && mapEndSiteLonWgs != null && mapEndSiteLatWgs != null) { + val latLngs = + CoordinateUtils.transformWgsToGcj(mapEndSiteLatWgs, mapEndSiteLonWgs) + val distance = CoordinateUtils.calculateLineDistance( + endSiteLon, endSiteLat, + latLngs[0], latLngs[1] + ).toDouble() + if (distance <= TaxiUnmannedConst.ARRIVE_AT_START_STATION_DISTANCE) {// 两坐标小于15米 + DebugView.printInfoMsg("[MAP到站通知] 到站坐标和任务终点15米内, 请求到站") + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onAutoPilotArriveAtEndStation(currentGrayId) + } + } else { + DebugView.printInfoMsg("[MAP到站通知] 到站坐标和任务终点不一致, 不请求到站") + } + } else { + DebugView.printErrorMsg( + "[MAP到站通知] 上报到站,数据异常,endSiteLat = $endSiteLat, endSiteLon = $endSiteLon, " + + "mapEndSiteLat = $mapEndSiteLatWgs, mapEndSiteLon = $mapEndSiteLonWgs" + ) + } + } + } + + // 自车定位监听 + private val mMapLocationListener: IMoGoChassisLocationGCJ02Listener = + object : IMoGoChassisLocationGCJ02Listener { + override fun onChassisLocationGCJ02(currentLocation: MogoLocation?) { + //位置变化时,通过围栏判断是否到达x点 + if (null == currentLocation) return + val endSite = currentGrayLineBean?.endSite ?: return + + val endLon = endSite.gcjLon + val endLat = endSite.gcjLat + + val distance = CoordinateUtils.calculateLineDistance( + endLon, + endLat, + currentLocation.longitude, + currentLocation.latitude + ).toDouble() + CallerLogger.i(TAG, "judgeEndStation() distance = $distance") + //1、当前位置和站点围栏15m内 + if (distance <= TaxiUnmannedConst.ARRIVE_AT_START_STATION_DISTANCE) { + //2、开始计算当前位置和站点的向量角度 < 90度 未经过 >90度 经过 + val stationAngle = DrivingDirectionUtils.getDegreeOfCar2Poi( + currentLocation.longitude, + currentLocation.latitude, + endLon, + endLat, + currentLocation.heading.toInt() + ).toDouble() + CallerLogger.i(TAG, "judgeEndStation() stationAngle = $stationAngle") + + //3、刚过站且过站距离在15m内, 提交到站 + if (stationAngle > 90) { + CallerLogger.i(TAG, "judgeEndStation() = 刚过站且在15m内") + DebugView.printInfoMsg( + "[自车定位围栏] 触发围栏, endSiteId=${currentGrayLineBean?.endSite?.siteId}, endSiteName=${currentGrayLineBean?.endSite?.siteName}, lineId=${currentGrayLineBean?.lineId},围栏范围:${TaxiUnmannedConst.ARRIVE_AT_START_STATION_DISTANCE}米 刚过站且在15m内" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onGDMapArriveAtEndStation(currentGrayId) + } + } else { + // 4、 没有过站距离小于15m 速度小于0.3(根据M1来的模数 可能要调) + if (currentLocation.gnssSpeed < 0.3) { + CallerLogger.i( + TAG, + "judgeEndStation() = 没有过站、速度基本为零且在15m内" + ) + DebugView.printInfoMsg( + "[自车定位围栏] 触发围栏, endSiteId=${currentGrayLineBean?.endSite?.siteId}, endSiteName=${currentGrayLineBean?.endSite?.siteName}, lineId=${currentGrayLineBean?.lineId},围栏范围:${TaxiUnmannedConst.ARRIVE_AT_START_STATION_DISTANCE}米 没有过站、速度基本为零且在15m内" + ) + mTaxiRoutingCallbackMap.forEach { + val listener = it.value + listener.onGDMapArriveAtEndStation(currentGrayId) + } + } + } + } + } + } + + fun addGDMapCurrentLocationListener() { + //定位监听, 传false是高德坐标系 10 -> 100ms一次 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, 10, mMapLocationListener) + } + + fun removeGDMapCurrentLocationListener() { + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + } + fun queryRoutingGrayLineList() { DebugView.printInfoMsg("[查询灰度路线] 准备发送请求,sn=${MoGoAiCloudClientConfig.getInstance().sn}") TaxiRoutingServiceManager.queryRoutingGrayLineList(mContext, @@ -302,14 +437,22 @@ object TaxiRoutingModel { }) } - fun updateCurrentGrayLineAndContrail(grayLineBean: GrayLineBean?, contrailBean: ContrailBean?) { + fun updateCurrentGrayLineAndContrail( + grayLineBean: GrayLineBean?, + contrailBean: ContrailBean?, + grayId: Long? + ) { currentGrayLineBean = grayLineBean currentContrailBean = contrailBean + currentGrayId = grayId } fun startAutoPilotByClick() { if (currentGrayLineBean == null || currentContrailBean == null) { - CallerLogger.e(TAG, "startAutoPilotByClick 异常,currentGrayLineBean == null || currentContrailBean == null") + CallerLogger.e( + TAG, + "startAutoPilotByClick 异常,currentGrayLineBean == null || currentContrailBean == null" + ) DebugView.printErrorMsg("[启自驾] startAutoPilotByClick 异常,currentGrayLineBean == null || currentContrailBean == null") return } @@ -398,6 +541,19 @@ object TaxiRoutingModel { return parameters } + /** + * 结束自动驾驶 + * */ + fun cancelAutopilot() { + try { + CallerAutoPilotControlManager.cancelAutoPilot() + DebugView.printInfoMsg("[取消自驾] 调用成功") + CallerLogger.d(TAG, "结束自动驾驶") + } catch (e: Exception) { + e.printStackTrace() + } + } + /** * 显示/隐藏 前往任务目的地的导航 * diff --git a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml index a5d1f74aec..e2572e7227 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml index 8c100f97eb..4382691e0a 100755 --- a/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/drawable/taxi_operation_status_bg_selector_new.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file From 508b7c90599d090d72eeda94d5042f3fe14f2bd6 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Thu, 30 Nov 2023 18:22:36 +0800 Subject: [PATCH 16/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=E5=85=B3?= =?UTF-8?q?=E9=97=ADSOPSettingView=E7=9A=84=E5=85=A5=E5=8F=A3=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=9C=A8=E7=99=BB=E5=87=BA=E6=97=B6=20?= =?UTF-8?q?=E5=85=B3=E9=97=AD=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/common/module/biz/provider/LoginServiceImpl.kt | 1 + .../mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt | 4 ++++ .../mogo/eagle/core/function/hmi/ui/setting/SopView.kt | 10 ++++++++-- .../eagle/core/function/hmi/ui/setting/ToolsView.kt | 4 ++++ .../core/function/api/hmi/warning/IMoGoHmiProvider.kt | 5 +++++ .../eagle/core/function/call/hmi/CallerHmiManager.kt | 7 +++++++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/provider/LoginServiceImpl.kt b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/provider/LoginServiceImpl.kt index f34d388d46..370bc3932b 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/provider/LoginServiceImpl.kt +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/biz/provider/LoginServiceImpl.kt @@ -60,6 +60,7 @@ class LoginServiceImpl : LoginService,ILoginViewCallback { if(uiModel) { fragment?.let { CallerHmiManager.hideToolsView() + CallerHmiManager.hideSOPSettingView() val parentFragmentManager = it.childFragmentManager val fragmentByTag: Fragment? = parentFragmentManager.findFragmentByTag(TAG) if (fragmentByTag is DialogFragment) { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt index 754956167e..f677890be3 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/MoGoHmiProvider.kt @@ -238,6 +238,10 @@ class MoGoHmiProvider : IMoGoHmiProvider { toolsView.dismiss() } + override fun hideSOPSettingView() { + toolsView.hideSOPSettingView() + } + @BizConfig(V2I, "", BIZ_RTS) override fun showVideoDialog(infList: List) { ThreadUtils.runOnUiThread { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/SopView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/SopView.kt index ceb84b519c..14be263c58 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/SopView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/SopView.kt @@ -6,11 +6,9 @@ import android.view.Gravity import android.view.View import android.view.WindowManager import android.view.animation.OvershootInterpolator -import com.mogo.eagle.core.data.config.FunctionBuildConfig import com.mogo.eagle.core.data.enums.SidePattern import com.mogo.eagle.core.function.hmi.notification.WarningFloat import com.mogo.eagle.core.function.hmi.notification.anim.DefaultAnimator -import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils import me.jessyan.autosize.utils.AutoSizeUtils class SopView private constructor(){ @@ -77,4 +75,12 @@ class SopView private constructor(){ } } } + + fun dismiss() { + if (mSOPSettingViewFloat != null) { + WarningFloat.dismiss(mSOPSettingViewFloat!!.config.floatTag, false) + mSOPSettingViewFloat = null + mSOPSettingView = null + } + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt index 8bbb921d72..cb26d3823b 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/ToolsView.kt @@ -123,4 +123,8 @@ class ToolsView private constructor() { dismissToolsFloatView() } + fun hideSOPSettingView() { + sopView?.dismiss() + } + } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt index 27014553eb..62b9dced0e 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/hmi/warning/IMoGoHmiProvider.kt @@ -66,6 +66,11 @@ interface IMoGoHmiProvider :IProvider{ */ fun hideToolsView() + /** + * 关闭运营面板 + */ + fun hideSOPSettingView() + /** * 展示绑定车辆弹框 */ diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt index c9cf543f3a..c72f51addc 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/hmi/CallerHmiManager.kt @@ -104,6 +104,13 @@ object CallerHmiManager { hmiProviderApi?.hideToolsView() } + /** + * 关闭运营面板 + */ + fun hideSOPSettingView() { + hmiProviderApi?.hideSOPSettingView() + } + /** * 展示绑定车辆弹框 */ From 60148ee30170224242f4eb8f17c3b100e07e904c Mon Sep 17 00:00:00 2001 From: aibingbing Date: Thu, 30 Nov 2023 18:23:04 +0800 Subject: [PATCH 17/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20refactor:=20=E8=B0=83=E6=95=B4=E7=81=B0?= =?UTF-8?q?=E5=BA=A6=E5=88=97=E8=A1=A8item=20UI=E6=A0=B7=E5=BC=8F;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/color/taxi_autopilot_text_color_selector.xml | 4 ++-- .../res/layout/routing_choose_line_list_item.xml | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml index e2572e7227..d327047eac 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/color/taxi_autopilot_text_color_selector.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml index d7b1c6849a..d87ee5006b 100644 --- a/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml +++ b/OCH/taxi/unmanned-driver/src/main/res/layout/routing_choose_line_list_item.xml @@ -3,11 +3,11 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="@dimen/dp_78" - android:paddingEnd="@dimen/dp_78" - android:layout_marginTop="@dimen/dp_8" + android:layout_marginTop="@dimen/dp_12" android:background="@drawable/routing_choose_line_shape_select_line_item_bg_normal" - android:orientation="vertical"> + android:orientation="vertical" + android:paddingStart="@dimen/dp_78" + android:paddingEnd="@dimen/dp_78"> + android:layout_marginBottom="@dimen/dp_20"> Date: Thu, 30 Nov 2023 19:26:27 +0800 Subject: [PATCH 18/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20=E7=BB=93=E6=9D=9F=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=97=B6=20taskId=E5=80=BC=E4=B8=8D=E5=AF=B9=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../taxi/ui/routing/TaxiRoutingFragment.kt | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 038ca5f52d..6b0d2bfccb 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -145,7 +145,7 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToStart.visibility = View.VISIBLE naviToEnd.visibility = View.INVISIBLE updateStartAndEndStationPointByStatus(false) - updateCurrentTaskTripInfo(0,0) + updateCurrentTaskTripInfo(0, 0) data.grayLineBean?.startSite?.also { initStartNaviToStationParam( @@ -184,7 +184,7 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToStart.visibility = View.INVISIBLE naviToEnd.visibility = View.VISIBLE updateStartAndEndStationPointByStatus(true) - updateCurrentTaskTripInfo(0,0) + updateCurrentTaskTripInfo(0, 0) routingTask.grayLineBean?.endSite?.also { initStartNaviToStationParam( @@ -209,43 +209,37 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { } private fun showFeedbackDialog(grayId: Long) { - if (mFeedbackDialog == null) { - val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() - builder.cancelStr( - MainMoGoApplication.getApp() - .getString(R.string.routing_feedback_result_btn_not_sure) - ).confirmStr( - MainMoGoApplication.getApp() - .getString(R.string.routing_feedback_result_btn_sure) - ).tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint)) - .clickListener(object : - TaxiRoutingFeedbackDialog.TaxiRoutingFeedBackDialogClickListener { - override fun confirm() { - mViewModel.sendUiIntent( - TaxiRoutingUiIntent.SubmitEndTask( - grayId, - EndGrayTaskFeedbackType.USABLE_YES - ) + val builder: TaxiRoutingFeedbackDialog.Builder = TaxiRoutingFeedbackDialog.Builder() + builder.cancelStr( + MainMoGoApplication.getApp() + .getString(R.string.routing_feedback_result_btn_not_sure) + ).confirmStr( + MainMoGoApplication.getApp() + .getString(R.string.routing_feedback_result_btn_sure) + ).tips(MainMoGoApplication.getApp().getString(R.string.routing_feedback_result_hint)) + .clickListener(object : + TaxiRoutingFeedbackDialog.TaxiRoutingFeedBackDialogClickListener { + override fun confirm() { + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.SubmitEndTask( + grayId, + EndGrayTaskFeedbackType.USABLE_YES ) - } + ) + } - override fun cancel() { - mViewModel.sendUiIntent( - TaxiRoutingUiIntent.SubmitEndTask( - grayId, - EndGrayTaskFeedbackType.USABLE_NO - ) + override fun cancel() { + mViewModel.sendUiIntent( + TaxiRoutingUiIntent.SubmitEndTask( + grayId, + EndGrayTaskFeedbackType.USABLE_NO ) - } - }) - activity?.also { - mFeedbackDialog = builder.build(it) - mFeedbackDialog?.showDialog() - } - } else { - activity?.also { - mFeedbackDialog?.showDialog() - } + ) + } + }) + activity?.also { + mFeedbackDialog = builder.build(it) + mFeedbackDialog?.showDialog() } } From 9a6af419528f546ca9ce61bd7ef3807ab89241cc Mon Sep 17 00:00:00 2001 From: aibingbing Date: Fri, 1 Dec 2023 17:24:13 +0800 Subject: [PATCH 19/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20debug=E5=8C=85=E4=B8=8D=E5=B1=95?= =?UTF-8?q?=E7=A4=BAmock=E6=8C=89=E9=92=AE=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt index 041b821113..25556b87a0 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/debug/DebugView.kt @@ -209,7 +209,7 @@ public class DebugView @JvmOverloads constructor( private fun initViewByTaskData(data: QueryCurrentTaskRespBean.Result?) { //release包下隐藏Mock按钮,避免司机误操作 - btnContainer.visibility = if (AppUtils.isAppDebug()) View.INVISIBLE else View.VISIBLE + btnContainer.visibility = if (AppUtils.isAppDebug()) View.VISIBLE else View.INVISIBLE val curContrail = TaxiTaskModel.getCurrentTaskTrajectory() currentDataTimestamps.text = "【当前数据返回时间】${currentDateTimeString()}" currentCarStatus.text = From 04e7e20c3729e2175f7353d33cf6310ff6d4150e Mon Sep 17 00:00:00 2001 From: aibingbing Date: Fri, 1 Dec 2023 21:45:52 +0800 Subject: [PATCH 20/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20fix:=20=E8=BF=9B=E8=A1=8C=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E5=88=87=E6=8D=A2=E5=90=8E=20=E6=97=A0=E4=BA=BA?= =?UTF-8?q?=E5=8C=96=E9=A1=B5=E9=9D=A2=20=E4=B8=8D=E8=83=BD=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E9=97=AE=E9=A2=98=EF=BC=8C=E5=8E=9F=E5=9B=A0=E4=B8=BA?= =?UTF-8?q?Model=EF=BC=8CViewModel=EF=BC=8CFragment=E7=9A=84=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E9=97=AE=E9=A2=98=EF=BC=8C=E5=BD=93Fragment=E9=87=8D?= =?UTF-8?q?=E5=BB=BA=E5=90=8E=E7=BB=91=E5=AE=9A=E4=BA=86=E6=96=B0ViewModel?= =?UTF-8?q?,=20=E5=90=8C=E6=97=B6Model=E6=98=AF=E5=8D=95=E4=BE=8B=EF=BC=8C?= =?UTF-8?q?=E4=BD=86=E6=98=AFModel=E7=BB=91=E5=AE=9A=E7=9A=84ViewModel?= =?UTF-8?q?=E8=BF=98=E6=98=AF=E4=B8=8A=E4=B8=80=E4=B8=AA=EF=BC=8C=E5=B0=B1?= =?UTF-8?q?=E4=BC=9A=E5=AF=BC=E8=87=B4=E6=95=B0=E6=8D=AE=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E5=88=B0ViewModel=E5=90=8E=E4=B8=8D=E8=83=BD=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E7=BB=99=E6=96=B0Fragment;=20refactor:=20Tas?= =?UTF-8?q?kWithOrder=20equals=20=E6=97=B6=E5=AD=97=E6=AE=B5=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=9B=20refactor:=20=E6=A8=A1=E5=BC=8F=E5=88=87?= =?UTF-8?q?=E6=8D=A2=20=E5=92=8C=20=E7=99=BB=E5=87=BA=20=E7=B1=BB=E4=BC=BC?= =?UTF-8?q?=EF=BC=8C=E6=9C=89=E4=BA=9B=E5=8F=98=E9=87=8F=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=90=8C=E7=AD=89=E9=87=8D=E7=BD=AE=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../taxi/bean/TaxiDriverTaskWithOrderBean.kt | 1 + .../taxi/ui/task/TaxiCurrentTaskFragment.kt | 22 ++++++------------- .../taxi/ui/task/TaxiCurrentTaskViewModel.kt | 6 +++++ .../mogo/och/taxi/ui/task/TaxiTaskModel.kt | 14 ++++++++---- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiDriverTaskWithOrderBean.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiDriverTaskWithOrderBean.kt index 019653c8b1..cb3277ee99 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiDriverTaskWithOrderBean.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/bean/TaxiDriverTaskWithOrderBean.kt @@ -100,6 +100,7 @@ data class QueryCurrentTaskRespBean(var data: Result?) : BaseData() { if (startSite != other.startSite) return false if (endSite != other.endSite) return false if (order != other.order) return false + if (writeVersion != other.writeVersion) return false return true } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskFragment.kt index 5db2755ac4..cb1e31f4b8 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskFragment.kt @@ -17,7 +17,6 @@ import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02Lis import com.mogo.eagle.core.function.main.MainMoGoApplication import com.mogo.eagle.core.network.utils.GsonUtil import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d -import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.e import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_TAXI import com.mogo.eagle.core.utilcode.util.ClickUtils @@ -68,7 +67,12 @@ import kotlinx.coroutines.flow.map class TaxiCurrentTaskFragment : BaseFragment(), View.OnClickListener, ICommonNaviChangedCallback { - private lateinit var mViewModel: TaxiCurrentTaskViewModel + private val mViewModel: TaxiCurrentTaskViewModel by lazy { + ViewModelProvider( + this, + ViewModelProvider.NewInstanceFactory() + )[TaxiCurrentTaskViewModel::class.java] + } private var mPrepareTasCountDownTimer: CountDownTimer? = null @@ -91,14 +95,6 @@ class TaxiCurrentTaskFragment : BaseFragment(), return this.javaClass.simpleName } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - mViewModel = ViewModelProvider( - this, - ViewModelProvider.NewInstanceFactory() - )[TaxiCurrentTaskViewModel::class.java] - } - override fun initViews() { initOnClickListener() initContainerView(false) @@ -311,11 +307,7 @@ class TaxiCurrentTaskFragment : BaseFragment(), } fun onCarTakeOrderStatusChanged() { - if (this::mViewModel.isInitialized) { - mViewModel.sendUiIntent(TaskUiIntent.StartOrEndTakeOrder) - } else { - e(TAG, "onCarTakeOrderStatusChanged: mViewModel is not Initialized") - } + mViewModel.sendUiIntent(TaskUiIntent.StartOrEndTakeOrder) } /** diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt index e08f21d5a1..7df5e66270 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiCurrentTaskViewModel.kt @@ -50,6 +50,12 @@ class TaxiCurrentTaskViewModel : BaseViewModel(), TaxiTaskModel.setCarServiceCallback(this) } + override fun onCleared() { + TaxiTaskModel.removeTaskWithOrderListener(TAG) + TaxiTaskModel.removeCarServiceCallback() + super.onCleared() + } + override fun initUiState(): UnmannedState { return UnmannedState(TaskWithOrderUIState.Init) } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt index 3b98559aed..9b3f681ffc 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/task/TaxiTaskModel.kt @@ -177,6 +177,10 @@ object TaxiTaskModel { mTaxiCarServiceCallback = callback } + fun removeCarServiceCallback() { + mTaxiCarServiceCallback = null + } + private fun getCurTaskStatus(): Int? { if (mCurrentTaskWithOrder == null) TaskStatusEnum.None return mCurrentTaskWithOrder?.currentStatus @@ -700,6 +704,8 @@ object TaxiTaskModel { mQueryTaskWithOrderDisposable?.dispose() mQueryTaskWithOrderDisposable = null } + mCurrentTaskWithOrder = null + mDriveToNearestStationTask = null } /** @@ -725,16 +731,16 @@ object TaxiTaskModel { return } val result: QueryCurrentTaskRespBean.Result? = data.data - d( - TAG, - "queryCurrentTaskOnce onSuccess:result=${GsonUtil.jsonFromObject(result)}" - ) d( TAG, "queryCurrentTaskOnce onSuccess:mCurrentTaskWithOrder=${ GsonUtil.jsonFromObject(mCurrentTaskWithOrder) }" ) + d( + TAG, + "queryCurrentTaskOnce onSuccess:result=${GsonUtil.jsonFromObject(result)}" + ) //本地根据订单 orderNo 去查询下(乘客取消订单) if (mCurrentTaskWithOrder != null From f53b6ed5539592af4f70ec94817265605a6bc054 Mon Sep 17 00:00:00 2001 From: aibingbing Date: Mon, 4 Dec 2023 17:00:29 +0800 Subject: [PATCH 21/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20feat:=20=E5=A2=9E=E5=8A=A0=20=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E6=97=B6=E8=B5=B7=E7=82=B9=E5=92=8C=E7=BB=88=E7=82=B9?= =?UTF-8?q?=20=E9=AB=98=E7=B2=BE=E5=9C=B0=E5=9B=BEMarker=20;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../och/taxi/constant/TaxiUnmannedConst.kt | 8 +++ .../taxi/ui/routing/TaxiRoutingFragment.kt | 62 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiUnmannedConst.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiUnmannedConst.kt index e759aef583..0e84fffa52 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiUnmannedConst.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/constant/TaxiUnmannedConst.kt @@ -42,6 +42,12 @@ class TaxiUnmannedConst { //终点UUID const val TAXI_END_MAP_MAKER = "taxi_end_map_maker" + //算路起点UUID + const val TAXI_ROUTING_VERIFY_START_SITE = "taxi_routing_verify_start_site" + + //算路终点UUID + const val TAXI_ROUTING_VERIFY_END_SITE = "taxi_routing_verify_end_site" + //演示:V 测试:内测 const val DEMO_USER = "V" const val TEST_USER = "内测" @@ -78,6 +84,8 @@ class TaxiUnmannedConst { */ const val TYPE_MARKER_TAXI_ORDER = "TYPE_MARKER_TAXI_ORDER" + const val TYPE_MARKER_ROUTING_VERIFY = "TYPE_MARKER_TAXI_ROUTING_VERIFY" + const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L const val TIMER_PREPARE_VIRTUAL_TASK_INTERVAL = 45 * 1000L //45s再次获取任务 diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index 6b0d2bfccb..e09caa978c 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -17,6 +17,8 @@ import com.mogo.och.common.module.utils.FlowBus import com.mogo.och.taxi.R import com.mogo.och.taxi.bean.EndGrayTaskFeedbackType import com.mogo.och.taxi.constant.TaxiDriverEventConst +import com.mogo.och.taxi.constant.TaxiUnmannedConst +import com.mogo.och.taxi.utils.MapMakerManager import com.mogo.och.taxi.utils.TaskUtils import kotlinx.android.synthetic.main.routing_fragment.btnChooseTask import kotlinx.android.synthetic.main.routing_fragment.btnFinishTask @@ -126,6 +128,8 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { btnChooseTask.visibility = View.VISIBLE btnStartTask.visibility = View.GONE finishSubmitIssueGroup.visibility = View.GONE + + removeAllMapMarker() } private fun showCurrentLineTaskContentView(data: RoutingUIState.RoutingTask) { @@ -156,10 +160,28 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToStart.setOnClickListener { showNaviToEndStationFragment(true) } + setOrRemoveMapMaker( + true, + TaxiUnmannedConst.TAXI_ROUTING_VERIFY_START_SITE, + it.wgs84Lat, + it.wgs84Lon, + R.raw.star_marker + ) + } + + data.grayLineBean?.endSite?.also { + setOrRemoveMapMaker( + false, + TaxiUnmannedConst.TAXI_ROUTING_VERIFY_END_SITE, + it.wgs84Lat, + it.wgs84Lon, + R.raw.end_marker + ) } startStationName.text = data.grayLineBean?.startSite?.siteName endStationName.text = data.grayLineBean?.endSite?.siteName + } private fun showFinishTaskView(routingTask: RoutingUIState.RoutingTask) { @@ -195,6 +217,23 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { naviToEnd.setOnClickListener { showNaviToEndStationFragment(true) } + setOrRemoveMapMaker( + true, + TaxiUnmannedConst.TAXI_ROUTING_VERIFY_END_SITE, + it.wgs84Lat, + it.wgs84Lon, + R.raw.end_marker + ) + } + + routingTask.grayLineBean?.startSite?.also { + setOrRemoveMapMaker( + false, + TaxiUnmannedConst.TAXI_ROUTING_VERIFY_START_SITE, + it.wgs84Lat, + it.wgs84Lon, + R.raw.star_marker + ) } } @@ -313,6 +352,29 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { } } + /** + * 绘制地图起点终点 + * @param isAdd + * @param uuid + */ + private fun setOrRemoveMapMaker( + isAdd: Boolean, + uuid: String, + lat: Double, + lon: Double, + resourceId: Int + ) { + if (isAdd) { + MapMakerManager.addMapMaker(TaxiUnmannedConst.TYPE_MARKER_ROUTING_VERIFY, uuid, lat, lon, resourceId) + } else { + MapMakerManager.removeMapMaker(uuid, lat, lon) + } + } + + private fun removeAllMapMarker() { + MapMakerManager.removeAllMapMarkerByOwner(TaxiUnmannedConst.TYPE_MARKER_ROUTING_VERIFY) + } + override fun onDestroyView() { AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() super.onDestroyView() From 9b4b7e99b6ef913e6a5c54b5ef8598674b32abbe Mon Sep 17 00:00:00 2001 From: aibingbing Date: Mon, 4 Dec 2023 20:15:35 +0800 Subject: [PATCH 22/22] =?UTF-8?q?[=E8=87=AA=E4=B8=BB=E7=AE=97=E8=B7=AF?= =?UTF-8?q?=E9=AA=8C=E8=AF=81]=20refactor:=20=E7=AE=97=E8=B7=AF=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E6=A8=A1=E5=BC=8F=20=E9=AB=98=E5=BE=B7=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E8=B7=9D=E7=A6=BB=EF=BC=8C=E6=97=B6=E9=97=B4=E4=B8=8D?= =?UTF-8?q?=E5=87=86=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/map/AmapNaviToDestinationModel.java | 3 ++- .../och/taxi/ui/routing/TaxiRoutingFragment.kt | 8 +++++--- .../ui/routing/TaxiRoutingFragmentViewModel.kt | 3 +++ .../com/mogo/och/taxi/ui/task/TaxiTaskModel.kt | 15 ++++++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/map/AmapNaviToDestinationModel.java b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/map/AmapNaviToDestinationModel.java index d49a3f7a34..a5bea903ec 100644 --- a/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/map/AmapNaviToDestinationModel.java +++ b/OCH/mogo-och-common-module/src/main/java/com/mogo/och/common/module/map/AmapNaviToDestinationModel.java @@ -78,7 +78,7 @@ public class AmapNaviToDestinationModel implements AMapNaviListener { public void setVoiceIsMute(boolean isPlay) { ThreadUtils.getSinglePool().execute(() -> { if (mAMapNavi == null) return; - CallerLogger.i(TAG, "setVoiceIsMute()--"+isPlay); + CallerLogger.i(TAG, "setVoiceIsMute()--" + isPlay); this.isPlay = isPlay; if (isPlay) { mAMapNavi.startSpeak(); @@ -108,6 +108,7 @@ public class AmapNaviToDestinationModel implements AMapNaviListener { } public void setTaxiNaviChangedCallback(ICommonNaviChangedCallback callback) { + CallerLogger.i(TAG, "setTaxiNaviChangedCallback()"); this.mNaviChangedCallback = callback; } diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt index e09caa978c..9b910b80b8 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragment.kt @@ -10,6 +10,7 @@ import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02Lis import com.mogo.eagle.core.function.main.MainMoGoApplication import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.ThreadUtils import com.mogo.eagle.core.utilcode.util.UiThreadHandler import com.mogo.och.common.module.map.AmapNaviToDestinationModel import com.mogo.och.common.module.map.ICommonNaviChangedCallback @@ -97,7 +98,6 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { when (routingUiState) { is RoutingUIState.Init -> { showChooseTaskView() - AmapNaviToDestinationModel.getInstance(context).destroyAmaNavi() } is RoutingUIState.RoutingTask -> { @@ -181,7 +181,6 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { startStationName.text = data.grayLineBean?.startSite?.siteName endStationName.text = data.grayLineBean?.endSite?.siteName - } private fun showFinishTaskView(routingTask: RoutingUIState.RoutingTask) { @@ -315,7 +314,10 @@ class TaxiRoutingFragment : BaseFragment(), ICommonNaviChangedCallback { val endNaviLatLng = NaviLatLng(stationLat, stationLng) AmapNaviToDestinationModel.getInstance(context).initAMapNavi(startNaviLatLng, endNaviLatLng) AmapNaviToDestinationModel.getInstance(context).setVoiceIsMute(isVoicePlay) - AmapNaviToDestinationModel.getInstance(context).setTaxiNaviChangedCallback(this) + // 怀疑在线程池执行的destroyAmaNavi会比 主线程执行的setTaxiNaviChangedCallback慢,导致setTaxiNaviChangedCallback(this)会被冲掉 + ThreadUtils.getSinglePool().execute { + AmapNaviToDestinationModel.getInstance(context).setTaxiNaviChangedCallback(this) + } } override fun onCurrentNaviDistAndTimeChanged(meters: Int, timeInSecond: Long) { diff --git a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt index 7a105e7096..2d6e900f96 100644 --- a/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt +++ b/OCH/taxi/unmanned-driver/src/main/java/com/mogo/och/taxi/ui/routing/TaxiRoutingFragmentViewModel.kt @@ -7,6 +7,7 @@ import com.mogo.commons.module.status.MogoStatusManager import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.common.module.map.AmapNaviToDestinationModel import com.mogo.och.taxi.base.BaseViewModel import com.mogo.och.taxi.base.IUiIntent import com.mogo.och.taxi.bean.GrayLineBean @@ -149,6 +150,8 @@ class TaxiRoutingFragmentViewModel : BaseViewModel