相机优化、对接识别名称搜索新接口、替换模型文件

This commit is contained in:
2025-10-30 15:40:36 +08:00
parent 7930ba0cd1
commit 89fabe7322
17 changed files with 333 additions and 209 deletions
Binary file not shown.
+35 -29
View File
@@ -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
View File
@@ -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
+33 -28
View File
@@ -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>