feat(composite-layup): 重构复合材料铺贴任务界面和功能
- 更新离线语音命令列表,新增开始铺贴、确认并继续等命令 - 修改数据模型,为CompositeLayupApiData添加ply、direction、vacuum字段 - 添加partNo和partName到CompositeLayupTaskDetail数据类 - 重构CompositeLayupTaskActivity界面状态管理,新增多个屏幕模式 - 实现铺贴任务流程控制,包括拍照、识别、铺贴、确认等步骤 - 添加倒计时自动返回任务列表功能 - 优化进度显示和操作提示信息 - 修复相机异常处理逻辑 - 更新聊天界面加载动画显示逻辑
这个提交包含在:
父节点
e676e03cb3
当前提交
47fa2c4464
@ -93,13 +93,15 @@ object OfflineCmdServiceHelper {
|
||||
private val CMDS_COMPOSITE_LAYUP = listOf(
|
||||
OfflineCmdBean("开始", "kai shi"),
|
||||
OfflineCmdBean("开始任务", "kai shi ren wu"),
|
||||
OfflineCmdBean("下一步", "xia yi bu"),
|
||||
OfflineCmdBean("继续识别", "ji xu shi bie"),
|
||||
OfflineCmdBean("继续任务", "ji xu ren wu"),
|
||||
OfflineCmdBean("重拍", "chong pai"),
|
||||
OfflineCmdBean("重新拍照", "chong xin pai zhao"),
|
||||
OfflineCmdBean("重新拍摄", "chong xin pai she"),
|
||||
OfflineCmdBean("完成任务", "wan cheng ren wu")
|
||||
OfflineCmdBean("开始铺贴", "kai shi pu tie"),
|
||||
OfflineCmdBean("确认并继续", "que ren bing ji xu"),
|
||||
OfflineCmdBean("否", "fou"),
|
||||
OfflineCmdBean("完成", "wan cheng"),
|
||||
OfflineCmdBean("完成任务", "wan cheng ren wu"),
|
||||
OfflineCmdBean("返回任务列表", "fan hui ren wu lie biao")
|
||||
)
|
||||
private val CMDS_WELCOME = listOf(
|
||||
OfflineCmdBean("决策中心", "jue ce zhong xin"),
|
||||
|
||||
@ -5,8 +5,9 @@ data class CompositeLayupDetailItem(
|
||||
val taskId: Long = 0,
|
||||
val taskNo: String = "",
|
||||
val stepSeq: Int = 0,
|
||||
val detailInfo: String = "",
|
||||
val detailResult: String = "",
|
||||
val ply: String = "",
|
||||
val direction: String = "",
|
||||
val vacuum: String = "",
|
||||
val detailStatus: Int = 0,
|
||||
val createdAt: String = "",
|
||||
val updatedAt: String = "",
|
||||
@ -17,6 +18,8 @@ data class CompositeLayupDetailItem(
|
||||
|
||||
data class CompositeLayupTaskDetail(
|
||||
val id: Long = 0,
|
||||
val partNo: String = "",
|
||||
val partName: String = "",
|
||||
val taskNo: String = "",
|
||||
val taskName: String = "",
|
||||
val taskType: Int = 0,
|
||||
|
||||
@ -41,11 +41,10 @@ class ChatActivity : BaseListFormLayoutNormalActivity<ChatItem, ChatVM, Activity
|
||||
scrollToBottom()
|
||||
}
|
||||
|
||||
// loading=true:pb 显示旋转 + 延一帧滚底(等 PagedList 提交到 adapter)
|
||||
// loading=false:pb 停转并隐藏
|
||||
// loading=true:显示旋转进度;loading=false:显示静态占位图
|
||||
viewModel.loading.observe(this) { loading ->
|
||||
binding.pb.visibility = if (loading) View.VISIBLE else View.INVISIBLE
|
||||
binding.pb1.visibility = if (!loading) View.VISIBLE else View.INVISIBLE
|
||||
binding.loadingProgress.visibility = if (loading) View.VISIBLE else View.GONE
|
||||
binding.loadingIdleIcon.visibility = if (loading) View.GONE else View.VISIBLE
|
||||
recyclerView.post { scrollToBottom() }
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +1,25 @@
|
||||
package com.nova.brain.glass.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.nova.brain.glass.R
|
||||
import com.nova.brain.glass.databinding.ActivityCompositeLayupTaskBinding
|
||||
import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
||||
import com.nova.brain.glass.helper.OfflineCmdListener
|
||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||
import com.nova.brain.glass.model.ItemItem
|
||||
import com.nova.brain.glass.viewmodel.CompositeLayupRecognizeState
|
||||
import com.nova.brain.glass.viewmodel.CompositeLayupTaskVM
|
||||
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
||||
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
||||
import com.xuqm.base.adapter.CommonAdapter
|
||||
import com.xuqm.base.adapter.ViewHolder
|
||||
import com.xuqm.base.common.LogHelper
|
||||
import com.xuqm.base.extensions.showMessage
|
||||
import com.xuqm.base.ui.BaseActivity
|
||||
@ -23,10 +31,14 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
override fun fullscreen(): Boolean = true
|
||||
|
||||
private enum class ScreenMode {
|
||||
START,
|
||||
STEP_SUCCESS,
|
||||
FAILED,
|
||||
FINISHED
|
||||
TASK_INFO,
|
||||
CAPTURE,
|
||||
RECOGNIZE_SUCCESS,
|
||||
RECOGNIZE_FAILED,
|
||||
LAYUP_PROMPT,
|
||||
LAYUP_WORKING,
|
||||
CONFIRM_FINISH,
|
||||
COMPLETE
|
||||
}
|
||||
|
||||
private val viewModel: CompositeLayupTaskVM by lazy {
|
||||
@ -35,24 +47,44 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
private val taskNoFromIntent: String by lazy {
|
||||
intent.getStringExtra(EXTRA_TASK_NO).orEmpty()
|
||||
}
|
||||
private val mainHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
private var isPhotoFallback = false
|
||||
private var isCaptureInFlight = false
|
||||
private var screenMode = ScreenMode.START
|
||||
private var screenMode = ScreenMode.TASK_INFO
|
||||
private var autoReturned = false
|
||||
|
||||
private val layupWorkingRunnable = Runnable {
|
||||
if (screenMode == ScreenMode.LAYUP_PROMPT) {
|
||||
applyScreenMode(ScreenMode.LAYUP_WORKING)
|
||||
}
|
||||
}
|
||||
|
||||
private val completeRunnable = Runnable {
|
||||
if (screenMode == ScreenMode.COMPLETE && !autoReturned) {
|
||||
autoReturned = true
|
||||
goTaskList()
|
||||
}
|
||||
}
|
||||
|
||||
private val listener = object : OfflineCmdListener {
|
||||
override fun onOfflineCmd(cmd: String) {
|
||||
runOnUiThread {
|
||||
when (cmd) {
|
||||
"退出", "返回", "退回" -> finish()
|
||||
"开始", "开始任务" -> if (screenMode == ScreenMode.START) triggerCapture()
|
||||
"下一步", "继续识别", "继续任务" -> {
|
||||
if (screenMode == ScreenMode.STEP_SUCCESS) triggerCapture()
|
||||
"开始", "开始任务" -> if (screenMode == ScreenMode.TASK_INFO) startCaptureFlow()
|
||||
"重新拍照", "重拍", "重新拍摄" -> {
|
||||
if (screenMode == ScreenMode.RECOGNIZE_FAILED) startCaptureFlow()
|
||||
}
|
||||
"重拍", "重新拍照", "重新拍摄" -> {
|
||||
if (screenMode == ScreenMode.FAILED) triggerCapture()
|
||||
"开始铺贴" -> if (screenMode == ScreenMode.RECOGNIZE_SUCCESS) startLayup()
|
||||
"确认并继续", "继续" -> if (screenMode == ScreenMode.CONFIRM_FINISH) confirmAndContinue()
|
||||
"否" -> if (screenMode == ScreenMode.CONFIRM_FINISH) backToWorking()
|
||||
"完成", "完成任务" -> {
|
||||
if (screenMode == ScreenMode.CONFIRM_FINISH && viewModel.canFinishAfterCurrentStep()) {
|
||||
finishCurrentTask()
|
||||
}
|
||||
"完成任务" -> if (screenMode == ScreenMode.FINISHED) finish()
|
||||
}
|
||||
"返回任务列表" -> if (screenMode == ScreenMode.COMPLETE) goTaskList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +107,9 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
} else {
|
||||
isCaptureInFlight = false
|
||||
runOnUiThread {
|
||||
updateHint("相机异常,请重试")
|
||||
val message = "相机异常,请重试"
|
||||
updateHint(message)
|
||||
applyScreenMode(ScreenMode.RECOGNIZE_FAILED, message)
|
||||
}
|
||||
"相机异常".showMessage()
|
||||
}
|
||||
@ -89,40 +123,50 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
}
|
||||
}
|
||||
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
bindClicks()
|
||||
applyScreenMode(ScreenMode.START)
|
||||
observeViewModel()
|
||||
if (taskNoFromIntent.isBlank()) {
|
||||
updateHint("任务编号缺失")
|
||||
"任务编号缺失".showMessage()
|
||||
} else {
|
||||
viewModel.loadTaskDetail(taskNoFromIntent)
|
||||
private val actionAdapter = object : CommonAdapter<ItemItem>(R.layout.item_manual_result_action) {
|
||||
override fun convert(holder: ViewHolder, item: ItemItem, position: Int) {
|
||||
holder.setText(R.id.text, item.text)
|
||||
.setClickListener(R.id.actionRoot) {
|
||||
when (item.text) {
|
||||
"开始任务" -> startCaptureFlow()
|
||||
"重新拍照" -> startCaptureFlow()
|
||||
"开始铺贴" -> startLayup()
|
||||
"确认并继续" -> confirmAndContinue()
|
||||
"否" -> backToWorking()
|
||||
"完成" -> finishCurrentTask()
|
||||
"返回任务列表" -> goTaskList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindClicks() {
|
||||
binding.btnAction.setOnClickListener {
|
||||
when (screenMode) {
|
||||
ScreenMode.START, ScreenMode.STEP_SUCCESS, ScreenMode.FAILED -> triggerCapture()
|
||||
ScreenMode.FINISHED -> finish()
|
||||
override fun initData() {
|
||||
super.initData()
|
||||
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
binding.baseRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
|
||||
binding.baseRecyclerView.adapter = actionAdapter
|
||||
binding.main.setOnClickListener {
|
||||
if (screenMode == ScreenMode.LAYUP_WORKING) {
|
||||
applyScreenMode(ScreenMode.CONFIRM_FINISH)
|
||||
}
|
||||
}
|
||||
binding.btnSecondary.setOnClickListener {
|
||||
if (screenMode == ScreenMode.FINISHED) {
|
||||
finish()
|
||||
}
|
||||
observeViewModel()
|
||||
applyScreenMode(ScreenMode.TASK_INFO)
|
||||
if (taskNoFromIntent.isBlank()) {
|
||||
val message = "任务编号缺失"
|
||||
updateHint(message)
|
||||
message.showMessage()
|
||||
} else {
|
||||
viewModel.loadTaskDetail(taskNoFromIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeViewModel() {
|
||||
viewModel.taskDetail.observe(this) { detail ->
|
||||
if (detail != null) {
|
||||
binding.tvTaskNo.text = "工号:${detail.taskNo.ifBlank { taskNoFromIntent }}"
|
||||
binding.tvTaskName.text = detail.taskName.ifBlank { "铺贴任务列表" }
|
||||
updateProgressText()
|
||||
binding.tvTaskName.text = detail.taskName.ifBlank { "铺贴任务" }
|
||||
renderTaskInfo()
|
||||
applyScreenMode(ScreenMode.TASK_INFO)
|
||||
}
|
||||
}
|
||||
viewModel.taskDetailError.observe(this) { msg ->
|
||||
@ -134,40 +178,45 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
viewModel.recognizeState.observe(this) { state ->
|
||||
when (state) {
|
||||
CompositeLayupRecognizeState.LOADING -> {
|
||||
binding.btnAction.isClickable = false
|
||||
updateHint("OCR识别中,请稍后...")
|
||||
renderActions(emptyList())
|
||||
}
|
||||
CompositeLayupRecognizeState.SUCCESS -> {
|
||||
binding.btnAction.isClickable = true
|
||||
handleRecognizeResult()
|
||||
}
|
||||
CompositeLayupRecognizeState.SUCCESS -> handleRecognizeResult()
|
||||
CompositeLayupRecognizeState.FAILED -> {
|
||||
binding.btnAction.isClickable = true
|
||||
val error = viewModel.recognizeError.value?.ifBlank { "OCR识别失败" } ?: "OCR识别失败"
|
||||
applyScreenMode(ScreenMode.FAILED, error)
|
||||
applyScreenMode(ScreenMode.RECOGNIZE_FAILED, error)
|
||||
}
|
||||
else -> binding.btnAction.isClickable = true
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTaskInfo() {
|
||||
val detail = viewModel.taskDetail.value ?: return
|
||||
binding.content1.text = "零件号:${detail.partNo.ifBlank { "-" }}"
|
||||
binding.content2.text = "任务编号:${detail.taskNo.ifBlank { taskNoFromIntent }}"
|
||||
binding.content3.text = "任务进度:${viewModel.currentProgressText()}"
|
||||
}
|
||||
|
||||
private fun handleRecognizeResult() {
|
||||
val result = viewModel.recognizeResult.value ?: return
|
||||
when {
|
||||
result.success && result.finished -> applyScreenMode(ScreenMode.FINISHED)
|
||||
result.success -> applyScreenMode(ScreenMode.STEP_SUCCESS)
|
||||
else -> applyScreenMode(ScreenMode.FAILED, result.errorMessage.ifBlank { "识别铺贴错误,请重新拍取" })
|
||||
if (result.success) {
|
||||
applyScreenMode(ScreenMode.RECOGNIZE_SUCCESS)
|
||||
} else {
|
||||
applyScreenMode(
|
||||
ScreenMode.RECOGNIZE_FAILED,
|
||||
result.errorMessage.ifBlank { "识别失败,请重试!" }
|
||||
)
|
||||
}
|
||||
viewModel.resetRecognizeState()
|
||||
}
|
||||
|
||||
private fun triggerCapture() {
|
||||
private fun startCaptureFlow() {
|
||||
if (isCaptureInFlight || taskNoFromIntent.isBlank()) {
|
||||
return
|
||||
}
|
||||
isCaptureInFlight = true
|
||||
binding.btnAction.isClickable = false
|
||||
updateHint("拍照中,请稍后...")
|
||||
applyScreenMode(ScreenMode.CAPTURE)
|
||||
takePhoto()
|
||||
}
|
||||
|
||||
@ -181,58 +230,144 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_720P, file.absolutePath)
|
||||
}
|
||||
|
||||
private fun updateProgressText() {
|
||||
binding.tvProgress.text = "任务进度:${viewModel.currentStepSeq}/${viewModel.totalSteps}"
|
||||
binding.tvStepHint.text = "识别到当前层第${viewModel.currentStepSeq}层 / 共${viewModel.totalSteps}层"
|
||||
private fun startLayup() {
|
||||
applyScreenMode(ScreenMode.LAYUP_PROMPT)
|
||||
}
|
||||
|
||||
private fun backToWorking() {
|
||||
applyScreenMode(ScreenMode.LAYUP_WORKING)
|
||||
}
|
||||
|
||||
private fun confirmAndContinue() {
|
||||
if (viewModel.canFinishAfterCurrentStep()) {
|
||||
finishCurrentTask()
|
||||
return
|
||||
}
|
||||
if (viewModel.moveToNextStep()) {
|
||||
renderTaskInfo()
|
||||
applyScreenMode(ScreenMode.TASK_INFO)
|
||||
}
|
||||
}
|
||||
|
||||
private fun finishCurrentTask() {
|
||||
applyScreenMode(ScreenMode.COMPLETE)
|
||||
}
|
||||
|
||||
private fun applyScreenMode(mode: ScreenMode, errorMessage: String = "") {
|
||||
screenMode = mode
|
||||
updateProgressText()
|
||||
binding.groupStart.visibility = if (mode == ScreenMode.START) View.VISIBLE else View.GONE
|
||||
binding.groupResult.visibility = if (mode == ScreenMode.START) View.GONE else View.VISIBLE
|
||||
binding.btnSecondary.visibility = if (mode == ScreenMode.FINISHED) View.VISIBLE else View.GONE
|
||||
mainHandler.removeCallbacks(layupWorkingRunnable)
|
||||
mainHandler.removeCallbacks(completeRunnable)
|
||||
renderTaskInfo()
|
||||
binding.groupStart.visibility = if (mode == ScreenMode.TASK_INFO) View.VISIBLE else View.GONE
|
||||
binding.groupCapture.visibility = if (mode == ScreenMode.CAPTURE) View.VISIBLE else View.GONE
|
||||
binding.groupResult.visibility =
|
||||
if (mode == ScreenMode.RECOGNIZE_SUCCESS || mode == ScreenMode.RECOGNIZE_FAILED) View.VISIBLE else View.GONE
|
||||
binding.groupWork.visibility =
|
||||
if (mode == ScreenMode.LAYUP_PROMPT || mode == ScreenMode.LAYUP_WORKING) View.VISIBLE else View.GONE
|
||||
binding.groupConfirm.visibility = if (mode == ScreenMode.CONFIRM_FINISH) View.VISIBLE else View.GONE
|
||||
binding.groupComplete.visibility = if (mode == ScreenMode.COMPLETE) View.VISIBLE else View.GONE
|
||||
|
||||
when (mode) {
|
||||
ScreenMode.START -> {
|
||||
binding.resultIcon.setImageResource(R.mipmap.ocr_photo)
|
||||
binding.resultTitle.text = "请开始本层铺贴工作"
|
||||
binding.resultSubtitle.text = "语音输入“开始任务”或点击按钮后拍照识别"
|
||||
binding.btnAction.text = "开工"
|
||||
updateHint("左滑右滑选择任务,单击开工,开始该任务。")
|
||||
ScreenMode.TASK_INFO -> {
|
||||
binding.captureMessage.text = "请对准下一张复材铺贴物料上的字符内容"
|
||||
binding.startIcon.setImageResource(R.mipmap.ocr_photo)
|
||||
renderActions(listOf("开始任务"))
|
||||
updateHint("单击或语音输入\"开始\",进入下一步")
|
||||
}
|
||||
ScreenMode.STEP_SUCCESS -> {
|
||||
ScreenMode.CAPTURE -> {
|
||||
binding.captureMessage.text = "请对准复材铺贴物料上的字符内容"
|
||||
renderActions(emptyList())
|
||||
updateHint("拍照中,请稍后...")
|
||||
}
|
||||
ScreenMode.RECOGNIZE_SUCCESS -> {
|
||||
val currentDetail = viewModel.currentDetail()
|
||||
binding.resultIcon.setImageResource(R.mipmap.ocr_true)
|
||||
binding.resultTitle.text = "识别铺贴层与料号信息正确"
|
||||
binding.resultSubtitle.text = "请开始下一层铺贴工作"
|
||||
binding.btnAction.text = "下一步"
|
||||
updateHint("当前层识别通过,可进入下一层识别。")
|
||||
binding.resultTitle.text = "铺贴层与零件信息正确"
|
||||
binding.resultSubtitle1.text = "识别到这是${viewModel.currentProgressText()}张"
|
||||
binding.resultSubtitle2.text = buildRecognizeInstruction(currentDetail?.vacuum, currentDetail?.direction)
|
||||
renderActions(listOf("开始铺贴"))
|
||||
updateHint("单击或语音输入\"开始铺贴\",进入下一步")
|
||||
}
|
||||
ScreenMode.FAILED -> {
|
||||
ScreenMode.RECOGNIZE_FAILED -> {
|
||||
binding.resultIcon.setImageResource(R.mipmap.ocr_false)
|
||||
binding.resultTitle.text = errorMessage.ifBlank { "识别铺贴错误,请重新拍取" }
|
||||
binding.resultSubtitle.text = "请重新拍照识别"
|
||||
binding.btnAction.text = "重拍"
|
||||
updateHint(errorMessage.ifBlank { "识别失败,请重试" })
|
||||
binding.resultTitle.text = errorMessage.ifBlank { "识别失败,请重试!" }
|
||||
binding.resultSubtitle1.text = "识别到这是${viewModel.currentProgressText()}张"
|
||||
binding.resultSubtitle2.text = "请重新拿取"
|
||||
renderActions(listOf("重新拍照"))
|
||||
updateHint("单击或语音输入\"重新拍照\",进入下一步")
|
||||
}
|
||||
ScreenMode.FINISHED -> {
|
||||
binding.resultIcon.setImageResource(R.mipmap.ocr_true)
|
||||
binding.resultTitle.text = "恭喜完成全部铺贴逐层任务!"
|
||||
binding.resultSubtitle.text = "请点击返回,回到铺贴任务列表开启下一任务"
|
||||
binding.btnAction.text = "返回"
|
||||
binding.btnSecondary.text = "完成任务"
|
||||
updateHint("当前任务已全部完成。")
|
||||
ScreenMode.LAYUP_PROMPT -> {
|
||||
binding.workText.text = "请进行铺贴工作\n完成后,滑动唤醒眼镜!"
|
||||
renderActions(emptyList())
|
||||
updateHint("")
|
||||
mainHandler.postDelayed(layupWorkingRunnable, 5000L)
|
||||
}
|
||||
ScreenMode.LAYUP_WORKING -> {
|
||||
binding.workText.text = buildWorkingInstruction()
|
||||
renderActions(emptyList())
|
||||
updateHint("")
|
||||
}
|
||||
ScreenMode.CONFIRM_FINISH -> {
|
||||
binding.confirmTitle.text = "请确认是否已完成第${viewModel.currentProgressText()}张铺贴"
|
||||
val primary = if (viewModel.canFinishAfterCurrentStep()) "完成" else "确认并继续"
|
||||
renderActions(listOf(primary, "否"))
|
||||
updateHint("点击或语音输入对应按钮,继续流程")
|
||||
}
|
||||
ScreenMode.COMPLETE -> {
|
||||
autoReturned = false
|
||||
binding.completeSubtitle.text = "3S后自动返回铺贴任务界面"
|
||||
renderActions(listOf("返回任务列表"))
|
||||
updateHint("")
|
||||
mainHandler.postDelayed(completeRunnable, 3000L)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderActions(actions: List<String>) {
|
||||
actionAdapter.setmDatas(actions.map(::ItemItem))
|
||||
binding.baseRecyclerView.layoutParams = binding.baseRecyclerView.layoutParams.apply {
|
||||
height = dpToPx(
|
||||
when {
|
||||
actions.isEmpty() -> 88
|
||||
actions.size == 1 -> 88
|
||||
else -> 152
|
||||
}
|
||||
)
|
||||
}
|
||||
binding.baseRecyclerView.visibility = if (actions.isEmpty()) View.INVISIBLE else View.VISIBLE
|
||||
}
|
||||
|
||||
private fun updateHint(text: String) {
|
||||
binding.hint.text = text
|
||||
binding.hint.visibility = if (text.isBlank()) View.INVISIBLE else View.VISIBLE
|
||||
}
|
||||
|
||||
private fun buildRecognizeInstruction(vacuum: String?, direction: String?): String {
|
||||
val vacuumText = if (vacuum.isNullOrBlank()) "" else "请真空铺贴、"
|
||||
val directionText = if (direction.isNullOrBlank()) "" else "纹理方向$direction"
|
||||
return (vacuumText + directionText).ifBlank { "请开始铺贴" }
|
||||
}
|
||||
|
||||
private fun buildWorkingInstruction(): String {
|
||||
val detail = viewModel.currentDetail()
|
||||
val stepText = "正在铺贴第${viewModel.currentStepSeq}张"
|
||||
val vacuumText = if (detail?.vacuum.isNullOrBlank()) "" else "请真空铺贴、"
|
||||
val directionText = if (detail?.direction.isNullOrBlank()) "" else "纹理方向${detail?.direction}、"
|
||||
return "$stepText\n${vacuumText}${directionText}撕衬纸\n完成后,滑动唤醒眼镜!"
|
||||
}
|
||||
|
||||
private fun goTaskList() {
|
||||
startActivity(Intent(this, TaskListActivity::class.java).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
})
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun dpToPx(dp: Int): Int =
|
||||
(dp * resources.displayMetrics.density).toInt()
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
isCaptureInFlight = false
|
||||
binding.btnAction.isClickable = true
|
||||
GlassMediaServiceHelper.addPhotoCallback(photoCallback)
|
||||
OfflineCmdServiceHelper.addListenerCompositeLayup()
|
||||
OfflineCmdServiceHelper.addOnLineListener(listener)
|
||||
@ -240,6 +375,8 @@ class CompositeLayupTaskActivity : BaseActivity<ActivityCompositeLayupTaskBindin
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mainHandler.removeCallbacks(layupWorkingRunnable)
|
||||
mainHandler.removeCallbacks(completeRunnable)
|
||||
GlassMediaServiceHelper.removePhotoCallback(photoCallback)
|
||||
OfflineCmdServiceHelper.removeListenerCompositeLayup()
|
||||
OfflineCmdServiceHelper.removeOnLineListener(listener)
|
||||
|
||||
@ -3,6 +3,7 @@ package com.nova.brain.glass.viewmodel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.nova.brain.glass.MyApplication
|
||||
import com.nova.brain.glass.model.data.CompositeLayupRecognizeResult
|
||||
import com.nova.brain.glass.model.data.CompositeLayupDetailItem
|
||||
import com.nova.brain.glass.model.data.CompositeLayupTaskDetail
|
||||
import com.nova.brain.glass.repository.Service4
|
||||
import com.xuqm.base.di.manager.HttpManager
|
||||
@ -32,6 +33,8 @@ class CompositeLayupTaskVM : ViewModel() {
|
||||
private set
|
||||
var totalSteps: Int = 1
|
||||
private set
|
||||
var lastRecognizeFinished: Boolean = false
|
||||
private set
|
||||
|
||||
fun loadTaskDetail(taskNo: String) {
|
||||
this.taskNo = taskNo
|
||||
@ -76,10 +79,8 @@ class CompositeLayupTaskVM : ViewModel() {
|
||||
val result = response.data
|
||||
if (response.success && result != null) {
|
||||
recognizeResult.value = result
|
||||
lastRecognizeFinished = result.finished
|
||||
recognizeState.value = CompositeLayupRecognizeState.SUCCESS
|
||||
if (result.success && !result.finished) {
|
||||
currentStepSeq = (currentStepSeq + 1).coerceAtMost(totalSteps.coerceAtLeast(1))
|
||||
}
|
||||
} else {
|
||||
recognizeState.value = CompositeLayupRecognizeState.FAILED
|
||||
recognizeError.value = response.message.ifBlank { "OCR识别失败" }
|
||||
@ -97,6 +98,29 @@ class CompositeLayupTaskVM : ViewModel() {
|
||||
recognizeError.value = ""
|
||||
}
|
||||
|
||||
fun currentDetail(): CompositeLayupDetailItem? =
|
||||
taskDetail.value?.detailList
|
||||
?.sortedBy { it.stepSeq }
|
||||
?.firstOrNull { it.stepSeq == currentStepSeq }
|
||||
?: taskDetail.value?.detailList
|
||||
?.sortedBy { it.stepSeq }
|
||||
?.getOrNull((currentStepSeq - 1).coerceAtLeast(0))
|
||||
|
||||
fun currentProgressText(): String = "${currentStepSeq}/${totalSteps}"
|
||||
|
||||
fun canFinishAfterCurrentStep(): Boolean =
|
||||
lastRecognizeFinished || currentStepSeq >= totalSteps
|
||||
|
||||
fun moveToNextStep(): Boolean {
|
||||
if (currentStepSeq >= totalSteps) {
|
||||
return false
|
||||
}
|
||||
currentStepSeq += 1
|
||||
lastRecognizeFinished = false
|
||||
resetRecognizeState()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun bindTaskDetail(detail: CompositeLayupTaskDetail) {
|
||||
taskDetail.value = detail
|
||||
this.taskNo = detail.taskNo.ifBlank { taskNo }
|
||||
@ -109,6 +133,7 @@ class CompositeLayupTaskVM : ViewModel() {
|
||||
}
|
||||
else -> 1
|
||||
}.coerceIn(1, totalSteps)
|
||||
lastRecognizeFinished = currentStepSeq >= totalSteps
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
||||
@ -13,22 +13,24 @@
|
||||
android:layout_height="400dp"
|
||||
android:overScrollMode="never" />
|
||||
<ProgressBar
|
||||
android:id="@+id/pb"
|
||||
android:id="@+id/loadingProgress"
|
||||
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/baseRecyclerView"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:visibility="gone"
|
||||
android:indeterminateDrawable="@drawable/load_progress" />
|
||||
<ImageView
|
||||
android:id="@+id/pb1"
|
||||
android:id="@+id/loadingIdleIcon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/baseRecyclerView"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:visibility="visible"
|
||||
android:src="@drawable/loading"/>
|
||||
|
||||
<TextView
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<layout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/app_color_black">
|
||||
@ -13,7 +14,7 @@
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/bg_item"
|
||||
android:gravity="center"
|
||||
android:text="复材铺贴任务:逐层识别作业"
|
||||
android:text="复材铺贴任务"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -49,7 +50,17 @@
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTaskNo"
|
||||
android:id="@+id/content1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="零件号:20293989-001"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
@ -59,22 +70,12 @@
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="任务进度:1/12"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStepHint"
|
||||
android:id="@+id/content3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:text="当前识别层:第1层 / 共12层"
|
||||
android:text="任务进度:1/12"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@ -96,99 +97,234 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:text="单击或语音输入"开始",进入下一步"
|
||||
android:text="单击或语音输入"开始",进入下一步"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupStart"
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btnAction"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/hint">
|
||||
app:layout_constraintTop_toBottomOf="@id/hint">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupStart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:background="@drawable/bg_composite_circle">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="150dp"
|
||||
android:id="@+id/startIcon"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@mipmap/ocr_photo" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupCapture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="320dp"
|
||||
android:layout_height="220dp">
|
||||
|
||||
<View
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="4dp"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="60dp"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="top|end"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="top|end"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="4dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<View
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:background="#ff40FF5E" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/captureMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="请对准复材铺贴物料上的字符内容"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="16sp" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupResult"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btnAction"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/hint">
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/resultIcon"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="150dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@mipmap/ocr_true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resultTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="识别铺贴层与料号信息正确"
|
||||
android:text="铺贴层与料号信息正确"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resultSubtitle"
|
||||
android:id="@+id/resultSubtitle1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:gravity="center"
|
||||
android:text="识别到这是1/12张"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/resultSubtitle2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="请开始下一层铺贴工作"
|
||||
android:text="请真空铺贴、纹理方向+90"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSecondary"
|
||||
android:layout_width="138dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@drawable/bg_composite_button_solid"
|
||||
android:backgroundTint="@null"
|
||||
android:text="完成任务"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" />
|
||||
android:textSize="18sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnAction"
|
||||
android:layout_width="148dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="28dp"
|
||||
android:background="@drawable/bg_composite_button_outline"
|
||||
android:backgroundTint="@null"
|
||||
android:text="开工"
|
||||
android:textAllCaps="false"
|
||||
<LinearLayout
|
||||
android:id="@+id/groupWork"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/workText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="请进行铺贴工作"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
android:textSize="22sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupConfirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/confirmTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="请确认是否已完成第3/12张铺贴"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="22sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/groupComplete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@mipmap/ocr_true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:text="恭喜完成当前铺贴任务!"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/completeSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:text="3S后自动返回铺贴任务界面"
|
||||
android:textColor="#ff40FF5E"
|
||||
android:textSize="18sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户