相机优化、对接识别名称搜索新接口、替换模型文件
This commit is contained in:
Binary file not shown.
@@ -1,38 +1,44 @@
|
||||
{
|
||||
"class_names": [
|
||||
"上海青",
|
||||
"土豆",
|
||||
"胡萝卜",
|
||||
"芹菜",
|
||||
"茄子",
|
||||
"蒜苔",
|
||||
"西红柿",
|
||||
"青椒",
|
||||
"黄瓜"
|
||||
"小白菜",
|
||||
"番茄[西红柿]",
|
||||
"胡萝卜(红)[金笋,丁香萝卜]",
|
||||
"芹菜(茎)[旱芹,药芹]",
|
||||
"茄子(代表值)",
|
||||
"蒜薹(带帽)",
|
||||
"西兰花[绿菜花]",
|
||||
"辣椒(青,尖)",
|
||||
"韭菜",
|
||||
"马铃薯[土豆、洋芋]",
|
||||
"黄瓜(鲜)[胡瓜]"
|
||||
],
|
||||
"class_to_idx": {
|
||||
"上海青": 0,
|
||||
"土豆": 1,
|
||||
"胡萝卜": 2,
|
||||
"芹菜": 3,
|
||||
"茄子": 4,
|
||||
"蒜苔": 5,
|
||||
"西红柿": 6,
|
||||
"青椒": 7,
|
||||
"黄瓜": 8
|
||||
"小白菜": 0,
|
||||
"番茄[西红柿]": 1,
|
||||
"胡萝卜(红)[金笋,丁香萝卜]": 2,
|
||||
"芹菜(茎)[旱芹,药芹]": 3,
|
||||
"茄子(代表值)": 4,
|
||||
"蒜薹(带帽)": 5,
|
||||
"西兰花[绿菜花]": 6,
|
||||
"辣椒(青,尖)": 7,
|
||||
"韭菜": 8,
|
||||
"马铃薯[土豆、洋芋]": 9,
|
||||
"黄瓜(鲜)[胡瓜]": 10
|
||||
},
|
||||
"idx_to_class": {
|
||||
"0": "上海青",
|
||||
"1": "土豆",
|
||||
"2": "胡萝卜",
|
||||
"3": "芹菜",
|
||||
"4": "茄子",
|
||||
"5": "蒜苔",
|
||||
"6": "西红柿",
|
||||
"7": "青椒",
|
||||
"8": "黄瓜"
|
||||
"0": "小白菜",
|
||||
"1": "番茄[西红柿]",
|
||||
"2": "胡萝卜(红)[金笋,丁香萝卜]",
|
||||
"3": "芹菜(茎)[旱芹,药芹]",
|
||||
"4": "茄子(代表值)",
|
||||
"5": "蒜薹(带帽)",
|
||||
"6": "西兰花[绿菜花]",
|
||||
"7": "辣椒(青,尖)",
|
||||
"8": "韭菜",
|
||||
"9": "马铃薯[土豆、洋芋]",
|
||||
"10": "黄瓜(鲜)[胡瓜]"
|
||||
},
|
||||
"embedding_dim": 512,
|
||||
"total_images": 450,
|
||||
"build_time": "2025-10-21T10:14:29.510882"
|
||||
"total_images": 550,
|
||||
"build_time": "2025-10-30T14:41:07.359332"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
|
||||
@@ -7,13 +7,8 @@ import android.text.style.ForegroundColorSpan
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.viewModels
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.view.CameraController
|
||||
import androidx.camera.view.LifecycleCameraController
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.core.graphics.toColorInt
|
||||
import androidx.core.view.postDelayed
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.shuwei.intelligent.shelves.utils.ext.appendText
|
||||
import com.shuwei.intelligent.shelves.utils.ext.buildSpannableString
|
||||
@@ -36,8 +31,8 @@ import com.sw.inbound.objbox.FoodModule
|
||||
import com.sw.inbound.sdk.SensorScaleUtils
|
||||
import com.sw.inbound.utils.BitmapCropper
|
||||
import com.sw.inbound.utils.BitmapSaver
|
||||
import com.sw.inbound.utils.CameraUtils
|
||||
import com.sw.inbound.utils.ImageUtil
|
||||
import com.sw.inbound.utils.PhotoCaptureHelper
|
||||
import com.sw.inbound.utils.ext.dp
|
||||
import com.sw.inbound.utils.ext.gone
|
||||
import com.sw.inbound.utils.ext.toJsonString
|
||||
@@ -46,6 +41,7 @@ import com.sw.inbound.viewmodel.ReceiptViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import kotlin.math.min
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -75,6 +71,10 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
private lateinit var backPressedCallback: OnBackPressedCallback
|
||||
private lateinit var previewView: PreviewView
|
||||
|
||||
private val cameraUtils: CameraUtils by lazy {
|
||||
CameraUtils(this@GoodsListActivity)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityGoodsListBinding.inflate(layoutInflater)
|
||||
@@ -84,7 +84,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
isNewReceipt = intent.getBooleanExtra(IS_NEW_RECEIPT, false)
|
||||
id = intent.getStringExtra(ID) ?: ""
|
||||
supplierId = intent.getStringExtra(SUPPLIER_ID) ?: ""
|
||||
initCamera()
|
||||
cameraUtils.initCamera()
|
||||
replaceIncludeContent()
|
||||
initRecyclerView()
|
||||
initView()
|
||||
@@ -131,7 +131,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
height = 1
|
||||
}
|
||||
}
|
||||
setPreviewController(previewView)
|
||||
cameraUtils.setPreviewController(previewView)
|
||||
|
||||
//viewModel.startSensorScale()
|
||||
binding.root.postDelayed({
|
||||
@@ -151,10 +151,6 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
if (weight < 200) {
|
||||
return
|
||||
}
|
||||
if (isShowRecognizeDialog.not()) {
|
||||
return
|
||||
}
|
||||
isShowRecognizeDialog = false
|
||||
runOnUiThread {
|
||||
recognizeFood()
|
||||
}
|
||||
@@ -167,7 +163,12 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
fun recognizeFood() {
|
||||
takePhoto(takePhotoSuccessCallback)
|
||||
if (isShowRecognizeDialog.not()) {
|
||||
return
|
||||
}
|
||||
isShowRecognizeDialog = false
|
||||
bindCamera()
|
||||
cameraUtils.takePhoto(takePhotoSuccessCallback)
|
||||
}
|
||||
|
||||
private var dropdownPopup: DropdownPopup? = null
|
||||
@@ -196,20 +197,23 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
)
|
||||
Timber.d("${this.javaClass.simpleName}-searchFood-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
val foodNameList = FoodModule.queryFood(newBmp)
|
||||
searchMultipleGoods(foodNameList) { goodsList ->
|
||||
//if (goodsList.size != foodNameList.size) {
|
||||
// toast("系统异常,请稍后重试!!!")
|
||||
// return@searchMultipleGoods
|
||||
//}
|
||||
viewModel.recognizeGoodsList(foodNameList) { goodsList ->
|
||||
handleGoodsResult(
|
||||
if (goodsList.size == foodNameList.size) goodsList
|
||||
else mutableListOf()
|
||||
goodsList = if (goodsList.size == foodNameList.size) goodsList else mutableListOf(),
|
||||
file = file,
|
||||
name = foodNameList.joinToString(",")
|
||||
)
|
||||
}
|
||||
// searchMultipleGoods(foodNameList) { goodsList ->
|
||||
// handleGoodsResult(
|
||||
// if (goodsList.size == foodNameList.size) goodsList
|
||||
// else mutableListOf()
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleGoodsResult(goodsList: MutableList<SearchGoodsInfo.Record>) {
|
||||
private fun handleGoodsResult(goodsList: List<SearchGoodsInfo.Record>, file: File?, name: String) {
|
||||
runOnUiThread {
|
||||
if (goodsRecognizeDialog?.isShowing == true) {
|
||||
isShowRecognizeDialog = false
|
||||
@@ -217,7 +221,9 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
}
|
||||
goodsRecognizeDialog = GoodsRecognizeDialog(
|
||||
context = this,
|
||||
list = goodsList
|
||||
list = goodsList.toMutableList(),
|
||||
goodsFile = file,
|
||||
goodsName = name
|
||||
) {
|
||||
GoodsSearchDialog(this).show()
|
||||
}.apply {
|
||||
@@ -237,61 +243,6 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
|
||||
private var goodsRecognizeDialog: GoodsRecognizeDialog? = null
|
||||
|
||||
private var cameraController: LifecycleCameraController? = null
|
||||
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
||||
private var isCameraReady = false
|
||||
fun takePhoto(callback: (Uri) -> Unit) {
|
||||
cameraController?.let {
|
||||
if (photoCaptureHelper == null) {
|
||||
initCaptureHelper()
|
||||
}
|
||||
}
|
||||
photoCaptureHelper?.let {
|
||||
it.addSuccessCallback(callback)
|
||||
it.takePhoto()
|
||||
}
|
||||
}
|
||||
|
||||
fun initCaptureHelper() {
|
||||
photoCaptureHelper = PhotoCaptureHelper(
|
||||
context = this,
|
||||
cameraController = cameraController!!,
|
||||
onSuccess = {},
|
||||
onError = { msg ->
|
||||
//toast(msg)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun setPreviewController(previewView: PreviewView?) {
|
||||
previewView?.controller = cameraController
|
||||
}
|
||||
|
||||
fun initCamera() {
|
||||
if (cameraController == null) {
|
||||
cameraController = LifecycleCameraController(this).apply {
|
||||
// 必须设置有效的用例
|
||||
setEnabledUseCases(
|
||||
CameraController.IMAGE_CAPTURE or
|
||||
CameraController.VIDEO_CAPTURE
|
||||
)
|
||||
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
}
|
||||
cameraController?.bindToLifecycle(this)
|
||||
}
|
||||
|
||||
// if (isCameraReady.not()) {
|
||||
// try {
|
||||
// cameraController!!.initializationFuture.addListener({
|
||||
// isCameraReady = true
|
||||
// Timber.d("Camera initialized successfully")
|
||||
// }, ContextCompat.getMainExecutor(this))
|
||||
// } catch (e: Exception) {
|
||||
// Timber.d("Camera initialized error = ${e.message}")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private fun replaceIncludeContent() {
|
||||
binding.flContainer.removeAllViews()
|
||||
if (isReceiptPage) {
|
||||
@@ -305,10 +256,23 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
unBindCamera()
|
||||
}
|
||||
|
||||
fun bindCamera() {
|
||||
cameraUtils.bind()
|
||||
}
|
||||
|
||||
fun unBindCamera() {
|
||||
cameraUtils.unbind()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
cameraController?.unbind()
|
||||
isCameraReady = false
|
||||
//cameraController?.unbind()
|
||||
//isCameraReady = false
|
||||
}
|
||||
|
||||
fun addGoods(it: GoodsInfo) {
|
||||
@@ -396,6 +360,10 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
goodsInfo.warehouseName = binding.tvWareHouse.text.toString()
|
||||
}
|
||||
}
|
||||
if (submitData.isEmpty()) {
|
||||
toast("请选择收货物品")
|
||||
return
|
||||
}
|
||||
val uploadInfo = UploadInfo(
|
||||
id = id,
|
||||
supplierId = supplierId,
|
||||
@@ -463,7 +431,4 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
viewModel.createNewGoods(param = param, callback = callback)
|
||||
}
|
||||
}
|
||||
|
||||
private var preview: Preview? = null
|
||||
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import com.sw.inbound.ext.toSafeBigDecimal
|
||||
import com.sw.inbound.ext.toSafeFloat
|
||||
import com.sw.inbound.model.request.GoodsAddParam
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.utils.CameraUtils
|
||||
import com.sw.inbound.utils.ext.dp
|
||||
import com.sw.inbound.utils.ext.gone
|
||||
import com.sw.inbound.utils.ext.toast
|
||||
@@ -40,13 +41,16 @@ class AddGoodsDialog(
|
||||
|
||||
private val dropdownList: MutableList<DictType> = mutableListOf()
|
||||
private var activity: GoodsListActivity? = null
|
||||
|
||||
private val cameraUtils: CameraUtils by lazy {
|
||||
CameraUtils(activity!!)
|
||||
}
|
||||
override fun show() {
|
||||
super.show()
|
||||
|
||||
cameraUtils.setPreviewController(previewView)
|
||||
cameraUtils.bind()
|
||||
window?.decorView?.postDelayed({
|
||||
activity?.setPreviewController(previewView)
|
||||
}, 600)
|
||||
binding.llCameraFlag.gone()
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private val takePhotoCallback: (Uri) -> Unit = { uri ->
|
||||
@@ -59,6 +63,11 @@ class AddGoodsDialog(
|
||||
private lateinit var previewView: PreviewView
|
||||
override fun initView() {
|
||||
activity = getReceiptActivity()
|
||||
activity?.unBindCamera()
|
||||
setOnDismissListener {
|
||||
cameraUtils.unbind()
|
||||
}
|
||||
cameraUtils.initCamera()
|
||||
val previewBinding =
|
||||
LayoutCameraPreviewBinding.inflate(LayoutInflater.from(context), binding.flCameraPreview)
|
||||
previewBinding.previewView.let {
|
||||
@@ -84,7 +93,7 @@ class AddGoodsDialog(
|
||||
binding.flCameraPreview.visible()
|
||||
}
|
||||
binding.btnTakePhoto.setOnClickListener {
|
||||
activity?.takePhoto(takePhotoCallback)
|
||||
cameraUtils.takePhoto(takePhotoCallback)
|
||||
}
|
||||
binding.btnUploadImg.gone()
|
||||
binding.btnUploadImg.setOnClickListener {
|
||||
|
||||
@@ -5,15 +5,19 @@ import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import coil.load
|
||||
import com.sw.inbound.activity.GoodsListActivity
|
||||
import com.sw.inbound.adapter.RecognizeAdapter
|
||||
import com.sw.inbound.databinding.DialogGoodsRecognizeBinding
|
||||
import com.sw.inbound.databinding.LayoutEmptyRecognizeBinding
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
import java.io.File
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
class GoodsRecognizeDialog(
|
||||
context: Context,
|
||||
var goodsFile: File?=null,
|
||||
var goodsName: String?=null,
|
||||
var list: MutableList<SearchGoodsInfo.Record>,
|
||||
var findGoods: () -> Unit
|
||||
) : BaseDialog(context) {
|
||||
@@ -26,6 +30,12 @@ class GoodsRecognizeDialog(
|
||||
return binding.root
|
||||
}
|
||||
|
||||
// override fun show() {
|
||||
// super.show()
|
||||
// binding.ivGoods.load(goodsFile)
|
||||
// binding.tvGoods.text = goodsName
|
||||
// }
|
||||
|
||||
private val recognizeAdapter by lazy {
|
||||
RecognizeAdapter(list).apply {
|
||||
isStateViewEnable = true
|
||||
|
||||
@@ -47,7 +47,12 @@ class GoodsSearchDialog(
|
||||
binding.etInputGoods.setText(goodsName)
|
||||
searchGoods()
|
||||
}
|
||||
).show()
|
||||
).apply {
|
||||
setOnDismissListener {
|
||||
//activity?.bindCamera()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
binding.btnConfirm.setOnClickListener {
|
||||
if (list.isEmpty()) {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.sw.inbound.model.response
|
||||
|
||||
data class RecGoodsName(
|
||||
var nameList: List<String>
|
||||
)
|
||||
@@ -11,13 +11,12 @@ import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.model.response.GoodsType
|
||||
import com.sw.inbound.model.response.PurchaseInfo
|
||||
import com.sw.inbound.model.response.RecGoodsName
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
import com.sw.inbound.model.response.StorageType
|
||||
import com.sw.inbound.model.response.SupplierInfo
|
||||
import com.sw.inbound.model.response.SupplierResponse
|
||||
import com.sw.inbound.model.response.User
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
@@ -162,11 +161,17 @@ interface ApiService {
|
||||
suspend fun searchGoodsInfoList(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}${apiPrefix}/pad/goodsInfoList",
|
||||
@Body param:Map<String, String>
|
||||
// @Query("goodsName") goodsName: String,
|
||||
// @Query("pageNum" ) pageNo: Int,
|
||||
// @Query("pageSize" ) pageSize: Int,
|
||||
): ApiResponse<SearchGoodsInfo>
|
||||
|
||||
/**
|
||||
* 物品列表(识别图片后根据名称查询,名称支持多个)
|
||||
*/
|
||||
@POST
|
||||
suspend fun recognizeGoodsList(
|
||||
@Url url: String = "${GlobalData.appBaseUrl}${apiPrefix}/pad/goodsList",
|
||||
@Body recGoodsName: RecGoodsName
|
||||
): ApiResponse<List<SearchGoodsInfo.Record>>
|
||||
|
||||
/**
|
||||
* 自采添加商品
|
||||
*/
|
||||
|
||||
@@ -33,9 +33,9 @@ object FoodModule {
|
||||
Thread {
|
||||
module_mobile = Module.load(copyAssetToCache(context, "best_embedding_model_mobile.pt"))
|
||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
||||
// if (box.all.isNotEmpty()) {
|
||||
// box.removeAll()
|
||||
// }
|
||||
if (box.all.isNotEmpty()) {
|
||||
box.removeAll()
|
||||
}
|
||||
if (box.all.isEmpty()) {
|
||||
initFoodData(context)
|
||||
}
|
||||
|
||||
@@ -11,16 +11,14 @@ import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.EquipmentInfo
|
||||
import com.sw.inbound.model.response.GoodsType
|
||||
import com.sw.inbound.model.response.PurchaseInfo
|
||||
import com.sw.inbound.model.response.RecGoodsName
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
import com.sw.inbound.model.response.StorageType
|
||||
import com.sw.inbound.model.response.SupplierInfo
|
||||
import com.sw.inbound.model.response.SupplierResponse
|
||||
import com.sw.inbound.model.response.User
|
||||
import com.sw.inbound.network.api.ApiService
|
||||
import com.sw.inbound.utils.ContextUtils
|
||||
import com.sw.inbound.utils.FileUtils
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -162,6 +160,12 @@ class RemoteRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun recognizeGoodsList(nameList: List<String>): ApiResponse<List<SearchGoodsInfo.Record>> {
|
||||
return safeApiCall {
|
||||
apiService.recognizeGoodsList(recGoodsName = RecGoodsName(nameList))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自采购-添加商品
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.sw.inbound.utils
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.view.CameraController
|
||||
import androidx.camera.view.LifecycleCameraController
|
||||
import androidx.camera.view.PreviewView
|
||||
import com.sw.inbound.activity.GoodsListActivity
|
||||
|
||||
class CameraUtils(private var activity: GoodsListActivity) {
|
||||
|
||||
private var cameraController: LifecycleCameraController? = null
|
||||
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
||||
// private var isCameraReady = false
|
||||
fun takePhoto(callback: (Uri) -> Unit) {
|
||||
cameraController?.let {
|
||||
if (photoCaptureHelper == null) {
|
||||
initCaptureHelper()
|
||||
}
|
||||
}
|
||||
photoCaptureHelper?.let {
|
||||
it.addSuccessCallback(callback)
|
||||
it.takePhoto()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initCaptureHelper() {
|
||||
photoCaptureHelper = PhotoCaptureHelper(
|
||||
context = activity,
|
||||
cameraController = cameraController!!,
|
||||
onSuccess = {},
|
||||
onError = { msg ->
|
||||
//toast(msg)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun setPreviewController(previewView: PreviewView?) {
|
||||
if (previewView?.controller == null) {
|
||||
previewView?.controller = cameraController
|
||||
}
|
||||
}
|
||||
|
||||
fun initCamera() {
|
||||
if (cameraController == null) {
|
||||
cameraController = LifecycleCameraController(activity).apply {
|
||||
// 必须设置有效的用例
|
||||
setEnabledUseCases(
|
||||
CameraController.IMAGE_CAPTURE
|
||||
// or CameraController.VIDEO_CAPTURE
|
||||
)
|
||||
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
}
|
||||
//cameraController?.bindToLifecycle(activity)
|
||||
}
|
||||
|
||||
// if (isCameraReady.not()) {
|
||||
// try {
|
||||
// cameraController!!.initializationFuture.addListener({
|
||||
// isCameraReady = true
|
||||
// Timber.d("Camera initialized successfully")
|
||||
// }, ContextCompat.getMainExecutor(this))
|
||||
// } catch (e: Exception) {
|
||||
// Timber.d("Camera initialized error = ${e.message}")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fun bind() {
|
||||
cameraController?.bindToLifecycle(activity)
|
||||
}
|
||||
fun unbind() {
|
||||
cameraController?.unbind()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -148,27 +148,27 @@ abstract class BaseViewModel(
|
||||
/**
|
||||
* 获取识别列表
|
||||
*/
|
||||
fun getIdentityList(photoUri: Uri) {
|
||||
Timber.d("getIdentityList")
|
||||
launchWithLoading {
|
||||
_searchListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
// 有收货列表,则返回收货列表
|
||||
if (_receiptList.value.isNotEmpty()) {
|
||||
_identityListItems.value = _receiptList.value
|
||||
if (_identityListItems.value.isNotEmpty()) {
|
||||
handleIdentityItem(_identityListItems.value[0])
|
||||
}
|
||||
} else {
|
||||
val response = repository.searchGoodsInfoList("", 1, 10)
|
||||
if (parseResponse(response)) {
|
||||
_identityListItems.value = response.result?.records ?: emptyList()
|
||||
if (_identityListItems.value.isNotEmpty()) {
|
||||
handleIdentityItem(_identityListItems.value[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fun getIdentityList(photoUri: Uri) {
|
||||
// Timber.d("getIdentityList")
|
||||
// launchWithLoading {
|
||||
// _searchListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
// // 有收货列表,则返回收货列表
|
||||
// if (_receiptList.value.isNotEmpty()) {
|
||||
// _identityListItems.value = _receiptList.value
|
||||
// if (_identityListItems.value.isNotEmpty()) {
|
||||
// handleIdentityItem(_identityListItems.value[0])
|
||||
// }
|
||||
// } else {
|
||||
// val response = repository.searchGoodsInfoList("", 1, 10)
|
||||
// if (parseResponse(response)) {
|
||||
// _identityListItems.value = response.result?.records ?: emptyList()
|
||||
// if (_identityListItems.value.isNotEmpty()) {
|
||||
// handleIdentityItem(_identityListItems.value[0])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 处理识别后要选中的值
|
||||
@@ -190,43 +190,54 @@ abstract class BaseViewModel(
|
||||
): List<SearchGoodsInfo.Record> {
|
||||
val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize)
|
||||
return if (parseResponse(response)) {
|
||||
response.result?.records ?: mutableListOf()
|
||||
response.result?.records ?: listOf()
|
||||
} else {
|
||||
mutableListOf()
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
|
||||
fun searchGoodsInfoList(
|
||||
goodsName: String,
|
||||
pageNo: Int = 1,
|
||||
pageSize: Int = 10,
|
||||
searchCallback: ((pageNo: Int, List<SearchGoodsInfo.Record>) -> Unit)? = null
|
||||
fun recognizeGoodsList(
|
||||
nameList: List<String>,
|
||||
callback: (List<SearchGoodsInfo.Record>) -> Unit
|
||||
) {
|
||||
launch {
|
||||
if (pageNo > 1) {
|
||||
_isMoreLoading.value = true
|
||||
}
|
||||
_identityListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize)
|
||||
_isMoreLoading.value = false
|
||||
if (parseResponse(response)) {
|
||||
val data = response.result
|
||||
data?.records?.let {
|
||||
_canLoadMore.value = data.records.size >= pageSize
|
||||
if (pageNo > 1) {
|
||||
_searchListItems.value = _searchListItems.value + data.records
|
||||
} else {
|
||||
_searchListItems.value = data.records
|
||||
}
|
||||
searchCallback?.invoke(pageNo, _searchListItems.value)
|
||||
}
|
||||
} else {
|
||||
_searchListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
searchCallback?.invoke(pageNo, _searchListItems.value)
|
||||
}
|
||||
val response = repository.recognizeGoodsList(nameList)
|
||||
val list = if (parseResponse(response)) response.data?:listOf() else listOf()
|
||||
callback(list)
|
||||
}
|
||||
}
|
||||
|
||||
// fun searchGoodsInfoList(
|
||||
// goodsName: String,
|
||||
// pageNo: Int = 1,
|
||||
// pageSize: Int = 10,
|
||||
// searchCallback: ((pageNo: Int, List<SearchGoodsInfo.Record>) -> Unit)? = null
|
||||
// ) {
|
||||
// launch {
|
||||
// if (pageNo > 1) {
|
||||
// _isMoreLoading.value = true
|
||||
// }
|
||||
// _identityListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
// val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize)
|
||||
// _isMoreLoading.value = false
|
||||
// if (parseResponse(response)) {
|
||||
// val data = response.result
|
||||
// data?.records?.let {
|
||||
// _canLoadMore.value = data.records.size >= pageSize
|
||||
// if (pageNo > 1) {
|
||||
// _searchListItems.value = _searchListItems.value + data.records
|
||||
// } else {
|
||||
// _searchListItems.value = data.records
|
||||
// }
|
||||
// searchCallback?.invoke(pageNo, _searchListItems.value)
|
||||
// }
|
||||
// } else {
|
||||
// _searchListItems.value = emptyList<SearchGoodsInfo.Record>()
|
||||
// searchCallback?.invoke(pageNo, _searchListItems.value)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fun getDictType() {
|
||||
Timber.d("获取所有字典列表")
|
||||
launchWithLoading {
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flCameraPreview"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp" />
|
||||
|
||||
<Space
|
||||
|
||||
@@ -40,37 +40,13 @@
|
||||
app:layout_constraintTop_toTopOf="@+id/llGoodsInfo"
|
||||
android:background="@drawable/bg_white_radius10_stroke2_dash">
|
||||
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:id="@+id/llStartPreview"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_gravity="center"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:orientation="vertical"-->
|
||||
<!-- android:visibility="gone">-->
|
||||
|
||||
<!-- <ImageView-->
|
||||
<!-- android:layout_width="96dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_gravity="center"-->
|
||||
<!-- android:scaleType="centerCrop"-->
|
||||
<!-- android:src="@mipmap/ic_camera_gray"-->
|
||||
<!-- tools:ignore="ContentDescription" />-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="24dp"-->
|
||||
<!-- android:text="图片采集"-->
|
||||
<!-- android:textColor="#ffb4b4c8"-->
|
||||
<!-- android:textSize="24sp" />-->
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
<FrameLayout
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/flCameraPreview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
android:layout_gravity="center"
|
||||
app:cardCornerRadius="10dp"
|
||||
app:cardElevation="0dp"/>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cvImageBg"
|
||||
@@ -90,6 +66,35 @@
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llCameraFlag"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/bg_white_radius10_stroke2_dash"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/ic_camera_gray"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="图片采集"
|
||||
android:textColor="#ffb4b4c8"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -95,4 +95,27 @@
|
||||
app:layout_constraintBottom_toTopOf="@id/dividerLine"
|
||||
android:layout_marginBottom="60dp"/>
|
||||
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:orientation="horizontal"-->
|
||||
<!-- android:gravity="center_vertical"-->
|
||||
<!-- android:layout_marginStart="20dp"-->
|
||||
<!-- app:layout_constraintStart_toEndOf="@id/btnAgainRecognize"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="@id/btnAgainRecognize"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="@id/btnAgainRecognize"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent">-->
|
||||
|
||||
<!-- <ImageView-->
|
||||
<!-- android:id="@+id/ivGoods"-->
|
||||
<!-- android:layout_width="100dp"-->
|
||||
<!-- android:layout_height="wrap_content"/>-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tvGoods"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"/>-->
|
||||
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in New Issue
Block a user