diff --git a/app/src/main/java/com/nova/brain/glass/helper/AsrHelper.kt b/app/src/main/java/com/nova/brain/glass/helper/AsrHelper.kt index 6da1422..dc303ae 100644 --- a/app/src/main/java/com/nova/brain/glass/helper/AsrHelper.kt +++ b/app/src/main/java/com/nova/brain/glass/helper/AsrHelper.kt @@ -1,10 +1,15 @@ package com.nova.brain.glass.helper +import android.R.attr.action import android.app.AlertDialog +import android.graphics.Color +import android.graphics.drawable.GradientDrawable import android.os.Handler import android.os.Looper import android.util.Log +import android.view.LayoutInflater import com.nova.brain.glass.BuildConfig +import com.nova.brain.glass.R import com.nova.brain.glass.model.RecognizeAction import com.rokid.online.speech.AsrClient import com.rokid.online.speech.OnlineSpeechSdk @@ -57,6 +62,9 @@ object AsrHelper : OfflineCmdListener { /** goToDecisionCenter 命中时的回调,由各 Activity 在 onResume/onPause 中注册/清空 */ var onGoToDecisionCenter: ((action: RecognizeAction) -> Unit)? = null + /** scene == "decision" 时直接用 ASR 文本发起对话,由 ChatActivity 注册 */ + var onDirectChat: ((text: String) -> Unit)? = null + fun init() { val cfg = OnlineSpeechSdkConfig( domain = DOMAIN, @@ -121,11 +129,28 @@ object AsrHelper : OfflineCmdListener { val activity = runCatching { AppManager.getInstance().getActivity() }.getOrNull() ?: return@post if (activity.isFinishing || activity.isDestroyed) return@post + + val contentView = LayoutInflater.from(activity) + .inflate(R.layout.dialog_listening, null) + + // 黑底 + 绿色圆角线框 + val density = activity.resources.displayMetrics.density + contentView.background = GradientDrawable().apply { + shape = GradientDrawable.RECTANGLE + cornerRadius = 12f * density + setColor(Color.BLACK) + setStroke((2f * density).toInt(), Color.parseColor("#FF40FF5E")) + } + listeningDialog = AlertDialog.Builder(activity) - .setMessage("飞宝在呢,您请说") + .setView(contentView) .setCancelable(false) .create() - .also { it.show() } + .also { dialog -> + dialog.show() + // 让 Dialog 窗口本身透明,只显示自定义 view 的背景 + dialog.window?.setBackgroundDrawableResource(android.R.color.transparent) + } } } @@ -162,17 +187,21 @@ object AsrHelper : OfflineCmdListener { asr?.stopAsrWithMic() Log.d(TAG, "ASR final result: $text") dismissListeningDialog() - IntentRecognizeHelper.recognize( - text = text, - scence = scene, - onSuccess = { action -> - if (action.name == "goToDecisionCenter") { - onGoToDecisionCenter?.invoke(action) - } else { - "需要跳转任务列表".showMessage() + if (scene == "decision") { + onDirectChat?.invoke(text) + } else { + IntentRecognizeHelper.recognize( + text = text, + scence = scene, + onSuccess = { action -> + if (action.name == "goToDecisionCenter") { + onGoToDecisionCenter?.invoke(action) + } else { + "需要跳转任务列表".showMessage() + } } - } - ) + ) + } } override fun onFinished(taskId: String) { diff --git a/app/src/main/java/com/nova/brain/glass/model/data/TopicData.kt b/app/src/main/java/com/nova/brain/glass/model/data/TopicData.kt new file mode 100644 index 0000000..84037fd --- /dev/null +++ b/app/src/main/java/com/nova/brain/glass/model/data/TopicData.kt @@ -0,0 +1,16 @@ +package com.nova.brain.glass.model.data + +//{"question":"我的任务哪个更紧急","topicId":14478,"knowledgeBaseId":"AI_ASSISTANT_MODE_FOR_GLASSES","model":"AI助手模式"} +data class TopicData( + val topicName: String, + val knowledgeBaseId: String = "AI_ASSISTANT_MODE_FOR_GLASSES", +) +// "date":"2026-04-16T15:48:13.550Z", +//"msg":"success", +//"code":0, +//"data": 31013, +//"status":200 +data class TopicModel( + val code: Int, + val data: Int +) diff --git a/app/src/main/java/com/nova/brain/glass/repository/Service.kt b/app/src/main/java/com/nova/brain/glass/repository/Service.kt index f87726b..985bea1 100644 --- a/app/src/main/java/com/nova/brain/glass/repository/Service.kt +++ b/app/src/main/java/com/nova/brain/glass/repository/Service.kt @@ -3,6 +3,8 @@ package com.nova.brain.glass.repository import com.nova.brain.glass.model.RecognizeModel import com.nova.brain.glass.model.data.ChatData import com.nova.brain.glass.model.data.RecognizeData +import com.nova.brain.glass.model.data.TopicData +import com.nova.brain.glass.model.data.TopicModel import io.reactivex.Observable import okhttp3.RequestBody import okhttp3.ResponseBody @@ -26,4 +28,7 @@ interface Service { @POST("/cbrain-gateway/cbraindep/docqa/chat/qa03") fun chat(@Body body: ChatData): Observable + @POST("/cbrain-gateway/cbraindep/docqa/tbtopic/save") + fun tbtopic(@Body body: TopicData): Observable + } \ No newline at end of file diff --git a/app/src/main/java/com/nova/brain/glass/ui/ChatActivity.kt b/app/src/main/java/com/nova/brain/glass/ui/ChatActivity.kt index fc65524..dbaf4f4 100644 --- a/app/src/main/java/com/nova/brain/glass/ui/ChatActivity.kt +++ b/app/src/main/java/com/nova/brain/glass/ui/ChatActivity.kt @@ -51,7 +51,7 @@ class ChatActivity : BaseListFormLayoutNormalActivity - viewModel.demoPostSse(action.params.question) + viewModel.prepareTopic(action.params.question) + } + AsrHelper.onDirectChat = { text -> + viewModel.prepareTopic(text) } } @@ -114,6 +117,7 @@ class ChatActivity : BaseListFormLayoutNormalActivity() { private lateinit var vm: WelcomeVM // 点动画 - private val tvOriginalText = "您可以说:Nova,我的任务有哪些?" + private val tvOriginalText = "您可以说:飞宝飞宝,我的任务有哪些?" private val dotsHandler = Handler(Looper.getMainLooper()) private var dotCount = 0 private val dotsRunnable = object : Runnable { diff --git a/app/src/main/java/com/nova/brain/glass/viewmodel/ChatVM.kt b/app/src/main/java/com/nova/brain/glass/viewmodel/ChatVM.kt index f6a3945..8d4db3a 100644 --- a/app/src/main/java/com/nova/brain/glass/viewmodel/ChatVM.kt +++ b/app/src/main/java/com/nova/brain/glass/viewmodel/ChatVM.kt @@ -8,12 +8,14 @@ import com.nova.brain.glass.model.ChatModel import com.nova.brain.glass.model.ChatModel1 import com.nova.brain.glass.model.ChatModel2 import com.nova.brain.glass.model.data.ChatData +import com.nova.brain.glass.model.data.TopicData import com.nova.brain.glass.repository.Service import com.xuqm.base.common.GsonImplHelp import com.xuqm.base.common.LogHelper import com.xuqm.base.di.manager.HttpManager import com.xuqm.base.viewmodel.BaseListViewModel import com.xuqm.base.viewmodel.callback.Response +import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers import org.json.JSONObject @@ -24,6 +26,7 @@ class ChatVM : BaseListViewModel() { companion object { const val SPACER_ID = -1 + private const val DEFAULT_TOPIC_ID = 14478 } val result = MutableLiveData() @@ -74,7 +77,24 @@ class ChatVM : BaseListViewModel() { } } - fun demoPostSse(question: String) { + /** + * 先请求 tbtopic 接口拿 topicId,成功则使用返回值,失败/code≠0 则用默认值,再发起 SSE。 + * 进入 Chat 界面时用此方法替代直接调 demoPostSse。 + */ + fun prepareTopic(question: String) { + HttpManager.getApi(Service::class.java) + .tbtopic(TopicData(topicName = question)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ model -> + val topicId = if (model.code == 0) model.data else DEFAULT_TOPIC_ID + demoPostSse(question, topicId) + }, { _ -> + demoPostSse(question, DEFAULT_TOPIC_ID) + }).also { add(it) } + } + + fun demoPostSse(question: String, topicId: Int = DEFAULT_TOPIC_ID) { currentTask?.dispose() currentTask = null stopThinkingAnimation() @@ -86,7 +106,7 @@ class ChatVM : BaseListViewModel() { result.postValue(UUID.randomUUID().toString()) loading.postValue(true) - currentTask = HttpManager.getApi(Service::class.java).chat(ChatData(question)) + currentTask = HttpManager.getApi(Service::class.java).chat(ChatData(question, topicId)) .subscribeOn(Schedulers.io()) .subscribe({ body -> var content = "" diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml index d8fa1a4..6f2ca38 100644 --- a/app/src/main/res/layout/activity_welcome.xml +++ b/app/src/main/res/layout/activity_welcome.xml @@ -11,7 +11,7 @@ android:layout_height="wrap_content" android:textColor="#ff3FFF5F" android:textSize="19sp" - android:text="您可以说:Nova,我的任务有哪些?" + android:text="您可以说:飞宝飞宝,我的任务有哪些?" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_marginBottom="100dp" diff --git a/app/src/main/res/layout/dialog_listening.xml b/app/src/main/res/layout/dialog_listening.xml new file mode 100644 index 0000000..397edc5 --- /dev/null +++ b/app/src/main/res/layout/dialog_listening.xml @@ -0,0 +1,11 @@ + +