Merge branch 'dev_robotaxi-d_250804_8.2.0' of gitlab.zhidaoauto.com:SCA/L4HA/AndroidApp/MoGoEagleEye into dev_robotaxi-d_250804_8.2.0

This commit is contained in:
xinfengkun
2025-08-13 16:19:30 +08:00
10 changed files with 330 additions and 38 deletions

View File

@@ -141,6 +141,7 @@ class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback, InputTextC
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_default)
switch_routing_rv.smoothScrollToPosition(0)
acctv_search_byid.isChecked = false
acctv_search_byid.text=""
acctv_search_byid.setBackgroundResource(R.drawable.biz_input_order_id_normal)
aciv_input_icon.setImageResource(R.drawable.biz_routing_search_right_normal)
InputManager.setKeyboardVisable(View.GONE)
@@ -184,6 +185,7 @@ class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback, InputTextC
switch_routing_rv.smoothScrollToPosition(0)
}
actv_order_by_num_desc.onClick {
// 按照总验证次序降序排列,而不是今日验证次序
mRoutingLineList.sortByDescending {
(it.lineSuccessCount?:0)+(it.lineFailCount?:0)
}
@@ -282,6 +284,7 @@ class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback, InputTextC
}
override fun onQueryRoutingGrayLineListSuccess(data: MutableList<GrayLineBean>) {
// 数据默认按照距离排序过了
onRoutingGrayLineListChanged(data)
if (AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)
||AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)
@@ -293,6 +296,8 @@ class RoutingSelectView: ConstraintLayout, SwtichRoutingViewCallback, InputTextC
}
}
}
actv_current_order.text = ResourcesUtils.getString(R.string.biz_routing_order_default)
acctv_search_byid.text=""
cancleAni()
}

View File

@@ -138,8 +138,10 @@ class TaskRunningView : ConstraintLayout, TaskRunningModel.SwtichLineViewCallbac
}
private fun showFeedbackDialog(grayId: Long) {
CallerLogger.d(TAG, "showFeedbackDialog!")
val occurrenceTime = System.currentTimeMillis()
if(closeRouting==null) {
CallerLogger.d(TAG, "closeRouting is null!")
closeRouting = CommonDialogStatus
.Builder()
.title("路线验证结束")
@@ -152,6 +154,7 @@ class TaskRunningView : ConstraintLayout, TaskRunningModel.SwtichLineViewCallbac
.build(context)
}else{
if(closeRouting?.isShowing==true){
CallerLogger.d(TAG, "closeRouting is showing, return!")
return
}
}
@@ -170,6 +173,7 @@ class TaskRunningView : ConstraintLayout, TaskRunningModel.SwtichLineViewCallbac
)
}
})
CallerLogger.d(TAG, "closeRouting show!")
closeRouting?.show()
}

View File

