feat(repository): 添加批量上传和任务提交接口支持
- 在 Service 接口中新增 batchUpload 和 submitTask 方法 - 添加 SubmitTaskRequest 和 SubmitTaskResponse 数据类 - 集成 Multipart 上传功能用于文件批量上传 - 添加完整的任务提交流程支持 refactor(ui): 优化喷涂作业界面任务信息获取逻辑 - 移除 SprayingActivity 中的直接网络请求代码 - 将任务信息获取改为通过 ViewModel 管理 - 添加 taskId 参数传递到 OCR 界面 - 简化 Activity 中的 RxJava 订阅管理 refactor(ui): 更新OCR识别界面上传和倒计时逻辑 - 移除 CountDownTimer 相关代码 - 添加基于 ViewModel 的上传状态管理 - 实现文件上传进度、成功、失败状态处理 - 添加取消上传功能 refactor(ui): 完善任务结果提交和成功提示逻辑 - 添加任务提交状态管理 (IDLE/LOADING/SUCCESS/FAILED) - 实现提交成功后显示审查对话框的功能 - 添加自动跳转回任务列表的延迟处理 - 优化资源清理和消息提示机制 feat(viewmodel): 新增喷涂相关ViewModel数据状态管理 - 在 SprayingVM 中添加任务信息获取和UI数据显示 - 在 SprayingOCRVM 中实现文件上传状态管理 - 在 SprayingResultVM 中实现任务提交状态管理 - 统一错误处理和用户反馈机制
这个提交包含在:
父节点
42b353c972
当前提交
2df4c0795d
@ -0,0 +1,12 @@
|
|||||||
|
package com.nova.brain.glass.model.data
|
||||||
|
|
||||||
|
data class SubmitTaskRequest(
|
||||||
|
val id: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SubmitTaskResponse(
|
||||||
|
val code: Int,
|
||||||
|
val message: String,
|
||||||
|
val data: Any? = null
|
||||||
|
)
|
||||||
|
|
||||||
@ -8,6 +8,8 @@ import com.nova.brain.glass.model.data.BackToRequest
|
|||||||
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
||||||
import com.nova.brain.glass.model.data.GetTaskInfoResponse
|
import com.nova.brain.glass.model.data.GetTaskInfoResponse
|
||||||
import com.nova.brain.glass.model.data.RecognizeData
|
import com.nova.brain.glass.model.data.RecognizeData
|
||||||
|
import com.nova.brain.glass.model.data.SubmitTaskRequest
|
||||||
|
import com.nova.brain.glass.model.data.SubmitTaskResponse
|
||||||
import com.nova.brain.glass.model.data.PushToNextData
|
import com.nova.brain.glass.model.data.PushToNextData
|
||||||
import com.nova.brain.glass.model.data.PushToNextRequest
|
import com.nova.brain.glass.model.data.PushToNextRequest
|
||||||
import com.nova.brain.glass.model.data.RecommendBackNodeData
|
import com.nova.brain.glass.model.data.RecommendBackNodeData
|
||||||
@ -19,11 +21,14 @@ import com.nova.brain.glass.model.TaskSearchResponse
|
|||||||
import com.nova.brain.glass.model.data.TopicData
|
import com.nova.brain.glass.model.data.TopicData
|
||||||
import com.nova.brain.glass.model.data.TopicModel
|
import com.nova.brain.glass.model.data.TopicModel
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Headers
|
import retrofit2.http.Headers
|
||||||
|
import retrofit2.http.Multipart
|
||||||
|
import retrofit2.http.Part
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Streaming
|
import retrofit2.http.Streaming
|
||||||
|
|
||||||
@ -63,4 +68,11 @@ interface Service {
|
|||||||
@POST("/skyscopicsecond-api/api/aiGlasses/getTaskInfo")
|
@POST("/skyscopicsecond-api/api/aiGlasses/getTaskInfo")
|
||||||
fun getTaskInfo(@Body body: GetTaskInfoRequest): Observable<GetTaskInfoResponse>
|
fun getTaskInfo(@Body body: GetTaskInfoRequest): Observable<GetTaskInfoResponse>
|
||||||
|
|
||||||
|
@Multipart
|
||||||
|
@POST("/skyscopicsecond-api/api/aiGlasses/batchUpload")
|
||||||
|
fun batchUpload(@Part multipartFile: MultipartBody.Part): Observable<ResponseBody>
|
||||||
|
|
||||||
|
@POST("/api/aiGlasses/submitTask")
|
||||||
|
fun submitTask(@Body body: SubmitTaskRequest): Observable<SubmitTaskResponse>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package com.nova.brain.glass.ui
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.nova.brain.glass.MyApplication
|
|
||||||
import com.nova.brain.glass.R
|
import com.nova.brain.glass.R
|
||||||
import com.nova.brain.glass.databinding.ActivitySprayingBinding
|
import com.nova.brain.glass.databinding.ActivitySprayingBinding
|
||||||
import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
import com.nova.brain.glass.helper.GlassMediaServiceHelper
|
||||||
@ -11,8 +10,6 @@ import com.nova.brain.glass.helper.OfflineCmdListener
|
|||||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||||
import com.nova.brain.glass.helper.SprayingPhotoManager
|
import com.nova.brain.glass.helper.SprayingPhotoManager
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
|
||||||
import com.nova.brain.glass.repository.Service
|
|
||||||
import com.nova.brain.glass.viewmodel.SprayingVM
|
import com.nova.brain.glass.viewmodel.SprayingVM
|
||||||
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
||||||
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
||||||
@ -20,12 +17,8 @@ import com.xuqm.base.adapter.BasePagedAdapter
|
|||||||
import com.xuqm.base.adapter.CommonPagedAdapter
|
import com.xuqm.base.adapter.CommonPagedAdapter
|
||||||
import com.xuqm.base.adapter.ViewHolder
|
import com.xuqm.base.adapter.ViewHolder
|
||||||
import com.xuqm.base.common.LogHelper
|
import com.xuqm.base.common.LogHelper
|
||||||
import com.xuqm.base.di.manager.HttpManager
|
|
||||||
import com.xuqm.base.extensions.showMessage
|
import com.xuqm.base.extensions.showMessage
|
||||||
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
|
import com.xuqm.base.ui.BaseListFormLayoutNormalActivity
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.disposables.Disposable
|
|
||||||
import io.reactivex.schedulers.Schedulers
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@ -35,7 +28,6 @@ class SprayingActivity :
|
|||||||
override fun fullscreen(): Boolean = true
|
override fun fullscreen(): Boolean = true
|
||||||
|
|
||||||
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
|
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
|
||||||
private var taskInfoDisposable: Disposable? = null
|
|
||||||
private val taskId: String by lazy {
|
private val taskId: String by lazy {
|
||||||
intent.getStringExtra("taskId")
|
intent.getStringExtra("taskId")
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
@ -99,6 +91,7 @@ class SprayingActivity :
|
|||||||
SprayingPhotoManager.addPhoto(path)
|
SprayingPhotoManager.addPhoto(path)
|
||||||
startActivity(Intent(this@SprayingActivity, SprayingOCRActivity::class.java).apply {
|
startActivity(Intent(this@SprayingActivity, SprayingOCRActivity::class.java).apply {
|
||||||
putExtra("path", path)
|
putExtra("path", path)
|
||||||
|
putExtra("taskId", taskId)
|
||||||
})
|
})
|
||||||
finish()
|
finish()
|
||||||
// runOnUiThread {
|
// runOnUiThread {
|
||||||
@ -114,32 +107,19 @@ class SprayingActivity :
|
|||||||
super.initData()
|
super.initData()
|
||||||
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
binding.tvTaskHeader.text = "您还有10项任务未完成"
|
binding.tvTaskHeader.text = "您还有10项任务未完成"
|
||||||
fetchTaskInfo()
|
viewModel.taskInfo.observe(this) { info ->
|
||||||
}
|
binding.tvTaskHeader.text = "您还有${info.taskCount}项任务未完成"
|
||||||
|
binding.title.text = "任务1:${info.itemName}"
|
||||||
private fun fetchTaskInfo() {
|
binding.content1.text = "AO/AAO:${info.aoNumber}"
|
||||||
if (taskId.isBlank()) return
|
binding.content2.text = "工序号:${info.productionInfoId}"
|
||||||
taskInfoDisposable?.dispose()
|
binding.content3.text = "架次:${info.frameTime}"
|
||||||
taskInfoDisposable = HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
}
|
||||||
.getTaskInfo(GetTaskInfoRequest(id = taskId))
|
viewModel.taskInfoError.observe(this) { message ->
|
||||||
.subscribeOn(Schedulers.io())
|
if (message.isNotBlank()) {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
message.showMessage()
|
||||||
.subscribe({ response ->
|
}
|
||||||
if (response.code == 200) {
|
}
|
||||||
val taskInfo = response.data
|
viewModel.fetchTaskInfo(taskId)
|
||||||
val formList = taskInfo?.productionFormDtoList.orEmpty()
|
|
||||||
binding.tvTaskHeader.text = "您还有${formList.size}项任务未完成"
|
|
||||||
val firstForm = formList.firstOrNull()
|
|
||||||
binding.title.text = "任务1:${firstForm?.itemName.orEmpty()}"
|
|
||||||
binding.content1.text = "AO/AAO:${taskInfo?.aoNumber.orEmpty()}"
|
|
||||||
binding.content2.text = "工序号:${taskInfo?.productionInfoId.orEmpty()}"
|
|
||||||
binding.content3.text = "架次:${taskInfo?.frameTime.orEmpty()}"
|
|
||||||
} else {
|
|
||||||
(if (response.message.isBlank()) "任务信息获取失败" else response.message).showMessage()
|
|
||||||
}
|
|
||||||
}, { e ->
|
|
||||||
(e.message ?: "任务信息获取失败").showMessage()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -157,7 +137,6 @@ class SprayingActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
taskInfoDisposable?.dispose()
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.nova.brain.glass.ui
|
package com.nova.brain.glass.ui
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.CountDownTimer
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.view.doOnLayout
|
import androidx.core.view.doOnLayout
|
||||||
@ -14,6 +13,7 @@ import com.nova.brain.glass.helper.OfflineCmdListener
|
|||||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||||
import com.nova.brain.glass.helper.SprayingPhotoManager
|
import com.nova.brain.glass.helper.SprayingPhotoManager
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
import com.nova.brain.glass.viewmodel.UploadState
|
||||||
import com.nova.brain.glass.viewmodel.SprayingOCRVM
|
import com.nova.brain.glass.viewmodel.SprayingOCRVM
|
||||||
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
||||||
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
||||||
@ -33,6 +33,7 @@ class SprayingOCRActivity :
|
|||||||
override fun fullscreen(): Boolean = true
|
override fun fullscreen(): Boolean = true
|
||||||
|
|
||||||
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
|
override fun getRecyclerOrientation(): Int = RecyclerView.VERTICAL
|
||||||
|
private val taskId: String by lazy { intent.getStringExtra("taskId").orEmpty() }
|
||||||
|
|
||||||
private val listener = object : OfflineCmdListener {
|
private val listener = object : OfflineCmdListener {
|
||||||
override fun onOfflineCmd(cmd: String) {
|
override fun onOfflineCmd(cmd: String) {
|
||||||
@ -42,6 +43,7 @@ class SprayingOCRActivity :
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
"开始", "拍照", "开始拍照", "开始任务", "重拍", "重新拍", "在拍一次" -> {
|
"开始", "拍照", "开始拍照", "开始任务", "重拍", "重新拍", "在拍一次" -> {
|
||||||
|
viewModel.cancelUpload()
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.hint.text = "拍照中,请稍后..."
|
binding.hint.text = "拍照中,请稍后..."
|
||||||
}
|
}
|
||||||
@ -55,15 +57,12 @@ class SprayingOCRActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun takePhoto() {
|
fun takePhoto() {
|
||||||
resultCountdown?.cancel()
|
|
||||||
resultCountdown = null
|
|
||||||
val fileName = "test_${System.currentTimeMillis()}.png"
|
val fileName = "test_${System.currentTimeMillis()}.png"
|
||||||
val publicPicturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
val publicPicturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
||||||
val file = File(publicPicturesDir, fileName)
|
val file = File(publicPicturesDir, fileName)
|
||||||
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_480P, file.absolutePath)
|
GlassMediaServiceHelper.takePhoto(PhotoResolution.RESOLUTION_480P, file.absolutePath)
|
||||||
}
|
}
|
||||||
private val photoCallbackId = UUID.randomUUID().toString()
|
private val photoCallbackId = UUID.randomUUID().toString()
|
||||||
private var resultCountdown: CountDownTimer? = null
|
|
||||||
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
private val mPhotoFileCallback = object : PhotoFileCallback.Stub() {
|
private val mPhotoFileCallback = object : PhotoFileCallback.Stub() {
|
||||||
@ -92,6 +91,7 @@ class SprayingOCRActivity :
|
|||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.hint.text = "单击或语音输入“重拍”,可重新拍摄"
|
binding.hint.text = "单击或语音输入“重拍”,可重新拍摄"
|
||||||
showPhoto(path)
|
showPhoto(path)
|
||||||
|
viewModel.startUpload(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,8 +101,32 @@ class SprayingOCRActivity :
|
|||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
viewModel.uploadState.observe(this) { state ->
|
||||||
|
binding.tvTaskHeader.text = when (state) {
|
||||||
|
UploadState.UPLOADING -> "附件上传中,请稍后..."
|
||||||
|
UploadState.SUCCESS -> "附件上传成功"
|
||||||
|
UploadState.FAILED -> "附件上传失败,请重拍"
|
||||||
|
UploadState.IDLE -> "OCR识别中,请稍后..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.uploadError.observe(this) { message ->
|
||||||
|
if (message.isNotBlank()) {
|
||||||
|
binding.hint.text = "单击或语音输入“重拍”,可重新拍摄"
|
||||||
|
message.showMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.uploadSuccessPath.observe(this) { path ->
|
||||||
|
if (path.isNullOrBlank()) return@observe
|
||||||
|
viewModel.clearUploadSuccessPath()
|
||||||
|
startActivity(Intent(this@SprayingOCRActivity, SprayingResultActivity::class.java).apply {
|
||||||
|
putExtra("path", path)
|
||||||
|
putExtra("taskId", taskId)
|
||||||
|
})
|
||||||
|
finish()
|
||||||
|
}
|
||||||
intent.getStringExtra("path")?.apply {
|
intent.getStringExtra("path")?.apply {
|
||||||
showPhoto(this)
|
showPhoto(this)
|
||||||
|
viewModel.startUpload(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,13 +139,13 @@ class SprayingOCRActivity :
|
|||||||
}
|
}
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
resultCountdown?.cancel()
|
|
||||||
OfflineCmdServiceHelper.removeListenerSprayingOCR()
|
OfflineCmdServiceHelper.removeListenerSprayingOCR()
|
||||||
OfflineCmdServiceHelper.removeOnLineListener(listener)
|
OfflineCmdServiceHelper.removeOnLineListener(listener)
|
||||||
GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
|
GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
viewModel.cancelUpload()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
binding.content.setImageDrawable(null)
|
binding.content.setImageDrawable(null)
|
||||||
}
|
}
|
||||||
@ -134,6 +158,7 @@ class SprayingOCRActivity :
|
|||||||
.setClickListener(R.id.photo) {
|
.setClickListener(R.id.photo) {
|
||||||
when (item.text) {
|
when (item.text) {
|
||||||
"重拍" -> {
|
"重拍" -> {
|
||||||
|
viewModel.cancelUpload()
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.hint.text = "拍照中,请稍后..."
|
binding.hint.text = "拍照中,请稍后..."
|
||||||
}
|
}
|
||||||
@ -158,24 +183,8 @@ class SprayingOCRActivity :
|
|||||||
return@runOnUiThread
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
binding.content.setImageBitmap(bitmap)
|
binding.content.setImageBitmap(bitmap)
|
||||||
restartResultCountdown(path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restartResultCountdown(path: String) {
|
|
||||||
resultCountdown?.cancel()
|
|
||||||
resultCountdown = object : CountDownTimer(5_000, 1_000) {
|
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinish() {
|
|
||||||
startActivity(Intent(this@SprayingOCRActivity, SprayingResultActivity::class.java).apply {
|
|
||||||
putExtra("path", path)
|
|
||||||
})
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
package com.nova.brain.glass.ui
|
package com.nova.brain.glass.ui
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.view.doOnLayout
|
import androidx.core.view.doOnLayout
|
||||||
@ -16,6 +20,7 @@ import com.nova.brain.glass.helper.OfflineCmdListener
|
|||||||
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
|
||||||
import com.nova.brain.glass.helper.SprayingPhotoManager
|
import com.nova.brain.glass.helper.SprayingPhotoManager
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
import com.nova.brain.glass.viewmodel.SubmitTaskState
|
||||||
import com.nova.brain.glass.viewmodel.SprayingResultVM
|
import com.nova.brain.glass.viewmodel.SprayingResultVM
|
||||||
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
import com.rokid.security.glass3.sdk.base.data.media.PhotoResolution
|
||||||
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
import com.rokid.security.system.server.media.callback.PhotoFileCallback
|
||||||
@ -35,8 +40,15 @@ class SprayingResultActivity :
|
|||||||
override fun fullscreen(): Boolean = true
|
override fun fullscreen(): Boolean = true
|
||||||
|
|
||||||
override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL
|
override fun getRecyclerOrientation(): Int = RecyclerView.HORIZONTAL
|
||||||
|
private val taskId: String by lazy {
|
||||||
|
intent.getStringExtra("taskId")
|
||||||
|
.orEmpty()
|
||||||
|
.ifBlank { "1493291302287048704" }
|
||||||
|
}
|
||||||
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
private val imageDecodeExecutor = Executors.newSingleThreadExecutor()
|
||||||
private var status = true
|
private var status = true
|
||||||
|
private var successDialog: AlertDialog? = null
|
||||||
|
private val uiHandler = Handler(Looper.getMainLooper())
|
||||||
private val manualResultLauncher =
|
private val manualResultLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
if (result.resultCode != Activity.RESULT_OK) {
|
if (result.resultCode != Activity.RESULT_OK) {
|
||||||
@ -69,11 +81,7 @@ class SprayingResultActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
SprayingFinishActivity.ACTION_SUBMIT -> {
|
SprayingFinishActivity.ACTION_SUBMIT -> {
|
||||||
SprayingPhotoManager.clear()
|
viewModel.submitTask(taskId)
|
||||||
startActivity(Intent(this, TaskListActivity::class.java).apply {
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
||||||
})
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,6 +159,7 @@ class SprayingResultActivity :
|
|||||||
this@SprayingResultActivity, SprayingOCRActivity::class.java
|
this@SprayingResultActivity, SprayingOCRActivity::class.java
|
||||||
).apply {
|
).apply {
|
||||||
putExtra("path", path)
|
putExtra("path", path)
|
||||||
|
putExtra("taskId", taskId)
|
||||||
})
|
})
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
@ -161,6 +170,27 @@ class SprayingResultActivity :
|
|||||||
override fun initData() {
|
override fun initData() {
|
||||||
super.initData()
|
super.initData()
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
viewModel.submitTaskState.observe(this) { state ->
|
||||||
|
when (state) {
|
||||||
|
SubmitTaskState.LOADING -> {
|
||||||
|
binding.hint.text = "提交中,请稍后..."
|
||||||
|
}
|
||||||
|
SubmitTaskState.SUCCESS -> {
|
||||||
|
viewModel.resetSubmitTaskState()
|
||||||
|
showSuccessDialogThenBackToTaskList()
|
||||||
|
}
|
||||||
|
SubmitTaskState.FAILED -> {
|
||||||
|
binding.hint.text = "单击或语音输入“结束任务”,进入任务确认"
|
||||||
|
viewModel.resetSubmitTaskState()
|
||||||
|
}
|
||||||
|
SubmitTaskState.IDLE -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewModel.submitTaskError.observe(this) { message ->
|
||||||
|
if (message.isNotBlank()) {
|
||||||
|
message.showMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
intent.getStringExtra("path")?.apply {
|
intent.getStringExtra("path")?.apply {
|
||||||
showResultImage(this)
|
showResultImage(this)
|
||||||
setStatusImage()
|
setStatusImage()
|
||||||
@ -197,6 +227,8 @@ class SprayingResultActivity :
|
|||||||
GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
|
GlassMediaServiceHelper.removePhotoCallback(mPhotoFileCallback)
|
||||||
}
|
}
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
uiHandler.removeCallbacksAndMessages(null)
|
||||||
|
successDialog?.dismiss()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
binding.iv.setImageDrawable(null)
|
binding.iv.setImageDrawable(null)
|
||||||
}
|
}
|
||||||
@ -255,4 +287,26 @@ class SprayingResultActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showSuccessDialogThenBackToTaskList() {
|
||||||
|
successDialog?.dismiss()
|
||||||
|
val contentView = LayoutInflater.from(this).inflate(R.layout.dialog_review, null)
|
||||||
|
successDialog = AlertDialog.Builder(this)
|
||||||
|
.setView(contentView)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
.also { dialog ->
|
||||||
|
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
uiHandler.postDelayed({
|
||||||
|
successDialog?.dismiss()
|
||||||
|
successDialog = null
|
||||||
|
SprayingPhotoManager.clear()
|
||||||
|
startActivity(Intent(this, TaskListActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||||
|
})
|
||||||
|
finish()
|
||||||
|
}, 1000L)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,34 @@
|
|||||||
package com.nova.brain.glass.viewmodel
|
package com.nova.brain.glass.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.nova.brain.glass.MyApplication
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
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.BaseListViewModel
|
||||||
import com.xuqm.base.viewmodel.callback.Response
|
import com.xuqm.base.viewmodel.callback.Response
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import java.io.File
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
|
||||||
|
enum class UploadState {
|
||||||
|
IDLE,
|
||||||
|
UPLOADING,
|
||||||
|
SUCCESS,
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
|
|
||||||
class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
||||||
|
val uploadState = MutableLiveData(UploadState.IDLE)
|
||||||
|
val uploadError = MutableLiveData<String>()
|
||||||
|
val uploadSuccessPath = MutableLiveData<String?>()
|
||||||
|
private var uploadingPath: String? = null
|
||||||
|
private var uploadDisposable: Disposable? = null
|
||||||
|
|
||||||
override fun loadData(
|
override fun loadData(
|
||||||
page: Int,
|
page: Int,
|
||||||
onResponse: Response<ItemItem>
|
onResponse: Response<ItemItem>
|
||||||
@ -13,4 +37,47 @@ class SprayingOCRVM: BaseListViewModel<ItemItem>() {
|
|||||||
add(ItemItem("重拍"))
|
add(ItemItem("重拍"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startUpload(path: String) {
|
||||||
|
cancelUpload()
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists() || !file.isFile) {
|
||||||
|
uploadState.value = UploadState.FAILED
|
||||||
|
uploadError.value = "附件上传失败"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadingPath = path
|
||||||
|
uploadState.value = UploadState.UPLOADING
|
||||||
|
val requestFile = file.asRequestBody("application/octet-stream".toMediaTypeOrNull())
|
||||||
|
val multipartFile = MultipartBody.Part.createFormData("multipartFile", file.name, requestFile)
|
||||||
|
val disposable = HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||||
|
.batchUpload(multipartFile)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
if (uploadingPath != path) return@subscribe
|
||||||
|
uploadState.value = UploadState.SUCCESS
|
||||||
|
uploadSuccessPath.value = path
|
||||||
|
}, { e ->
|
||||||
|
if (uploadingPath != path) return@subscribe
|
||||||
|
uploadState.value = UploadState.FAILED
|
||||||
|
uploadError.value = e.message ?: "附件上传失败"
|
||||||
|
})
|
||||||
|
uploadDisposable = disposable
|
||||||
|
add(disposable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelUpload() {
|
||||||
|
uploadingPath = null
|
||||||
|
uploadDisposable?.dispose()
|
||||||
|
uploadDisposable = null
|
||||||
|
if (uploadState.value == UploadState.UPLOADING) {
|
||||||
|
uploadState.value = UploadState.IDLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearUploadSuccessPath() {
|
||||||
|
uploadSuccessPath.value = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,27 @@
|
|||||||
package com.nova.brain.glass.viewmodel
|
package com.nova.brain.glass.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.nova.brain.glass.MyApplication
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
import com.nova.brain.glass.model.data.SubmitTaskRequest
|
||||||
|
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.BaseListViewModel
|
||||||
import com.xuqm.base.viewmodel.callback.Response
|
import com.xuqm.base.viewmodel.callback.Response
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
enum class SubmitTaskState {
|
||||||
|
IDLE,
|
||||||
|
LOADING,
|
||||||
|
SUCCESS,
|
||||||
|
FAILED
|
||||||
|
}
|
||||||
|
|
||||||
class SprayingResultVM: BaseListViewModel<ItemItem>() {
|
class SprayingResultVM: BaseListViewModel<ItemItem>() {
|
||||||
|
val submitTaskState = MutableLiveData(SubmitTaskState.IDLE)
|
||||||
|
val submitTaskError = MutableLiveData<String>()
|
||||||
|
|
||||||
override fun loadData(
|
override fun loadData(
|
||||||
page: Int,
|
page: Int,
|
||||||
onResponse: Response<ItemItem>
|
onResponse: Response<ItemItem>
|
||||||
@ -15,4 +32,36 @@ class SprayingResultVM: BaseListViewModel<ItemItem>() {
|
|||||||
add(ItemItem("人工更正结果"))
|
add(ItemItem("人工更正结果"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun submitTask(taskId: String) {
|
||||||
|
if (taskId.isBlank()) {
|
||||||
|
submitTaskState.value = SubmitTaskState.FAILED
|
||||||
|
submitTaskError.value = "缺少任务ID,无法提交"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (submitTaskState.value == SubmitTaskState.LOADING) return
|
||||||
|
submitTaskState.value = SubmitTaskState.LOADING
|
||||||
|
add(
|
||||||
|
HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||||
|
.submitTask(SubmitTaskRequest(id = taskId))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ response ->
|
||||||
|
if (response.code == 200) {
|
||||||
|
submitTaskState.value = SubmitTaskState.SUCCESS
|
||||||
|
} else {
|
||||||
|
submitTaskState.value = SubmitTaskState.FAILED
|
||||||
|
submitTaskError.value =
|
||||||
|
if (response.message.isBlank()) "提交失败" else response.message
|
||||||
|
}
|
||||||
|
}, { e ->
|
||||||
|
submitTaskState.value = SubmitTaskState.FAILED
|
||||||
|
submitTaskError.value = e.message ?: "提交失败"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetSubmitTaskState() {
|
||||||
|
submitTaskState.value = SubmitTaskState.IDLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,28 @@
|
|||||||
package com.nova.brain.glass.viewmodel
|
package com.nova.brain.glass.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.nova.brain.glass.MyApplication
|
||||||
import com.nova.brain.glass.model.ItemItem
|
import com.nova.brain.glass.model.ItemItem
|
||||||
|
import com.nova.brain.glass.model.data.GetTaskInfoRequest
|
||||||
|
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.BaseListViewModel
|
||||||
import com.xuqm.base.viewmodel.callback.Response
|
import com.xuqm.base.viewmodel.callback.Response
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
data class SprayingTaskUiData(
|
||||||
|
val taskCount: Int,
|
||||||
|
val itemName: String,
|
||||||
|
val aoNumber: String,
|
||||||
|
val productionInfoId: String,
|
||||||
|
val frameTime: String
|
||||||
|
)
|
||||||
|
|
||||||
class SprayingVM: BaseListViewModel<ItemItem>() {
|
class SprayingVM: BaseListViewModel<ItemItem>() {
|
||||||
|
val taskInfo = MutableLiveData<SprayingTaskUiData>()
|
||||||
|
val taskInfoError = MutableLiveData<String>()
|
||||||
|
|
||||||
override fun loadData(
|
override fun loadData(
|
||||||
page: Int,
|
page: Int,
|
||||||
onResponse: Response<ItemItem>
|
onResponse: Response<ItemItem>
|
||||||
@ -13,4 +31,33 @@ class SprayingVM: BaseListViewModel<ItemItem>() {
|
|||||||
add(ItemItem("开始任务"))
|
add(ItemItem("开始任务"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fetchTaskInfo(taskId: String) {
|
||||||
|
if (taskId.isBlank()) return
|
||||||
|
add(
|
||||||
|
HttpManager.getApi(MyApplication.appComponent2, Service::class.java)
|
||||||
|
.getTaskInfo(GetTaskInfoRequest(id = taskId))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ response ->
|
||||||
|
if (response.code == 200) {
|
||||||
|
val taskInfo = response.data
|
||||||
|
val formList = taskInfo?.productionFormDtoList.orEmpty()
|
||||||
|
val firstForm = formList.firstOrNull()
|
||||||
|
this.taskInfo.value = SprayingTaskUiData(
|
||||||
|
taskCount = formList.size,
|
||||||
|
itemName = firstForm?.itemName.orEmpty(),
|
||||||
|
aoNumber = taskInfo?.aoNumber.orEmpty(),
|
||||||
|
productionInfoId = taskInfo?.productionInfoId.orEmpty(),
|
||||||
|
frameTime = taskInfo?.frameTime.orEmpty()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
taskInfoError.value =
|
||||||
|
if (response.message.isBlank()) "任务信息获取失败" else response.message
|
||||||
|
}
|
||||||
|
}, { e ->
|
||||||
|
taskInfoError.value = e.message ?: "任务信息获取失败"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
正在加载...
在新工单中引用
屏蔽一个用户