联调优化
This commit is contained in:
@@ -153,6 +153,9 @@ dependencies {
|
||||
} else {
|
||||
releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
|
||||
}
|
||||
|
||||
implementation("org.greenrobot:eventbus:3.3.1")
|
||||
|
||||
}
|
||||
|
||||
apply(plugin = "io.objectbox")
|
||||
@@ -1,42 +1,42 @@
|
||||
{
|
||||
"class_names": [
|
||||
"圆白菜[卷心菜]",
|
||||
"大白菜(代表值)",
|
||||
"大葱",
|
||||
"洋葱(鲜)[葱头]",
|
||||
"番茄[西红柿]",
|
||||
"胡萝卜(红)[金笋,丁香萝卜]",
|
||||
"芹菜(茎)[旱芹,药芹]",
|
||||
"茄子(代表值)",
|
||||
"西兰花[绿菜花]",
|
||||
"辣椒(青,尖)",
|
||||
"黄瓜(鲜)[胡瓜]"
|
||||
"圆白菜[卷心菜,包菜]WP2025111000063",
|
||||
"大白菜WP2025111000064",
|
||||
"大葱WP2025111000060",
|
||||
"洋葱(鲜)[葱头]WP2025111000061",
|
||||
"番茄WP2025110700016",
|
||||
"胡萝卜WP2025110600008",
|
||||
"芹菜WP2025111000065",
|
||||
"茄子(紫皮,长)WP2025110700024",
|
||||
"西兰花[绿菜花]WP2025110700029",
|
||||
"辣椒(青辣椒,螺丝椒)WP2025110700017",
|
||||
"黄瓜(鲜)[胡瓜]WP2025110700031"
|
||||
],
|
||||
"class_to_idx": {
|
||||
"圆白菜[卷心菜]": 0,
|
||||
"大白菜(代表值)": 1,
|
||||
"大葱": 2,
|
||||
"洋葱(鲜)[葱头]": 3,
|
||||
"番茄[西红柿]": 4,
|
||||
"胡萝卜(红)[金笋,丁香萝卜]": 5,
|
||||
"芹菜(茎)[旱芹,药芹]": 6,
|
||||
"茄子(代表值)": 7,
|
||||
"西兰花[绿菜花]": 8,
|
||||
"辣椒(青,尖)": 9,
|
||||
"黄瓜(鲜)[胡瓜]": 10
|
||||
"圆白菜[卷心菜,包菜]WP2025111000063": 0,
|
||||
"大白菜WP2025111000064": 1,
|
||||
"大葱WP2025111000060": 2,
|
||||
"洋葱(鲜)[葱头]WP2025111000061": 3,
|
||||
"番茄WP2025110700016": 4,
|
||||
"胡萝卜WP2025110600008": 5,
|
||||
"芹菜WP2025111000065": 6,
|
||||
"茄子(紫皮,长)WP2025110700024": 7,
|
||||
"西兰花[绿菜花]WP2025110700029": 8,
|
||||
"辣椒(青辣椒,螺丝椒)WP2025110700017": 9,
|
||||
"黄瓜(鲜)[胡瓜]WP2025110700031": 10
|
||||
},
|
||||
"idx_to_class": {
|
||||
"0": "圆白菜[卷心菜]",
|
||||
"1": "大白菜(代表值)",
|
||||
"2": "大葱",
|
||||
"3": "洋葱(鲜)[葱头]",
|
||||
"4": "番茄[西红柿]",
|
||||
"5": "胡萝卜(红)[金笋,丁香萝卜]",
|
||||
"6": "芹菜(茎)[旱芹,药芹]",
|
||||
"7": "茄子(代表值)",
|
||||
"8": "西兰花[绿菜花]",
|
||||
"9": "辣椒(青,尖)",
|
||||
"10": "黄瓜(鲜)[胡瓜]"
|
||||
"0": "圆白菜[卷心菜,包菜]WP2025111000063",
|
||||
"1": "大白菜WP2025111000064",
|
||||
"2": "大葱WP2025111000060",
|
||||
"3": "洋葱(鲜)[葱头]WP2025111000061",
|
||||
"4": "番茄WP2025110700016",
|
||||
"5": "胡萝卜WP2025110600008",
|
||||
"6": "芹菜WP2025111000065",
|
||||
"7": "茄子(紫皮,长)WP2025110700024",
|
||||
"8": "西兰花[绿菜花]WP2025110700029",
|
||||
"9": "辣椒(青辣椒,螺丝椒)WP2025110700017",
|
||||
"10": "黄瓜(鲜)[胡瓜]WP2025110700031"
|
||||
},
|
||||
"embedding_dim": 512,
|
||||
"total_images": 770,
|
||||
|
||||
@@ -276,7 +276,13 @@ class FoodCollectionActivity : ComponentActivity() {
|
||||
private fun image2VectorTask(bitmap: Bitmap, position: Int) {
|
||||
try {
|
||||
initBox()
|
||||
val imageVector = FoodModule.bitmap2FloatArray(bitmap)
|
||||
val imageVector = try {
|
||||
FoodModule.bitmap2FloatArray(bitmap)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
//toast("保存失败")
|
||||
return
|
||||
}
|
||||
box?.put(
|
||||
Food(
|
||||
name = searchGoodsList[clickIndex].goodsName,
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.activity.viewModels
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.core.graphics.toColorInt
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.shuwei.intelligent.shelves.utils.ext.appendText
|
||||
import com.shuwei.intelligent.shelves.utils.ext.buildSpannableString
|
||||
import com.sw.inbound.GlobalData
|
||||
@@ -45,13 +46,15 @@ import com.sw.inbound.utils.ext.toJsonString
|
||||
import com.sw.inbound.utils.ext.toast
|
||||
import com.sw.inbound.viewmodel.ReceiptViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
typealias RecognizeCallback = (List<SearchGoodsInfo.Record>)->Unit
|
||||
typealias RecognizeCallback = (List<SearchGoodsInfo.Record>) -> Unit
|
||||
|
||||
@AndroidEntryPoint
|
||||
abstract class GoodsListActivity : ComponentActivity() {
|
||||
@@ -147,14 +150,16 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
startTime = System.currentTimeMillis()
|
||||
binding.root.postDelayed({
|
||||
SensorScaleUtils.addWeightListener {
|
||||
try {
|
||||
weightCallback?.invoke(it)
|
||||
recognizeWeight(weight = it)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
runOnUiThread {
|
||||
try {
|
||||
weightCallback?.invoke(it)
|
||||
recognizeWeight(weight = it)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3 * 1000)
|
||||
}, 1 * 1000)
|
||||
}
|
||||
|
||||
private var weightCallback: ((weight: Int) -> Unit)? = null
|
||||
@@ -171,13 +176,13 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
// return
|
||||
//}
|
||||
if (weight < 200) {
|
||||
if (abs(weight) < 10) {
|
||||
if (DialogManager.getDialogList().size == 1 &&
|
||||
DialogManager.contains("GoodsRecognizeDialog") &&
|
||||
goodsRecognizeDialog?.isShowing == true) {
|
||||
goodsRecognizeDialog?.dismiss()
|
||||
}
|
||||
}
|
||||
// if (abs(weight) < 10) {
|
||||
// if (DialogManager.getDialogList().size == 1 &&
|
||||
// DialogManager.contains("GoodsRecognizeDialog") &&
|
||||
// goodsRecognizeDialog?.isShowing == true) {
|
||||
// goodsRecognizeDialog?.dismiss()
|
||||
// }
|
||||
// }
|
||||
return
|
||||
}
|
||||
this.lastWeight = weight
|
||||
@@ -192,7 +197,8 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
// Timber.tag(TAG).d("recognizeWeight, checkResult=true")
|
||||
// return
|
||||
// }
|
||||
Timber.tag(TAG).d("recognizeWeight,recognizeFood:isShowRecognizeDialog=$isShowRecognizeDialog")
|
||||
Timber.tag(TAG)
|
||||
.d("recognizeWeight,recognizeFood:isShowRecognizeDialog=$isShowRecognizeDialog")
|
||||
recognizeFood()
|
||||
}
|
||||
|
||||
@@ -201,19 +207,29 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
|
||||
private val takePhotoSuccessCallback: (Uri) -> Unit = { uri ->
|
||||
Thread {
|
||||
searchFood(uri)
|
||||
try {
|
||||
searchFood(uri)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun delayRecognizeFood() {
|
||||
window.decorView.postDelayed({
|
||||
if (abs(lastWeight) < 10) {
|
||||
return
|
||||
}
|
||||
window.decorView.postDelayed(
|
||||
{
|
||||
recognizeFood()
|
||||
},
|
||||
DELAY_TIME.toLong())
|
||||
DELAY_TIME.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
fun recognizeFood() {
|
||||
if (isShowRecognizeDialog.not()) {
|
||||
if(goodsRecognizeDialog == null) {
|
||||
if (goodsRecognizeDialog == null) {
|
||||
isShowRecognizeDialog = true
|
||||
}
|
||||
return
|
||||
@@ -231,7 +247,7 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private var recognizeCallback:RecognizeCallback?=null
|
||||
private var recognizeCallback: RecognizeCallback? = null
|
||||
var isAgainRecognize = false
|
||||
|
||||
fun againRecognizeFood(callback: RecognizeCallback) {
|
||||
@@ -267,33 +283,47 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
targetWidth = 1000, targetHeight = 1300,
|
||||
offsetX = 30, offsetY = 100
|
||||
)
|
||||
val file = BitmapSaver.saveToAppFilesDir(
|
||||
newBmp,
|
||||
this,
|
||||
"IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
)
|
||||
Timber.d("${this.javaClass.simpleName}-searchFood-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
//val foodList = FoodModule.queryFood(newBmp)
|
||||
if (bitmap.isRecycled.not()) {
|
||||
bitmap.recycle()
|
||||
}
|
||||
// val file = BitmapSaver.saveToAppFilesDir(
|
||||
// newBmp,
|
||||
// this,
|
||||
// "IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
// )
|
||||
// Timber.d("${this.javaClass.simpleName}-searchFood-裁剪bitmap保存文件路径:${file?.absolutePath}")
|
||||
//var foodList = FoodModule.queryFood(newBmp)
|
||||
//物品编号
|
||||
//foodList = foodList.map { "WP"+it.split("WP")[1] }
|
||||
//物品名称
|
||||
//foodList = foodList.map { it.split("WP")[0] }
|
||||
|
||||
val foodList = FoodModule.getFoodScoreList(newBmp)
|
||||
runOnUiThread {
|
||||
if (foodList.isEmpty()) {
|
||||
handleGoodsResult()
|
||||
return@runOnUiThread
|
||||
}
|
||||
viewModel.recognizeGoodsList(
|
||||
//nameList = foodList,
|
||||
scoreList = foodList,
|
||||
) { goodsList ->
|
||||
if (newBmp.isRecycled.not()) {
|
||||
newBmp.recycle()
|
||||
}
|
||||
if (foodList.isEmpty()) {
|
||||
recognizeFoodError()
|
||||
return@let
|
||||
}
|
||||
foodList.forEach {
|
||||
it.name = it.name.split("WP")[0]
|
||||
}
|
||||
viewModel.recognizeGoodsList(
|
||||
//nameList = foodList,
|
||||
scoreList = foodList,
|
||||
) { goodsList ->
|
||||
runOnUiThread {
|
||||
if (isAgainRecognize) {
|
||||
Loading.dismiss()
|
||||
recognizeCallback?.invoke(goodsList)
|
||||
isAgainRecognize = false
|
||||
return@recognizeGoodsList
|
||||
return@runOnUiThread
|
||||
}
|
||||
handleGoodsResult(
|
||||
goodsList = if (goodsList.size == foodList.size) goodsList else mutableListOf(),
|
||||
file = file,
|
||||
name = foodList.joinToString(",")
|
||||
// file = null,
|
||||
// name = foodList.joinToString(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -302,8 +332,8 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
|
||||
private fun handleGoodsResult(
|
||||
goodsList: List<SearchGoodsInfo.Record> = mutableListOf(),
|
||||
file: File?=null,
|
||||
name: String?=null,
|
||||
file: File? = null,
|
||||
name: String? = null,
|
||||
) {
|
||||
runOnUiThread {
|
||||
if (goodsRecognizeDialog?.isShowing == true) {
|
||||
@@ -383,7 +413,8 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
val finalWeight = item.goodsWeight?.toDouble().plus2(goods.goodsWeight?.toDouble())
|
||||
val finalNum = item.receivedNum.plus2(goods.receivedNum)
|
||||
val finalAmount = item.recPriceInItem.plus2(goods.recPriceInItem)
|
||||
val finalPrice = if (finalAmount == 0.toDouble() || finalNum == 0.toDouble()) 0.toDouble() else finalAmount / finalNum
|
||||
val finalPrice =
|
||||
if (finalAmount == 0.toDouble() || finalNum == 0.toDouble()) 0.toDouble() else finalAmount / finalNum
|
||||
item.run {
|
||||
receivedNum = finalNum
|
||||
recUnitPriceTaxIn = finalPrice.roundedDecimalPlace(2)
|
||||
@@ -453,7 +484,10 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
val count = goodsList.count { it.isLocalGoods }
|
||||
// 处理返回事件
|
||||
if (count > 0) {
|
||||
WarnDialog(context = this@GoodsListActivity, content = "存在未收货的物品,请确认是否放弃收货,若放弃则数据不会保存?") {
|
||||
WarnDialog(
|
||||
context = this@GoodsListActivity,
|
||||
content = "存在未收货的物品,请确认是否放弃收货,若放弃则数据不会保存?"
|
||||
) {
|
||||
//onBackPressedDispatcher.onBackPressed()
|
||||
finish()
|
||||
}.show()
|
||||
@@ -531,18 +565,18 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
fun uploadImage(imageUri: Uri, callback: (String?) -> Unit) {
|
||||
viewModel.uploadImage(imageUri) { imgUrl ->
|
||||
if (imgUrl.isNullOrBlank()) {
|
||||
callback(null)
|
||||
return@uploadImage
|
||||
}
|
||||
callback(imgUrl)
|
||||
}
|
||||
}
|
||||
// fun uploadImage(imageUri: Uri, callback: (String?) -> Unit) {
|
||||
// viewModel.uploadImage(imageUri) { imgUrl ->
|
||||
// if (imgUrl.isNullOrBlank()) {
|
||||
// callback(null)
|
||||
// return@uploadImage
|
||||
// }
|
||||
// callback(imgUrl)
|
||||
// }
|
||||
// }
|
||||
|
||||
fun createNewGoods(imageUri: Uri, param: GoodsAddParam, callback: (Boolean) -> Unit) {
|
||||
viewModel.uploadImage(imageUri) { imgUrl ->
|
||||
fun createNewGoods(file: File, param: GoodsAddParam, callback: (Boolean) -> Unit) {
|
||||
viewModel.uploadImage(file) { imgUrl ->
|
||||
if (imgUrl.isNullOrBlank()) {
|
||||
toast("图片上传失败")
|
||||
return@uploadImage
|
||||
@@ -551,4 +585,15 @@ abstract class GoodsListActivity : ComponentActivity() {
|
||||
viewModel.createNewGoods(param = param, callback = callback)
|
||||
}
|
||||
}
|
||||
|
||||
private fun recognizeFoodError() {
|
||||
if (isAgainRecognize) {
|
||||
Loading.dismiss()
|
||||
recognizeCallback?.invoke(mutableListOf())
|
||||
isAgainRecognize = false
|
||||
} else {
|
||||
handleGoodsResult()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,10 @@ 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.BitmapCropper
|
||||
import com.sw.inbound.utils.BitmapSaver
|
||||
import com.sw.inbound.utils.CameraUtils
|
||||
import com.sw.inbound.utils.ImageUtil
|
||||
import com.sw.inbound.utils.ext.dp
|
||||
import com.sw.inbound.utils.ext.gone
|
||||
import com.sw.inbound.utils.ext.toast
|
||||
@@ -46,6 +49,7 @@ class AddGoodsDialog(
|
||||
private val cameraUtils: CameraUtils by lazy {
|
||||
CameraUtils(activity!!)
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
super.show()
|
||||
cameraUtils.setPreviewController(previewView)
|
||||
@@ -71,7 +75,10 @@ class AddGoodsDialog(
|
||||
}
|
||||
cameraUtils.initCamera()
|
||||
val previewBinding =
|
||||
LayoutCameraPreviewBinding.inflate(LayoutInflater.from(context), binding.flCameraPreview)
|
||||
LayoutCameraPreviewBinding.inflate(
|
||||
LayoutInflater.from(context),
|
||||
binding.flCameraPreview
|
||||
)
|
||||
previewBinding.previewView.let {
|
||||
it.updateLayoutParams {
|
||||
width = 428.dp
|
||||
@@ -98,9 +105,9 @@ class AddGoodsDialog(
|
||||
cameraUtils.takePhoto(takePhotoCallback)
|
||||
}
|
||||
binding.btnUploadImg.gone()
|
||||
binding.btnUploadImg.setOnClickListener {
|
||||
uploadImage()
|
||||
}
|
||||
// binding.btnUploadImg.setOnClickListener {
|
||||
// uploadImage()
|
||||
// }
|
||||
binding.tvGoodsType.let { tv ->
|
||||
tv.text = "原材料"
|
||||
tv.tag = GlobalData.goodsTypeList.firstOrNull { it.value == "原材料" }?.id
|
||||
@@ -111,7 +118,7 @@ class AddGoodsDialog(
|
||||
textView = binding.tvProcurementUnit,
|
||||
arrowImage = binding.ivProcurementArrow,
|
||||
list = GlobalData.unitTypeList,
|
||||
height = 2*71.dp
|
||||
height = 2 * 71.dp
|
||||
)
|
||||
// showDropDownList(
|
||||
// binding.flGoodsType,
|
||||
@@ -129,7 +136,7 @@ class AddGoodsDialog(
|
||||
textView = binding.tvWarehouseUnit,
|
||||
arrowImage = binding.ivWarehouseArrow,
|
||||
list = GlobalData.unitTypeList,
|
||||
height = 3*71.dp
|
||||
height = 3 * 71.dp
|
||||
) {
|
||||
binding.tvSelectUseUnit.text = it.value
|
||||
binding.tvSelectProcurementUnit.text = it.value
|
||||
@@ -144,7 +151,7 @@ class AddGoodsDialog(
|
||||
height: Int = 355.dp,
|
||||
block: (DictType) -> Unit = {}
|
||||
) {
|
||||
dropdownView.setOnClickListener {v->
|
||||
dropdownView.setOnClickListener { v ->
|
||||
dropdownList.clear()
|
||||
val tempList =
|
||||
list.filter { it.id.isNullOrBlank().not() && it.value.isNullOrBlank().not() }
|
||||
@@ -238,31 +245,51 @@ class AddGoodsDialog(
|
||||
purchaseValue = goodsCount.toSafeFloat(),
|
||||
purchasePrice = goodsPrice.toSafeBigDecimal(),
|
||||
)
|
||||
activity?.createNewGoods(imageUri!!, param) {
|
||||
if (it.not()) {
|
||||
context.toast("新增物品失败")
|
||||
return@createNewGoods
|
||||
activity?.let {
|
||||
Loading.show(it)
|
||||
}
|
||||
ImageUtil.uriToBitmap(context, imageUri!!)?.let { bitmap ->
|
||||
val newBmp = BitmapCropper.cropCenter(
|
||||
original = bitmap,
|
||||
targetWidth = 1000, targetHeight = 1300,
|
||||
offsetX = 30, offsetY = 100
|
||||
)
|
||||
val file = BitmapSaver.saveToAppFilesDir(
|
||||
newBmp,
|
||||
context,
|
||||
"IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
)
|
||||
if(file == null) {
|
||||
context.toast("请重新拍照后再试")
|
||||
Loading.dismiss()
|
||||
return@let
|
||||
}
|
||||
activity?.createNewGoods(file, param) {
|
||||
Loading.dismiss()
|
||||
if (it.not()) {
|
||||
context.toast("新增物品失败")
|
||||
return@createNewGoods
|
||||
}
|
||||
context.toast("新增物品成功")
|
||||
confirmBlock(goodsName)
|
||||
dismiss()
|
||||
}
|
||||
context.toast("新增物品成功")
|
||||
confirmBlock(goodsName)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private var imageUri: Uri? = null
|
||||
|
||||
private fun uploadImage() {
|
||||
if (imageUri == null) {
|
||||
context.toast("请采集图片")
|
||||
return
|
||||
}
|
||||
activity?.uploadImage(imageUri!!) { imgUrl ->
|
||||
if (imgUrl.isNullOrBlank()) {
|
||||
context.toast("图片上传失败")
|
||||
return@uploadImage
|
||||
}
|
||||
context.toast(imgUrl)
|
||||
}
|
||||
}
|
||||
|
||||
// private fun uploadImage() {
|
||||
// if (imageUri == null) {
|
||||
// context.toast("请采集图片")
|
||||
// return
|
||||
// }
|
||||
// activity?.uploadImage(imageUri!!) { imgUrl ->
|
||||
// if (imgUrl.isNullOrBlank()) {
|
||||
// context.toast("图片上传失败")
|
||||
// return@uploadImage
|
||||
// }
|
||||
// context.toast(imgUrl)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -151,7 +151,7 @@ class CollectSearchDialog(
|
||||
confirmBlock = {
|
||||
Thread {
|
||||
activity?.runOnUiThread {
|
||||
Loading.show(context)
|
||||
Loading.show(activity!!)
|
||||
}
|
||||
val name = list[position].goodsName
|
||||
val filterIdList = box?.all?.filter { it.name == name }?.map { it.id }
|
||||
@@ -191,7 +191,7 @@ class CollectSearchDialog(
|
||||
list.clear()
|
||||
var queryList = box?.all?.distinctBy { it.name }
|
||||
if (searchName.isNullOrBlank().not()) {
|
||||
queryList = queryList?.filter { it.name?.contains(searchName) == true }
|
||||
queryList = queryList?.filter { it.name?.contains(searchName!!) == true }
|
||||
}
|
||||
queryList?.forEach {
|
||||
list.add((SearchGoodsInfo.Record(goodsName = it.name)))
|
||||
|
||||
@@ -88,14 +88,14 @@ class GoodsRecognizeDialog(
|
||||
binding.btnAgainRecognize.setOnClickListener {
|
||||
//dismiss()
|
||||
activity?.againRecognizeFood { goodsList ->
|
||||
binding.rvRecognize.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
list.clear()
|
||||
list.addAll(goodsList)
|
||||
recognizeAdapter.notifyDataSetChanged()
|
||||
if (recognizeAdapter.list.isEmpty()) {
|
||||
loadEmptyView()
|
||||
return@againRecognizeFood
|
||||
}
|
||||
binding.rvRecognize.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
recognizeAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import android.text.style.StyleSpan
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.core.graphics.toColorInt
|
||||
@@ -25,7 +24,6 @@ import com.sw.inbound.activity.GoodsListActivity
|
||||
import com.sw.inbound.databinding.DialogGoodsStoreBinding
|
||||
import com.sw.inbound.databinding.LayoutImagePreviewBinding
|
||||
import com.sw.inbound.databinding.LayoutTakePhotoBinding
|
||||
import com.sw.inbound.ext.toFormattedString
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.GoodsInfo
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||
@@ -97,6 +95,9 @@ class GoodsStoreDialog(
|
||||
binding.btnConfirm.setOnClickListener {
|
||||
confirmInputData()
|
||||
}
|
||||
binding.tvTitle.setOnClickListener {
|
||||
SensorScaleUtils.startScale(autoScale = true)
|
||||
}
|
||||
// binding.ivAddUnit.setOnClickListener {
|
||||
// AddProcurementUnitDialog(context).show()
|
||||
// }
|
||||
@@ -124,13 +125,12 @@ class GoodsStoreDialog(
|
||||
}
|
||||
}
|
||||
val first = goods.unitVoList!!.first { it.businessUnitId == dictType.id }
|
||||
val stringBuilder = StringBuilder()
|
||||
.append("1").append(dictType.value).append("=")
|
||||
.append(first.purchaseValue!!.toInt().toString())
|
||||
.append(goods.kcUnitName)
|
||||
.append(",")
|
||||
.append("1").append(goods.kcUnitName).append("=")
|
||||
.append(first.consumeValue).append("克")
|
||||
val stringBuilder =
|
||||
StringBuilder().append("1").append(dictType.value).append("=")
|
||||
.append(first.purchaseValue!!.toInt().toString())
|
||||
.append(goods.kcUnitName).append(",").append("1")
|
||||
.append(goods.kcUnitName).append("=").append(first.consumeValue)
|
||||
.append("克")
|
||||
binding.tvUnitCalculate.text = stringBuilder.toString()
|
||||
//val count = getUnitCount(dictType.id!!)
|
||||
//if (count.isBlank() || "0" == count) {
|
||||
@@ -268,9 +268,7 @@ class GoodsStoreDialog(
|
||||
StyleSpan(Typeface.BOLD)
|
||||
)
|
||||
appendText(
|
||||
" 克",
|
||||
ForegroundColorSpan("#FF000033".toColorInt()),
|
||||
StyleSpan(Typeface.BOLD)
|
||||
" 克", ForegroundColorSpan("#FF000033".toColorInt()), StyleSpan(Typeface.BOLD)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -375,6 +373,9 @@ class GoodsStoreDialog(
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.root.postDelayed({
|
||||
SensorScaleUtils.startScale()
|
||||
}, 2600)
|
||||
}
|
||||
|
||||
private var imageUri: Uri? = null
|
||||
@@ -435,8 +436,10 @@ class GoodsStoreDialog(
|
||||
ImageUtil.uriToBitmap(context, imageUri!!)?.let { bitmap ->
|
||||
val cropBitmap = BitmapCropper.cropCenter(
|
||||
original = bitmap,
|
||||
targetWidth = 1000, targetHeight = 1300,
|
||||
offsetX = 30, offsetY = 100
|
||||
targetWidth = 1000,
|
||||
targetHeight = 1300,
|
||||
offsetX = 30,
|
||||
offsetY = 100
|
||||
)
|
||||
val file = BitmapSaver.saveToAppFilesDir(
|
||||
cropBitmap, context, "IMG_CROP_${System.currentTimeMillis()}.jpg"
|
||||
@@ -448,7 +451,11 @@ class GoodsStoreDialog(
|
||||
Thread {
|
||||
try {
|
||||
val imageVector = FoodModule.bitmap2FloatArray(bitmap)
|
||||
box?.put(Food(name = goods.goodsName, foodIdx = 0, foodVector = imageVector))
|
||||
box?.put(
|
||||
Food(
|
||||
name = goods.goodsName, foodIdx = 0, foodVector = imageVector
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
package com.sw.inbound.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import com.sw.inbound.R
|
||||
import com.sw.inbound.databinding.DialogLoadingBinding
|
||||
import kotlin.let
|
||||
import kotlin.run
|
||||
|
||||
object Loading {
|
||||
|
||||
private var dialog: LoadingDialog? = null
|
||||
|
||||
fun show(context: Context) {
|
||||
fun show(activity: Activity) {
|
||||
try {
|
||||
if (activity.isFinishing || activity.isDestroyed) {
|
||||
return
|
||||
}
|
||||
if (dialog?.isShowing == true) {
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
if (dialog == null) {
|
||||
dialog = LoadingDialog(context)
|
||||
dialog = LoadingDialog(activity)
|
||||
}
|
||||
dialog?.show()
|
||||
} catch (e: Exception) {
|
||||
@@ -56,10 +60,10 @@ class LoadingDialog(
|
||||
setCanceledOnTouchOutside(true)
|
||||
window?.run {
|
||||
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||
//setFlags(
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
//)
|
||||
// setFlags(
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
// )
|
||||
}
|
||||
setOnDismissListener {
|
||||
onDismiss()
|
||||
@@ -67,83 +71,3 @@ class LoadingDialog(
|
||||
}
|
||||
}
|
||||
|
||||
//class LoadingDialog3(
|
||||
// private val activity: Activity,
|
||||
// private val message: String = "加载中……",
|
||||
// private val onDismiss: () -> Unit = {}
|
||||
//) : DialogFragment() {
|
||||
//
|
||||
// override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
// return SafeDialog(
|
||||
// activity = activity,
|
||||
// themeResId = R.style.ToastDialogTheme,
|
||||
// ).apply {
|
||||
// val binding = DialogLoadingBinding.inflate(LayoutInflater.from(context))
|
||||
// binding.tvMessage.text = message
|
||||
// setContentView(binding.root)
|
||||
// setCancelable(true)
|
||||
// window?.run {
|
||||
// setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||
// setFlags(
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
// );
|
||||
// }
|
||||
// setOnDismissListener {
|
||||
// onDismiss()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun dismiss() {
|
||||
// super.dismiss()
|
||||
// }
|
||||
//
|
||||
// override fun show(manager: FragmentManager, tag: String?) {
|
||||
// runCatching {
|
||||
// super.show(manager, tag)
|
||||
// Handler(Looper.getMainLooper()).postDelayed({
|
||||
// super.dismiss()
|
||||
// }, 800)
|
||||
// }.onFailure {
|
||||
// it.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
//class LoadingDialog(
|
||||
// private val activity: Activity,
|
||||
// private val message: String = "加载中……",
|
||||
// private val onDismiss: () -> Unit = {}
|
||||
//) : SafeDialog(
|
||||
// activity = activity,
|
||||
// themeResId = R.style.ToastDialogTheme,
|
||||
//) {
|
||||
//
|
||||
// override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// super.onCreate(savedInstanceState)
|
||||
// val binding = DialogLoadingBinding.inflate(LayoutInflater.from(context))
|
||||
// binding.tvMessage.text = message
|
||||
// setContentView(binding.root)
|
||||
// setCancelable(true)
|
||||
// window?.run {
|
||||
// setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||
// setFlags(
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
// );
|
||||
// }
|
||||
// setOnDismissListener {
|
||||
// onDismiss()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun show(manager: FragmentManager, tag: String?) {
|
||||
// show()
|
||||
// Handler(Looper.getMainLooper()).postDelayed({
|
||||
// super.dismiss()
|
||||
// }, 800)
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@@ -61,14 +61,8 @@ object FoodModule {
|
||||
NO_STD_RGB // [0.229, 0.224, 0.225] TORCHVISION_NORM_STD_RGB
|
||||
)
|
||||
val outputTensor = module_mobile.forward(IValue.from(inputTensor)).toTensor()
|
||||
// return floatArrayOf()
|
||||
val floatArray = outputTensor.dataAsFloatArray
|
||||
// try {
|
||||
// if (bitmap.isRecycled.not()) {
|
||||
// bitmap.recycle()
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
return floatArray
|
||||
}
|
||||
|
||||
@@ -110,8 +104,13 @@ object FoodModule {
|
||||
}
|
||||
fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List<IdNameScore> {
|
||||
val floatArray = bitmap2FloatArray(bitmap)
|
||||
// return emptyList()
|
||||
val nameScoreList = queryFoodNameScore(floatArray, queryCount)
|
||||
val maxScoreList = nameScoreList.groupBy { it.name }.map { (_, value) -> value.minByOrNull { it.score }!! }.toMutableList()
|
||||
val maxScoreList = nameScoreList
|
||||
.filter { it.score < 0.20 }
|
||||
.groupBy { it.name }
|
||||
.map { (_, value) -> value.minByOrNull { it.score }!! }
|
||||
.toMutableList()
|
||||
val map = mutableMapOf<String, Int>()
|
||||
nameScoreList.forEach {
|
||||
val key = it.name
|
||||
@@ -142,7 +141,7 @@ object FoodModule {
|
||||
|
||||
data class IdNameScore(
|
||||
val id:Long,
|
||||
val name:String,
|
||||
var name:String,
|
||||
val score: Double
|
||||
)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.sw.inbound.network.api.ApiService
|
||||
import com.sw.inbound.utils.ContextUtils
|
||||
import com.sw.inbound.utils.FileUtils
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -126,6 +127,22 @@ class RemoteRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
suspend fun uploadImage(file:File): ApiResponse<String> {
|
||||
return safeApiCall {
|
||||
//val codeRequestBody = RequestBody.create(
|
||||
// MultipartBody.FORM,
|
||||
// "4"
|
||||
//)
|
||||
|
||||
val part = FileUtils.genRequestPart(file)
|
||||
if (part == null) {
|
||||
ApiResponse(code = "-1", msg = "解析图片失败")
|
||||
} else {
|
||||
//apiService.uploadImage(code = codeRequestBody, file = part)
|
||||
apiService.uploadImage(file = part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 部分收货
|
||||
|
||||
@@ -2,12 +2,17 @@ package com.sw.inbound.sdk
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.sw.inbound.utils.MessageEvent
|
||||
import com.sw.inbound.utils.ThreadUtils
|
||||
import com.sw.inbound.utils.ToastUtils
|
||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
|
||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale.OnScaleResult
|
||||
import kotlinx.coroutines.delay
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import timber.log.Timber
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
typealias WeightCallback = (Int) -> Unit
|
||||
|
||||
/**
|
||||
@@ -18,18 +23,24 @@ object SensorScaleUtils {
|
||||
const val serialPort = "/dev/ttyS7"
|
||||
const val baudRate = 115200
|
||||
private var mSensorScale: SensorScale? = null
|
||||
var isValidWeight = false
|
||||
|
||||
private fun init() {
|
||||
if (mSensorScale != null) {
|
||||
return
|
||||
}
|
||||
mSensorScale = SensorScale(object : OnScaleResult {
|
||||
/**
|
||||
* 读取重量
|
||||
*/
|
||||
override fun readWeight(state: Int, value: Double) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
callbackList.forEach {
|
||||
it.invoke((value * 1000).roundToInt())
|
||||
}
|
||||
isValidWeight = true
|
||||
callbackList.forEach {
|
||||
it.invoke((value * 1000).roundToInt())
|
||||
}
|
||||
|
||||
// EventBus.getDefault().post(MessageEvent((value * 1000).roundToInt()))
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,9 +51,11 @@ object SensorScaleUtils {
|
||||
}
|
||||
|
||||
override fun fail(errCode: Int) {
|
||||
isValidWeight = false
|
||||
Timber.e("fail code = $errCode")
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
ToastUtils.showToast("秤读取数据异常")
|
||||
startScale()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -61,15 +74,16 @@ object SensorScaleUtils {
|
||||
init()
|
||||
mSensorScale?.openScale(serialPort, baudRate) { open ->
|
||||
if (open && autoScale) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
mSensorScale?.readWeight()
|
||||
mSensorScale?.startContinuousRead()
|
||||
}, 1500)
|
||||
// ThreadUtils.launchOnIo {
|
||||
// delay(1000)
|
||||
// // 打开后需要等待后才能调用,否则会 1001 SDK未初始化
|
||||
// mSensorScale?.startContinuousRead()
|
||||
// }
|
||||
// Handler(Looper.getMainLooper()).postDelayed({
|
||||
// mSensorScale?.readWeight()
|
||||
// mSensorScale?.startContinuousRead()
|
||||
// }, 1500)
|
||||
ThreadUtils.launchOnIo {
|
||||
delay(1000)
|
||||
// 打开后需要等待后才能调用,否则会 1001 SDK未初始化
|
||||
mSensorScale?.readWeight()
|
||||
mSensorScale?.startContinuousRead()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.sw.inbound.utils
|
||||
import android.graphics.Bitmap
|
||||
import android.util.DisplayMetrics
|
||||
|
||||
object BitmapCropper {
|
||||
/**
|
||||
@@ -22,8 +23,11 @@ object BitmapCropper {
|
||||
startY = startY.coerceAtLeast(0)
|
||||
val actualWidth = minOf(targetWidth, originalWidth - startX)
|
||||
val actualHeight = minOf(targetHeight, originalHeight - startY)
|
||||
|
||||
return Bitmap.createBitmap(original, startX, startY, actualWidth, actualHeight)
|
||||
|
||||
return Bitmap.createBitmap(original, startX, startY, actualWidth, actualHeight).also {
|
||||
// it.setConfig(Bitmap.Config.RGB_565)
|
||||
// it.density = DisplayMetrics.DENSITY_LOW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ object BitmapSaver {
|
||||
context: Context,
|
||||
fileName: String,
|
||||
format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG,
|
||||
quality: Int = 100
|
||||
quality: Int = 10
|
||||
): File? {
|
||||
//val dir = context.getExternalFilesDir(null)
|
||||
val dir = context.cacheDir
|
||||
|
||||
@@ -51,6 +51,9 @@ object FileUtils {
|
||||
Timber.d("genRequestPart imageUri = $imageUri")
|
||||
// 1. 从Uri获取文件
|
||||
val file = getFileFromUri(context, imageUri)
|
||||
return genRequestPart(file)
|
||||
}
|
||||
fun genRequestPart(file: File?): MultipartBody.Part? {
|
||||
if (file == null) {
|
||||
Timber.e("getFileFromUri file is null")
|
||||
return null
|
||||
|
||||
@@ -6,9 +6,11 @@ import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
|
||||
object ImageUtil {
|
||||
|
||||
fun uriToBitmap(context: Context, uri: Uri): Bitmap? {
|
||||
return try {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inSampleSize = 10; // 这会将图片的尺寸缩小到原来的1/2
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565
|
||||
context.contentResolver.openInputStream(uri)?.use { stream ->
|
||||
BitmapFactory.decodeStream(stream)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.sw.inbound.repository.RemoteRepository
|
||||
import com.sw.inbound.utils.ext.toJsonString
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -335,9 +336,20 @@ class ReceiptViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun uploadImage(imageUri: Uri, callback: (String?) -> Unit) {
|
||||
// fun uploadImage(imageUri: Uri, callback: (String?) -> Unit) {
|
||||
// launchWithLoading {
|
||||
// val resp = repository.uploadImage(imageUri)
|
||||
// if (!parseResponse(resp)) {
|
||||
// callback(null)
|
||||
// return@launchWithLoading
|
||||
// }
|
||||
// callback(resp.data)
|
||||
// }
|
||||
// }
|
||||
|
||||
fun uploadImage(file:File, callback: (String?) -> Unit) {
|
||||
launchWithLoading {
|
||||
val resp = repository.uploadImage(imageUri)
|
||||
val resp = repository.uploadImage(file)
|
||||
if (!parseResponse(resp)) {
|
||||
callback(null)
|
||||
return@launchWithLoading
|
||||
@@ -365,4 +377,6 @@ class ReceiptViewModel @Inject constructor(
|
||||
callback(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="14"
|
||||
|
||||
Reference in New Issue
Block a user