@@ -25,10 +25,14 @@ import com.mogo.och.data.taxi.TaxiOrderStatusEnum
import com.mogo.och.unmanned.passenger.bean.ai.LatLonBody
import com.mogo.och.unmanned.passenger.network.ai.AiServiceManager
import com.mogo.och.unmanned.passenger.ui.aiview.bean.MGCommonTitleBean
import com.mogo.och.unmanned.passenger.ui.aiview.bean.MGDefaultQABean
import com.mogo.och.unmanned.passenger.ui.aiview.bean.MGEagleEyeBean
import com.mogo.och.unmanned.passenger.ui.aiview.bean.MGSpotPKBean
import com.mogo.och.unmanned.taxi.utils.order.OrderListener
import com.mogo.och.unmanned.taxi.utils.order.OrderModel
import com.mogo.service.v2n.bean.MGEventExtInfoBean
import com.mogo.service.v2n.bean.MGLlmQueryBean
import com.mogo.service.v2n.bean.MGLlmQueryRespBean
import com.mogo.service.v2n.utils.JsonUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -122,9 +126,14 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
llmResultJob = viewModelScope.launch(Dispatchers.IO) {
V2XRepository.llmResultFlow.collect { result ->
if (result.queryId.startsWith("AUTO")) {
return@collect
}
if (result.aiMsg.eventType != "workflow_finished") {
return@collect
}
Log.d(TAG, "llm result: $result")
val title = result.aiMsg?.title ?: ""
val suggestion = result.aiMsg?.suggestion ?: result.answer ?: ""
val msg = msgList.findLast { it.id == result.queryId }
@@ -133,37 +142,100 @@ class AIViewModel : ViewModel(), AIMessageManager.AIMessageListener, IWakeUpList
return@collect
}
if (result.aiMsg?.data != null) {
val data: MGCommonTitleBean? = result.aiMsg?.parseData()
val content = data?.title ?: ""
AIMessage.QA(
id = result.queryId,
title = title,
tts = content,
answer = content,
question = "",
pictureUrl = result.imgUrls.getOrNull(0) ?: "",
pictureUrlList = result.imgUrls,
)
}else{
AIMessageManager.post(
AIMessage.QA(
id = result.queryId,
title = result.answer,
tts = result.answer,
answer = suggestion,
question = msg.question,
state = AIMessage.QA.QuestionState.FINISH,
pictureUrl = result.imgUrls.getOrNull(0) ?: "",
pictureUrlList = result.imgUrls
)
)
}
postAIEvent(result, question = msg.question)
}
}
}
fun postAIEvent(
result: MGLlmQueryRespBean,
question: String = "",
isAuto: Boolean = false, isShowAll: Boolean = true
) {
val title = result.aiMsg?.title ?: ""
val msgType = result.aiMsg?.type ?: 0
val fromValue = AIMessageReplyType.fromValue(msgType)
val state = result.aiMsg.getMessageState()
val stateDes = result.aiMsg?.nodeStatus ?: ""
val flowType = result.aiMsg?.flowType ?: 0
when (fromValue) {
//千里眼
AIMessageReplyType.EagleEye -> {
val data: MGEagleEyeBean? = result.aiMsg?.parseData()
val content = data?.title ?: ""
AIMessage.QA(
id = result.queryId,
title = title,
tts = "$title$content",
answer = content,
question = question,
state = state,
pictureUrl = data?.liveInfo?.imgUrl?:"",
)
}
//景点PK
AIMessageReplyType.SpotPK -> {
val data: MGSpotPKBean? = result.aiMsg?.parseData()
val content = data?.title ?: ""
AIMessage.QA(
id = result.queryId,
title = title,
tts = "$title$content",
answer = content,
question = question,
state = state,
)
}
// 默认QA
else -> {
if (result.aiMsg?.responseMode == MGEventExtInfoBean.RESPONSE_MODE_STREAM) {
val data: MGDefaultQABean? = result.aiMsg?.parseData()
val titleName = data?.title ?: ""
val suggestion = data?.suggestion ?: result.answer ?: ""
var imagesUrl = data?.getImagesUrl()?: mutableListOf()
if (result.imgUrls.isNotEmpty()) {
imagesUrl = result.imgUrls
}
AIMessage.QA(
id = result.queryId,
title = titleName,
tts = titleName,
answer = suggestion,
question = question,
state = state,
pictureUrl = imagesUrl.getOrNull(0) ?: "",
pictureUrlList = imagesUrl
)
} else {
val suggestion = result.aiMsg?.suggestion ?: result.answer ?: ""
val new = MGDefaultQABean().apply {
this.title = result.aiMsg?.title ?: ""
this.suggestion = suggestion
this.status = result.aiMsg.status
this.description = result.aiMsg.description
this.images = result.aiMsg.images
}
AIMessage.QA(
id = result.queryId,
title = new.title,
tts = "$title$suggestion",
answer = suggestion,
question = question,
state = state,
pictureUrl = result.imgUrls.getOrNull(0) ?: "",
pictureUrlList = result.imgUrls,
)
}
}
}.let {
AIMessageManager.post(it)
}
}
override fun onCleared() {
AIMessageManager.unregisterListener(this)
@@ -412,6 +484,40 @@ inline fun <reified T> MGEventExtInfoBean.parseData(): T? {
}
}
enum class AIMessageReplyType(val code: Int) {
Default(0),
RoutePlan(20),
Guardian(21),
SpotPK(22),
EagleEye(23),
Cross(25);
companion object {
fun fromValue(value: Int): AIMessageReplyType? {
return values().find { it.code == value }
}
}
}
fun MGEventExtInfoBean?.getMessageState(): AIMessage.QA.QuestionState {
if (this == null) {
return AIMessage.QA.QuestionState.FINISH
}
if (this.eventType.isNullOrEmpty()) {
return AIMessage.QA.QuestionState.FINISH
}
// if (this.eventType == "workflow_started") {
// return AIMessage.QuestionState.PROCESSING
// }
if (this.eventType == "workflow_finished") {
return AIMessage.QA.QuestionState.FINISH
}
return AIMessage.QA.QuestionState.FINISH
}

