diff --git a/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt b/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt index 915113b..462abcd 100644 --- a/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt +++ b/app/src/main/java/com/nova/brain/glass/helper/OfflineCmdServiceHelper.kt @@ -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"), diff --git a/app/src/main/java/com/nova/brain/glass/model/data/CompositeLayupApiData.kt b/app/src/main/java/com/nova/brain/glass/model/data/CompositeLayupApiData.kt index 332635b..551e7c8 100644 --- a/app/src/main/java/com/nova/brain/glass/model/data/CompositeLayupApiData.kt +++ b/app/src/main/java/com/nova/brain/glass/model/data/CompositeLayupApiData.kt @@ -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, 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 ed711ac..fc033fe 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 @@ -41,11 +41,10 @@ class ChatActivity : BaseListFormLayoutNormalActivity - 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() } } @@ -125,4 +124,4 @@ class ChatActivity : BaseListFormLayoutNormalActivity 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(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 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 { - 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) { + 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= 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() { diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index d4f48c4..e106717 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -13,22 +13,24 @@ android:layout_height="400dp" android:overScrollMode="never" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/activity_composite_layup_task.xml b/app/src/main/res/layout/activity_composite_layup_task.xml index 40d2772..e47f62f 100644 --- a/app/src/main/res/layout/activity_composite_layup_task.xml +++ b/app/src/main/res/layout/activity_composite_layup_task.xml @@ -2,6 +2,7 @@ @@ -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" /> + + - - @@ -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" /> - - - - - - - - - - - - - -