feat(task): 添加任务中心语音识别功能

- 新增 goToTaskCenter 回调函数用于处理任务中心跳转
- 修改 ASR 处理逻辑支持 goToTaskCenter 和 goToDecisionCenter 两种操作
- 扩展 RecognizeParams 数据类添加任务相关参数字段
- 更新 TaskItem 数据模型增加任务类型、参数和状态信息
- 修改 Service 接口返回 TaskSearchResponse 类型
- 在 ChatActivity 中处理语音识别结果并调用相应功能
- 实现 TaskListActivity 的初始化数据加载和任务列表显示
- 更新 WelcomeActivity 添加任务中心跳转功能
- 完善 TaskListVM 从服务端获取真实任务数据
这个提交包含在:
徐勤民 2026-04-18 11:19:22 +08:00
父节点 7bc0a53ed9
当前提交 f143b900ff
共有 8 个文件被更改,包括 97 次插入25 次删除

查看文件

@ -62,6 +62,9 @@ object AsrHelper : OfflineCmdListener {
/** goToDecisionCenter 命中时的回调,由各 Activity 在 onResume/onPause 中注册/清空 */
var onGoToDecisionCenter: ((action: RecognizeAction) -> Unit)? = null
/** goToTaskCenter 命中时的回调,由各 Activity 在 onResume/onPause 中注册/清空 */
var onGoToTaskCenter: ((action: RecognizeAction) -> Unit)? = null
/** scene == "decision" 时直接用 ASR 文本发起对话,由 ChatActivity 注册 */
var onDirectChat: ((text: String) -> Unit)? = null
@ -193,10 +196,10 @@ object AsrHelper : OfflineCmdListener {
text = text,
scence = scene,
onSuccess = { action ->
if (action.name == "goToDecisionCenter") {
onGoToDecisionCenter?.invoke(action)
} else {
"需要跳转任务列表".showMessage()
when (action.name) {
"goToDecisionCenter" -> onGoToDecisionCenter?.invoke(action)
"goToTaskCenter" -> onGoToTaskCenter?.invoke(action)
else -> Log.d(TAG, "unhandled action: $action")
}
}
)

查看文件

@ -44,5 +44,13 @@ data class RecognizeAction(
)
data class RecognizeParams(
val question: String,
val question: String? = null,
// goToTaskCenter params
val dateRange: Int? = null,
val dateTpye: Int? = null,
val isOverdue: Int? = null,
val keyword: String? = null,
val taskType: String? = null,
val tenantId: Int? = null,
val userId: String? = null,
)

查看文件

@ -2,6 +2,12 @@ package com.nova.brain.glass.model
import com.xuqm.base.adapter.BaseItem
data class TaskItem(val id: String): BaseItem() {
data class TaskItem(
val id: String,
val taskType: String = "",
val params: Map<String, String> = emptyMap(),
val processStatus: String = "",
val aiDescription: String = ""
) : BaseItem() {
var selected: Boolean = false
}

查看文件

@ -4,6 +4,7 @@ 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.TaskListData
import com.nova.brain.glass.model.TaskSearchResponse
import com.nova.brain.glass.model.data.TopicData
import com.nova.brain.glass.model.data.TopicModel
import io.reactivex.Observable
@ -33,6 +34,6 @@ interface Service {
fun tbtopic(@Body body: TopicData): Observable<TopicModel>
@POST("/cbrain-gateway/cbrain-task-server/cbrain-task/task/glassesTaskSearch")
fun glassesTaskSearch(@Body body: TaskListData): Observable<TopicModel>
fun glassesTaskSearch(@Body body: TaskListData): Observable<TaskSearchResponse>
}

查看文件

@ -108,7 +108,7 @@ class ChatActivity : BaseListFormLayoutNormalActivity<ChatItem, ChatVM, Activity
OfflineCmdServiceHelper.addOnLineListener(listener)
AsrHelper.scene = "decision"
AsrHelper.onGoToDecisionCenter = { action ->
viewModel.demoPostSse(action.params.question)
viewModel.demoPostSse(action.params.question!!)
}
AsrHelper.onDirectChat = { text ->
viewModel.demoPostSse(text)

查看文件

@ -9,6 +9,7 @@ import com.nova.brain.glass.databinding.ActivityTaskListBinding
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.TaskItem
import com.nova.brain.glass.model.data.TaskListData
import com.nova.brain.glass.viewmodel.TaskListVM
import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter
@ -73,6 +74,19 @@ class TaskListActivity :
}
}
override fun initData() {
viewModel.searchParams = TaskListData(
taskType = intent.getStringExtra("taskType") ?: "",
keyword = intent.getStringExtra("keyword") ?: "",
dateRange = intent.getIntExtra("dateRange", 0),
dateType = intent.getIntExtra("dateType", 0),
isOverdue = intent.getIntExtra("isOverdue", 2),
tenantId = intent.getIntExtra("tenantId", 1),
userId = intent.getStringExtra("userId") ?: ""
)
super.initData()
}
private val offlineCmdListener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) {
runOnUiThread { dispatchVoiceCmd(cmd) }
@ -182,10 +196,10 @@ class TaskListActivity :
private val adapter = object : CommonPagedAdapter<TaskItem>(R.layout.item_task_list) {
override fun convert(holder: ViewHolder, item: TaskItem, position: Int) {
val displayPosition = (position - pageStartPosition + 1).coerceAtLeast(1)
val title = "${displayPosition}. ${item.aiDescription}${item.processStatus}"
holder
.setText(R.id.tv_title, "${displayPosition}.[$position]张三提交的出差预算申请审核任务,从上海到北京,3月23开始3月24结束,预算金额¥1800元。【已逾期】")
.setClickListener(R.id.tv_title
) {
.setText(R.id.tv_title, title)
.setClickListener(R.id.tv_title) {
openTask(position)
}
}

查看文件

@ -12,6 +12,7 @@ import com.nova.brain.glass.helper.AsrHelper
import com.nova.brain.glass.helper.IntentRecognizeHelper
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.RecognizeParams
import com.nova.brain.glass.viewmodel.WelcomeVM
import com.xuqm.base.ui.BaseActivity
@ -59,13 +60,15 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
IntentRecognizeHelper.recognize(
text = "查看我的任务列表?",
onSuccess = { action ->
if (action.name == "goToDecisionCenter") {
startActivity(
when (action.name) {
"goToDecisionCenter" -> startActivity(
Intent(this, ChatActivity::class.java)
.putExtra("question", action.params.question)
)
} else {
Log.d("WelcomeActivity", "triggerRecognize onSuccess: $action")
"goToTaskCenter" -> startActivity(
intentForTaskList(action.params)
)
else -> Log.d("WelcomeActivity", "triggerRecognize onSuccess: $action")
}
},
onComplete = {
@ -101,6 +104,20 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
.putExtra("question", action.params.question)
)
}
AsrHelper.onGoToTaskCenter = { action ->
startActivity(intentForTaskList(action.params))
}
}
private fun intentForTaskList(params: RecognizeParams) =
Intent(this, TaskListActivity::class.java).apply {
putExtra("taskType", params.taskType ?: "")
putExtra("keyword", params.keyword ?: "")
putExtra("dateRange", params.dateRange ?: 0)
putExtra("dateType", params.dateTpye ?: 0)
putExtra("isOverdue", params.isOverdue ?: 2)
putExtra("tenantId", params.tenantId ?: 1)
putExtra("userId", params.userId ?: "")
}
override fun onPause() {
@ -109,6 +126,7 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
OfflineCmdServiceHelper.removeListenerWelcome()
dotsHandler.removeCallbacks(dotsRunnable)
AsrHelper.onGoToDecisionCenter = null
AsrHelper.onGoToTaskCenter = null
}
override fun onDestroy() {

查看文件

@ -1,18 +1,40 @@
package com.nova.brain.glass.viewmodel
import com.nova.brain.glass.MyApplication
import com.nova.brain.glass.model.TaskItem
import com.nova.brain.glass.model.data.TaskListData
import com.nova.brain.glass.repository.Service
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.schedulers.Schedulers
class TaskListVM : BaseListViewModel<TaskItem>() {
override fun loadData(
page: Int,
onResponse: Response<TaskItem>
) {
onResponse.onResponse(arrayListOf<TaskItem>().apply {
for (i in 0..10) {
add(TaskItem(i.toString()))
}
var searchParams: TaskListData =
TaskListData(taskType = "", keyword = "", dateRange = 0, dateType = 0)
override fun loadData(page: Int, onResponse: Response<TaskItem>) {
add(
HttpManager.getApi(MyApplication.appComponent1, Service::class.java)
.glassesTaskSearch(searchParams)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ response ->
val items = response.data?.list?.map {
TaskItem(
id = it.id,
taskType = it.taskType,
params = it.params,
processStatus = it.processStatus,
aiDescription = it.aiDescription
)
} ?: emptyList()
onResponse.onResponse(ArrayList(items))
}, {
onResponse.onResponse(arrayListOf())
})
)
}
}