View File

@@ -32,6 +32,7 @@ import com.mogo.eagle.core.utilcode.kotlin.onClick
import com.mogo.eagle.core.utilcode.mogo.glide.GlideImageLoader
import com.mogo.eagle.core.utilcode.mogo.glide.transform.GlideRoundedCornersTransform
import com.mogo.eagle.core.utilcode.mogo.imageloader.MogoImageView
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.DateTimeUtils
import com.mogo.och.common.module.utils.FrameAnimatorContainer
import com.mogo.och.common.module.biz.media.VoiceNotice
@@ -117,7 +118,7 @@ class QAViewHolder(val binding: View) : MessageViewHolder(binding) {
private var clContain: ConstraintLayout = binding.findViewById(R.id.clContain)
private var tvTimestamp: TextView = binding.findViewById(R.id.tvTimestamp)
private var tvStateContent: TextView = binding.findViewById(R.id.tvStateContent)
private var tvPncActionDesc: TextView = binding.findViewById(R.id.tvPncActionDesc)
private var tvAnswer: TextView = binding.findViewById(R.id.tvPncActionDesc)
// private var ivPicture: OchRoundImageView = binding.findViewById(R.id.ivPicture)
private var llState: LinearLayout = binding.findViewById(R.id.llState)
private var picBanner = binding.findViewById<Banner<String,BannerImageAdapter>>(R.id.picBanner)
@@ -125,22 +126,31 @@ class QAViewHolder(val binding: View) : MessageViewHolder(binding) {
override fun bind(item: AIMessage, onItemClickListener: OnItemClickListener?) {
if (item is AIMessage.QA) {
CallerLogger.d(TAG,"bind:${item}")
binding.apply {
handleState(item.state)
tvQuestion.text = item.question
Log.d(TAG, "bind: ${item}")
if(item.title==item.answer){
tvTitle.text = item.title
tvPncActionDesc.text = item.answer
tvAnswer.text = item.answer
tvTitle.visibility = View.VISIBLE
tvPncActionDesc.visibility = View.GONE
tvAnswer.visibility = View.GONE
tvTitleImage.visibility = View.VISIBLE
}else{
tvTitle.text = item.title
tvPncActionDesc.text = item.answer
tvTitle.visibility = View.VISIBLE
tvPncActionDesc.visibility = View.VISIBLE
tvTitleImage.visibility = View.VISIBLE
if(item.title.isNullOrEmpty()){
tvTitle.text = item.answer
tvAnswer.text = item.answer
tvTitle.visibility = View.GONE
tvAnswer.visibility = View.VISIBLE
tvTitleImage.visibility = View.GONE
}else {
tvTitle.text = item.title
tvAnswer.text = item.answer
tvTitle.visibility = View.VISIBLE
tvAnswer.visibility = View.VISIBLE
tvTitleImage.visibility = View.VISIBLE
}
}
handleTimestamp(item, tvTimestamp)

View File

@@ -0,0 +1,59 @@
package com.mogo.och.unmanned.passenger.ui.aiview.bean
data class AICrossBean(
val cameraLiveUrl: String?,
val cameraPicUrl: String?,
val currentLaneFlow: RoadFlowInfo?,
val flowStatistics: FlowStatistics?,
val title: String,
var otherQuestion: List<String>? = null,
)
data class RoadFlowInfo(
val totalPcuCount: Double,
val avgSpeed: Double,
val level: Int,
val infos: List<LaneInfo>
)
data class LaneInfo(
// val crossId: String,
val roadId: String,
val laneNo: String,
// val vehicleCount: Int,
// val avgSpeed: Double,
val pcuCount: Double,
val bearing: Int,
val arrowType: Int
)
data class FlowStatistics(
val v2nInfoList: List<V2nEventInfo>?,
val flowTimeInfo: FlowInfo?,
)
data class FlowInfo(
val defaultCount: Int,
val totalPcuCount: Double?,
val flowTimeInfoList: List<FlowTimeInfo>
)
data class FlowTimeInfo(
val flowTime: Long,
val flowTimeStr: String,
val count: Int,
val avgSpeed: Double,
val pcuCount: Double,
val level: String,
val flag: String
)
data class V2nEventInfo(
val id: Int,
//10006 道路施工; 10007 道路拥堵
val poiType: String,
val updateTimeLong: Long,
val createTimeLong: Long,
)

View File

@@ -0,0 +1,26 @@
package com.mogo.och.unmanned.passenger.ui.aiview.bean
import com.mogo.service.v2n.bean.MGEventExtInfoBean
class MGDefaultQABean
/**
* 默认构造函数
* 初始化基本字段为默认值
*/
{
fun getImagesUrl(): MutableList<String> {
val rusult = mutableListOf<String>()
images?.forEach {
rusult.add(it.url)
}
return rusult
}
// Getters and setters
var title: String = "" // 事件标题
var status: Int = 0 // 事件状态 1 显示 0 不显示
var suggestion: String = "" // 建议操作
var description: List<MGEventExtInfoBean.Description>? = null // 事件描述列表
var images: List<MGEventExtInfoBean.ImageInfo>? = null // 事件相关图片信息
var congestion: List<MGEventExtInfoBean.Congestion>? = null
}

View File

@@ -0,0 +1,53 @@
package com.mogo.och.unmanned.passenger.ui.aiview.bean
data class MGEagleEyeBean(
val title: String = "",
val liveInfo: LiveInfo? = null,
val parkingLots: List<ParkingLot>? = null,
val trafficInfo: TrafficInfo? = null,
val touristDensity: String? = null,
var personCount:Int = 0,
val weatherInfo: WeatherInfo? = null,
val noise: String? = null,
var otherQuestion: List<String>? = null,
) {
data class LiveInfo(
val imgUrl: String = "",
val liveUrl: String = ""
)
data class ParkingLot(
val name: String = "",
val address: String = "",
val businessHours: String = "",
val fee: String = "",
val total: String = "",
val free: String = "",
val freeRate: String = "",
val lat: Double = 0.0,
val lng: Double = 0.0,
val imgUrl: String = "",
val liveUrl: String = ""
)
// driveDuration":165.48,"driveDistance":154.58,"busDistance":14.45,"busDuration":48.48,"level":2
data class TrafficInfo(
val driveDistance: String = "",
val busDistance: String = "",
val driveDuration: String = "",
val busDuration: String = "",
val level: Int = 0,
val lon: Double = 0.0,
val lat: Double = 0.0,
val address:String = "",
val status: String = ""
)
data class WeatherInfo(
val temperature: String = "",
val windDirection: String = "",
val windPower: String = "",
val weather: String = "",
val sunlightIntensity: String = "",
val dressingAdv: String? = null,
)
}

View File

@@ -0,0 +1,27 @@
package com.mogo.och.unmanned.passenger.ui.aiview.bean
data class MGSpotPKBean(
val title: String = "",
val spots: List<Spot> = emptyList(),
var otherQuestion: List<String>? = null,
) {
data class Spot(
val name: String = "",
val isRecommend: Int = 0,
val roadStatus: String = "",
val distance: String = "",
val weather: String = "",
val crowded: String = "",
val feature: String = "",
val fee: String = "",
val lat: Double = 0.0,
val lng: Double = 0.0,
val imgUrl: String = "",
val liveUrl: String = "",
val parkingAddress:String? = null,
var parkingName:String? = null,
val parkingType:String? = null,
val parkingLon: Double? = null,
val parkingLat: Double? = null,
val parkingUrl: String? = null
)
}

View File

@@ -74,7 +74,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/clContain"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvTitleImage"
@@ -100,6 +100,7 @@
android:visibility="gone"
tools:visibility="visible"
android:textStyle="bold"
android:singleLine="true"
style="@style/AIMsgTextTitle"
tools:text="前方道路施工" />
@@ -109,6 +110,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tvTitleImage"
app:layout_constraintLeft_toLeftOf="@id/tvTitle"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone"
tools:visibility="visible"

View File

@@ -90,7 +90,7 @@ dependencies {
api rootProject.ext.dependencies.mogochainbase
api rootProject.ext.dependencies.mogoservicebiz
api ('com.mogo.service:mogo-v2x-enhanced:1.3.37'){
api ('com.mogo.service:mogo-v2x-enhanced:1.3.45'){
exclude group: 'com.google.protobuf', module: 'protoc'
exclude group: 'com.google.protobuf', module: 'protobuf-java'
exclude group: 'com.google.protobuf', module: 'protobuf-java-util'