优化-待测试
This commit is contained in:
@@ -1,13 +1,18 @@
|
|||||||
package com.sw.inbound.activity
|
package com.sw.inbound.activity
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Dialog
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.sw.inbound.R
|
import com.sw.inbound.R
|
||||||
@@ -17,6 +22,7 @@ import com.sw.inbound.databinding.ActivityFoodCollectionBinding
|
|||||||
import com.sw.inbound.databinding.LayoutCameraPreviewBinding
|
import com.sw.inbound.databinding.LayoutCameraPreviewBinding
|
||||||
import com.sw.inbound.databinding.LayoutEmptySearchBinding
|
import com.sw.inbound.databinding.LayoutEmptySearchBinding
|
||||||
import com.sw.inbound.dialog.CollectSearchDialog
|
import com.sw.inbound.dialog.CollectSearchDialog
|
||||||
|
import com.sw.inbound.dialog.CustomDialog
|
||||||
import com.sw.inbound.dialog.Loading
|
import com.sw.inbound.dialog.Loading
|
||||||
import com.sw.inbound.model.response.SearchGoodsInfo
|
import com.sw.inbound.model.response.SearchGoodsInfo
|
||||||
import com.sw.inbound.objbox.Food
|
import com.sw.inbound.objbox.Food
|
||||||
@@ -26,6 +32,7 @@ import com.sw.inbound.objbox.ObjectBox
|
|||||||
import com.sw.inbound.utils.BitmapCropper
|
import com.sw.inbound.utils.BitmapCropper
|
||||||
import com.sw.inbound.utils.BitmapSaver
|
import com.sw.inbound.utils.BitmapSaver
|
||||||
import com.sw.inbound.utils.CameraUtils
|
import com.sw.inbound.utils.CameraUtils
|
||||||
|
import com.sw.inbound.utils.ImageUploader
|
||||||
import com.sw.inbound.utils.ImageUtil
|
import com.sw.inbound.utils.ImageUtil
|
||||||
import com.sw.inbound.utils.ext.addOnActionSearchListener
|
import com.sw.inbound.utils.ext.addOnActionSearchListener
|
||||||
import com.sw.inbound.utils.ext.clickWithDebounce
|
import com.sw.inbound.utils.ext.clickWithDebounce
|
||||||
@@ -41,7 +48,10 @@ import com.sw.inbound.viewmodel.ReceiptViewModel
|
|||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.kotlin.boxFor
|
import io.objectbox.kotlin.boxFor
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -77,8 +87,8 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
it.uploadSuccess = false
|
it.uploadSuccess = false
|
||||||
}
|
}
|
||||||
collectionAdapter.notifyItemChanged(position)
|
collectionAdapter.notifyItemChanged(position)
|
||||||
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
val count = collectList.count { it.imageFile != null && it.uploadSuccess.not() }
|
||||||
binding.btnUploadImage.text = "待上传图片${count}张"
|
// binding.btnUploadImage.text = "待上传图片${count}张"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,14 +145,14 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
searchGoods()
|
searchGoods()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.btnUploadImage.setOnClickListener {
|
// binding.btnUploadImage.setOnClickListener {
|
||||||
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
||||||
if (count == 0) {
|
// if (count == 0) {
|
||||||
toast("已全部上传成功")
|
// toast("已全部上传成功")
|
||||||
return@setOnClickListener
|
// return@setOnClickListener
|
||||||
}
|
// }
|
||||||
uploadAllImage()
|
// uploadAllImage()
|
||||||
}
|
// }
|
||||||
binding.btnSave.setOnClickListener { _ ->
|
binding.btnSave.setOnClickListener { _ ->
|
||||||
if (clickIndex == -1) {
|
if (clickIndex == -1) {
|
||||||
toast("请选择物品名称")
|
toast("请选择物品名称")
|
||||||
@@ -153,8 +163,10 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
toast("请拍摄物品照片")
|
toast("请拍摄物品照片")
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
vectorThread()
|
// vectorThread()
|
||||||
uploadAllImage()
|
// uploadAllImage()
|
||||||
|
|
||||||
|
upload()
|
||||||
}
|
}
|
||||||
binding.btnTakePhoto.clickWithDebounce {
|
binding.btnTakePhoto.clickWithDebounce {
|
||||||
takePhoto()
|
takePhoto()
|
||||||
@@ -182,7 +194,7 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
loadEmptyView()
|
loadEmptyView()
|
||||||
|
|
||||||
binding.tvTitle.setOnClickListener {
|
binding.tvTitle.setOnClickListener {
|
||||||
startActivity<LocalImagePreviewActivity> { }
|
startActivity<LocalImagePreviewActivity> { }
|
||||||
|
|
||||||
// val goodsImage = GoodsImage(goodsId = "1993493094888140802", goodsName = "多宝鱼", startTime = 1764120531856L, endTime = 1764121842825L)
|
// val goodsImage = GoodsImage(goodsId = "1993493094888140802", goodsName = "多宝鱼", startTime = 1764120531856L, endTime = 1764121842825L)
|
||||||
// uploadImage(goodsImage)
|
// uploadImage(goodsImage)
|
||||||
@@ -261,14 +273,14 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
searchAdapter.notifyDataSetChanged()
|
searchAdapter.notifyDataSetChanged()
|
||||||
loadEmptyView()
|
loadEmptyView()
|
||||||
binding.ivFinish.invisible()
|
binding.ivFinish.invisible()
|
||||||
binding.btnUploadImage.text = "待上传图片${0}张"
|
// binding.btnUploadImage.text = "待上传图片${0}张"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val cameraCallback: (Uri) -> Unit = { uri ->
|
private val cameraCallback: (Uri) -> Unit = { uri ->
|
||||||
val index = collectList.indexOfFirst { it.imageFile == null }
|
val index = collectList.indexOfFirst { it.imageFile == null }
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
toast("每次只允许保存6条数据")
|
toast("每次只允许保存6条数据")
|
||||||
rerurn@cameraCallback
|
rerurn@ cameraCallback
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
ImageUtil.uriToBitmap(this, uri)?.let { bitmap ->
|
||||||
@@ -286,7 +298,8 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
return@let
|
return@let
|
||||||
}
|
}
|
||||||
val foodList = FoodModule.queryFoodNameScore(imageVector)
|
val foodList = FoodModule.queryFoodNameScore(imageVector)
|
||||||
val filterList = foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子")}
|
val filterList =
|
||||||
|
foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子") }
|
||||||
if (filterList.isNotEmpty()) {
|
if (filterList.isNotEmpty()) {
|
||||||
toast("当前物品可能被袋子遮挡,请检查后重试")
|
toast("当前物品可能被袋子遮挡,请检查后重试")
|
||||||
return@let
|
return@let
|
||||||
@@ -302,8 +315,8 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
it.isShowCamera = false
|
it.isShowCamera = false
|
||||||
}
|
}
|
||||||
collectionAdapter.notifyItemChanged(index)
|
collectionAdapter.notifyItemChanged(index)
|
||||||
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
val count = collectList.count { it.imageFile != null && it.uploadSuccess.not() }
|
||||||
binding.btnUploadImage.text = "待上传图片${count}张"
|
// binding.btnUploadImage.text = "待上传图片${count}张"
|
||||||
if (cropBitmap.isRecycled.not()) {
|
if (cropBitmap.isRecycled.not()) {
|
||||||
cropBitmap.recycle()
|
cropBitmap.recycle()
|
||||||
}
|
}
|
||||||
@@ -337,9 +350,10 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun image2VectorTask(
|
private fun image2VectorTask(
|
||||||
bitmap: Bitmap?=null,
|
bitmap: Bitmap? = null,
|
||||||
imageVector: FloatArray?=null,
|
imageVector: FloatArray? = null,
|
||||||
position: Int) {
|
position: Int
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
initBox()
|
initBox()
|
||||||
// val imageVector = try {
|
// val imageVector = try {
|
||||||
@@ -443,51 +457,77 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private val failList = mutableListOf<File>()
|
// private fun uploadAllImage() {
|
||||||
// private var successCount = 0
|
// Loading.show(this)
|
||||||
private fun uploadAllImage() {
|
// val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! }
|
||||||
Loading.show(this)
|
// if (files.isEmpty()) {
|
||||||
val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! }
|
// return
|
||||||
if (files.isEmpty()) {
|
// }
|
||||||
return
|
// val goods = searchGoodsList[clickIndex]
|
||||||
}
|
// for (index in collectList.indices step 5) {
|
||||||
// successCount = 0
|
// val end = if(index + 5 < collectList.size - 1) index + 5 else collectList.size - 1
|
||||||
// failList.clear()
|
// val subList = collectList.subList(index, end)
|
||||||
val goods = searchGoodsList[clickIndex]
|
// val subFiles = subList.map { it.imageFile }
|
||||||
for (index in collectList.indices step 5) {
|
// viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, subFiles) {isSuccess->
|
||||||
val end = if(index + 5 < collectList.size - 1) index + 5 else collectList.size - 1
|
// Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
|
||||||
val subList = collectList.subList(index, end)
|
// subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
|
||||||
val subFiles = subList.map { it.imageFile }
|
//
|
||||||
viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, subFiles) {isSuccess->
|
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
||||||
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
|
// runOnUiThread {
|
||||||
//{"code":"00000","data":null,"msg":"成功","total":0}
|
// binding.btnUploadImage.text = "待上传图片${count}张"
|
||||||
// val resp = result?.toObject<RespData>()
|
// if (count == 0) {
|
||||||
// val isSuccess = resp?.code == "00000"
|
// Loading.dismiss()
|
||||||
subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
|
// }
|
||||||
|
// }
|
||||||
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
|
||||||
runOnUiThread {
|
|
||||||
binding.btnUploadImage.text = "待上传图片${count}张"
|
|
||||||
if (count == 0) {
|
|
||||||
Loading.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// binding.ivFinish.run {
|
|
||||||
// if (isSuccess) visible() else invisible()
|
|
||||||
// }
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
private fun upload() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val totalFileCount = collectList.count { it.imageFile != null }
|
||||||
|
val goods = searchGoodsList[clickIndex]
|
||||||
|
val params = HashMap<String, RequestBody>()
|
||||||
|
//params["placeId"] = restId.toRequestBody()
|
||||||
|
params["foodId"] = goods.id!!.toRequestBody()
|
||||||
|
params["foodName"] = goods.goodsName!!.toRequestBody()
|
||||||
|
//params["foodVector"] = foodVector.toRequestBody()
|
||||||
|
ImageUploader(
|
||||||
|
totalList = collectList,
|
||||||
|
uploadImage = { batch ->
|
||||||
|
val files = batch.map { it.imageFile }
|
||||||
|
viewModel.uploadMultipleImages(files = files, params)
|
||||||
|
},
|
||||||
|
onProgress = { count, batch ->
|
||||||
|
runOnUiThread {
|
||||||
|
showWaitingDialog2("图片上传中$count/$totalFileCount")
|
||||||
|
batch.forEach {
|
||||||
|
it.uploadSuccess = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
runOnUiThread {
|
||||||
|
hideWaitingDialog()
|
||||||
|
toast("上传失败,请稍后重试")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onComplete = {
|
||||||
|
hideWaitingDialog()
|
||||||
|
vectorThread()
|
||||||
|
}
|
||||||
|
).processUploads()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val receiptViewModel: ReceiptViewModel by viewModels()
|
private val receiptViewModel: ReceiptViewModel by viewModels()
|
||||||
|
|
||||||
fun searchGoodsInfoList(goodsName: String, block:(List<SearchGoodsInfo.Record>)->Unit) {
|
fun searchGoodsInfoList(goodsName: String, block: (List<SearchGoodsInfo.Record>) -> Unit) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val list = searchGoodsInfoList2(goodsName)
|
val list = searchGoodsInfoList2(goodsName)
|
||||||
block(list)
|
block(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun searchGoodsInfoList2(
|
suspend fun searchGoodsInfoList2(
|
||||||
goodsName: String,
|
goodsName: String,
|
||||||
pageNo: Int = 1,
|
pageNo: Int = 1,
|
||||||
@@ -496,18 +536,53 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
return receiptViewModel.searchGoodsInfoList2(goodsName, pageNo, pageSize)
|
return receiptViewModel.searchGoodsInfoList2(goodsName, pageNo, pageSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var mDialogWaiting: CustomDialog? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示等待提示框
|
||||||
|
*/
|
||||||
|
fun showWaitingDialog(tip: String?): Dialog? {
|
||||||
|
hideWaitingDialog()
|
||||||
|
val view = View.inflate(this, R.layout.dialog_waiting, null)
|
||||||
|
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
|
||||||
|
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
|
||||||
|
mDialogWaiting!!.show()
|
||||||
|
mDialogWaiting!!.setCancelable(true)
|
||||||
|
return mDialogWaiting
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏等待提示框
|
||||||
|
*/
|
||||||
|
fun hideWaitingDialog() {
|
||||||
|
mDialogWaiting?.dismiss()
|
||||||
|
mDialogWaiting = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showWaitingDialog2(tip: String?) {
|
||||||
|
if (mDialogWaiting == null) {
|
||||||
|
hideWaitingDialog()
|
||||||
|
val view = View.inflate(this, R.layout.dialog_waiting, null)
|
||||||
|
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
|
||||||
|
mDialogWaiting!!.show()
|
||||||
|
mDialogWaiting!!.setCancelable(true)
|
||||||
|
}
|
||||||
|
val tvTip = findViewById<TextView>(R.id.tvTip)
|
||||||
|
tvTip.text = tip
|
||||||
|
}
|
||||||
|
|
||||||
data class RespData(
|
data class RespData(
|
||||||
var code:String?=null,
|
var code: String? = null,
|
||||||
var data:String?=null,
|
var data: String? = null,
|
||||||
var msg:String?=null,
|
var msg: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
data class GoodsImage(
|
data class GoodsImage(
|
||||||
var goodsId:String,
|
var goodsId: String,
|
||||||
var goodsName:String,
|
var goodsName: String,
|
||||||
var startTime:Long,
|
var startTime: Long,
|
||||||
var endTime:Long
|
var endTime: Long
|
||||||
)
|
)
|
||||||
//
|
//
|
||||||
// val goodsImageList = mutableListOf<GoodsImage>().apply {
|
// val goodsImageList = mutableListOf<GoodsImage>().apply {
|
||||||
@@ -564,52 +639,52 @@ class FoodCollectionActivity : ComponentActivity() {
|
|||||||
// ))
|
// ))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private fun uploadImage(goodsImage: GoodsImage) {
|
// private fun uploadImage(goodsImage: GoodsImage) {
|
||||||
Loading.show(this)
|
// Loading.show(this)
|
||||||
val cropFile = File(this.cacheDir, "crop")
|
// val cropFile = File(this.cacheDir, "crop")
|
||||||
val list = mutableListOf<File>()
|
// val list = mutableListOf<File>()
|
||||||
val startTime = goodsImage.startTime
|
// val startTime = goodsImage.startTime
|
||||||
val endTime = goodsImage.endTime
|
// val endTime = goodsImage.endTime
|
||||||
cropFile.listFiles()?.forEach {
|
// cropFile.listFiles()?.forEach {
|
||||||
if (it.isDirectory) {
|
// if (it.isDirectory) {
|
||||||
return@forEach
|
// return@forEach
|
||||||
}
|
// }
|
||||||
val start = "IMG_CROP_".length
|
// val start = "IMG_CROP_".length
|
||||||
val end = it.name.indexOf(".jpg")
|
// val end = it.name.indexOf(".jpg")
|
||||||
val time = it.name.substring(start, end).toLong()
|
// val time = it.name.substring(start, end).toLong()
|
||||||
if (time in startTime..endTime) {
|
// if (time in startTime..endTime) {
|
||||||
list.add(it)
|
// list.add(it)
|
||||||
}
|
// }
|
||||||
if (list.size < 5) {
|
// if (list.size < 5) {
|
||||||
return@forEach
|
// return@forEach
|
||||||
}
|
// }
|
||||||
viewModel.uploadMultipleImages(
|
// viewModel.uploadMultipleImages(
|
||||||
goodsId = goodsImage.goodsId,
|
// goodsId = goodsImage.goodsId,
|
||||||
goodsName = goodsImage.goodsName,
|
// goodsName = goodsImage.goodsName,
|
||||||
files = list
|
// files = list
|
||||||
) { isSuccess ->
|
// ) { isSuccess ->
|
||||||
// val resp = data?.toObject<RespData>()
|
//// val resp = data?.toObject<RespData>()
|
||||||
// val isSuccess = resp?.code == "00000"
|
//// val isSuccess = resp?.code == "00000"
|
||||||
binding.ivFinish.run {
|
// binding.ivFinish.run {
|
||||||
if (isSuccess) visible() else invisible()
|
// if (isSuccess) visible() else invisible()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
list.clear()
|
// list.clear()
|
||||||
}
|
// }
|
||||||
if (list.isNotEmpty()) {
|
// if (list.isNotEmpty()) {
|
||||||
viewModel.uploadMultipleImages(
|
// viewModel.uploadMultipleImages(
|
||||||
goodsId = goodsImage.goodsId,
|
// goodsId = goodsImage.goodsId,
|
||||||
goodsName = goodsImage.goodsName,
|
// goodsName = goodsImage.goodsName,
|
||||||
files = list
|
// files = list
|
||||||
) { isSuccess ->
|
// ) { isSuccess ->
|
||||||
// val resp = data?.toObject<RespData>()
|
//// val resp = data?.toObject<RespData>()
|
||||||
// val isSuccess = resp?.code == "00000"
|
//// val isSuccess = resp?.code == "00000"
|
||||||
binding.ivFinish.run {
|
// binding.ivFinish.run {
|
||||||
if (isSuccess) visible() else invisible()
|
// if (isSuccess) visible() else invisible()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Loading.dismiss()
|
// Loading.dismiss()
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ import androidx.activity.viewModels
|
|||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.shuwei.intelligent.shelves.utils.ext.appendText
|
import com.shuwei.intelligent.shelves.utils.ext.appendText
|
||||||
import com.shuwei.intelligent.shelves.utils.ext.buildSpannableString
|
import com.shuwei.intelligent.shelves.utils.ext.buildSpannableString
|
||||||
@@ -45,7 +46,10 @@ import com.sw.inbound.utils.ext.toJsonString
|
|||||||
import com.sw.inbound.utils.ext.toast
|
import com.sw.inbound.utils.ext.toast
|
||||||
import com.sw.inbound.viewmodel.ReceiptViewModel
|
import com.sw.inbound.viewmodel.ReceiptViewModel
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@@ -180,8 +184,9 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
// Timber.tag(TAG).d(clazzName)
|
// Timber.tag(TAG).d(clazzName)
|
||||||
if (DialogManager.getDialogList().size == 1 &&
|
if (DialogManager.getDialogList().size == 1 &&
|
||||||
DialogManager.contains("GoodsRecognizeDialog") &&
|
DialogManager.contains("GoodsRecognizeDialog") &&
|
||||||
goodsRecognizeDialog?.isShowing == true) {
|
goodsRecognizeDialog?.isShowing == true
|
||||||
goodsRecognizeDialog?.dismiss()
|
) {
|
||||||
|
goodsRecognizeDialog?.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -313,7 +318,8 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
foodList.forEach {
|
foodList.forEach {
|
||||||
it.name = it.name.split("WP")[0]
|
it.name = it.name.split("WP")[0]
|
||||||
}
|
}
|
||||||
val filterList = foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子")}
|
val filterList =
|
||||||
|
foodList.filter { it.score < FoodModule.BAG_RATE && it.name.contains("黑袋子") }
|
||||||
if (filterList.isNotEmpty()) {
|
if (filterList.isNotEmpty()) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
toast("当前物品可能被袋子遮挡,请检查后重试")
|
toast("当前物品可能被袋子遮挡,请检查后重试")
|
||||||
@@ -622,14 +628,17 @@ abstract class GoodsListActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadImage(goodsId:String, goodsName:String, imageFile: File?) {
|
fun uploadImage(goodsId: String, goodsName: String, imageFile: File?) {
|
||||||
if (imageFile == null) {
|
lifecycleScope.launch {
|
||||||
return
|
if (imageFile == null) {
|
||||||
}
|
return@launch
|
||||||
val list = mutableListOf<File>()
|
}
|
||||||
list.add(imageFile)
|
val list = mutableListOf<File>()
|
||||||
viewModel.uploadMultipleImages(goodsId, goodsName, list) {
|
list.add(imageFile)
|
||||||
Timber.tag(TAG).d("uploadMultipleImages: ${it}")
|
val map = hashMapOf<String, RequestBody>()
|
||||||
|
map["goodsId"] = goodsId.toRequestBody()
|
||||||
|
map["goodsName"] = goodsName.toRequestBody()
|
||||||
|
viewModel.uploadMultipleImages(files = list, params = map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.sw.inbound.dialog;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sw.inbound.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载进度条弹窗
|
||||||
|
*/
|
||||||
|
public class CustomDialog extends Dialog {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 宽高由布局文件中指定(但是最底层的宽度无效,可以多嵌套一层解决)
|
||||||
|
*/
|
||||||
|
public CustomDialog(Context context, View layout, int style) {
|
||||||
|
|
||||||
|
super(context, style);
|
||||||
|
|
||||||
|
setContentView(layout);
|
||||||
|
|
||||||
|
Window window = getWindow();
|
||||||
|
|
||||||
|
WindowManager.LayoutParams params = window.getAttributes();
|
||||||
|
|
||||||
|
params.gravity = Gravity.CENTER;
|
||||||
|
|
||||||
|
window.setAttributes(params);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 宽高由该方法的参数设置
|
||||||
|
*/
|
||||||
|
public CustomDialog(Context context, int width, int height, View layout,
|
||||||
|
int style) {
|
||||||
|
super(context, style);
|
||||||
|
// 设置内容
|
||||||
|
setContentView(layout);
|
||||||
|
// 设置窗口属性
|
||||||
|
Window window = getWindow();
|
||||||
|
WindowManager.LayoutParams params = window.getAttributes();
|
||||||
|
// 设置宽度、高度、密度、对齐方式
|
||||||
|
float density = getDensity(context);
|
||||||
|
params.width = (int) (width * density);
|
||||||
|
params.height = (int) (height * density);
|
||||||
|
params.gravity = Gravity.CENTER;
|
||||||
|
window.setAttributes(params);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取显示密度
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public float getDensity(Context context) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
DisplayMetrics dm = res.getDisplayMetrics();
|
||||||
|
return dm.density;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fullScreenImmersive(View view) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
|
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||||
|
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
|
| View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||||
|
view.setSystemUiVisibility(uiOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||||
|
super.show();
|
||||||
|
// fullScreenImmersive(getWindow().getDecorView());
|
||||||
|
// this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -213,11 +213,11 @@ class RemoteRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun uploadMultipleImages(fileList: List<File>, param: Map<String, String>): ApiResponse<String> {
|
suspend fun uploadMultipleImages(fileList: List<File>, params: HashMap<String, RequestBody>): ApiResponse<String> {
|
||||||
val paramsMap = hashMapOf<String, RequestBody>()
|
// val paramsMap = hashMapOf<String, RequestBody>()
|
||||||
param.forEach { (key, value) ->
|
// param.forEach { (key, value) ->
|
||||||
paramsMap[key] = value.toRequestBody("text/plain".toMediaTypeOrNull())
|
// paramsMap[key] = value.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 准备文件参数
|
// 准备文件参数
|
||||||
val fileParts = mutableListOf<MultipartBody.Part>()
|
val fileParts = mutableListOf<MultipartBody.Part>()
|
||||||
@@ -232,7 +232,7 @@ class RemoteRepository @Inject constructor(
|
|||||||
fileParts.add(filePart)
|
fileParts.add(filePart)
|
||||||
}
|
}
|
||||||
return safeApiCall {
|
return safeApiCall {
|
||||||
apiService.uploadMultipleImages(params = paramsMap, goodsPics = fileParts)
|
apiService.uploadMultipleImages(params = params, goodsPics = fileParts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.sw.inbound.utils
|
||||||
|
|
||||||
|
import com.sw.inbound.objbox.FoodCollectionBean
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import kotlin.collections.chunked
|
||||||
|
import kotlin.collections.count
|
||||||
|
|
||||||
|
class ImageUploader(
|
||||||
|
private val totalList: List<FoodCollectionBean>,
|
||||||
|
private val uploadImage: suspend (List<FoodCollectionBean>)-> Boolean,
|
||||||
|
private val onProgress: (Int, List<FoodCollectionBean>) -> Unit,
|
||||||
|
private val onError:(List<FoodCollectionBean>) -> Unit,
|
||||||
|
private val onComplete:() -> Unit
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private const val BATCH_SIZE = 5
|
||||||
|
}
|
||||||
|
private val uploadedCount = AtomicInteger(0)
|
||||||
|
|
||||||
|
suspend fun processUploads() {
|
||||||
|
val batches = totalList.chunked(BATCH_SIZE)
|
||||||
|
|
||||||
|
for (batch in batches) {
|
||||||
|
val success = uploadImage(batch)
|
||||||
|
if (!success) {
|
||||||
|
//println("上传失败,终止流程")
|
||||||
|
onError(batch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val fileCount = batch.count { it.imageFile!=null }
|
||||||
|
uploadedCount.addAndGet(fileCount)
|
||||||
|
onProgress(uploadedCount.get(), batch)
|
||||||
|
//println("已上传 ${uploadedCount.get()}/$totalImages")
|
||||||
|
}
|
||||||
|
|
||||||
|
onComplete()
|
||||||
|
//println("流程完成,总计上传 ${uploadedCount.get()} 张图片")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.sw.inbound.model.response.SearchGoodsInfo
|
|||||||
import com.sw.inbound.repository.RemoteRepository
|
import com.sw.inbound.repository.RemoteRepository
|
||||||
import com.sw.inbound.utils.ext.toJsonString
|
import com.sw.inbound.utils.ext.toJsonString
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import okhttp3.RequestBody
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -347,7 +348,7 @@ class ReceiptViewModel @Inject constructor(
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fun uploadImage(file:File, callback: (String?) -> Unit) {
|
fun uploadImage(file: File, callback: (String?) -> Unit) {
|
||||||
launchWithLoading {
|
launchWithLoading {
|
||||||
val resp = repository.uploadImage(file)
|
val resp = repository.uploadImage(file)
|
||||||
if (!parseResponse(resp)) {
|
if (!parseResponse(resp)) {
|
||||||
@@ -377,23 +378,42 @@ class ReceiptViewModel @Inject constructor(
|
|||||||
callback(true)
|
callback(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun uploadMultipleImages(goodsId:String, goodsName:String, files:List<File?>, callback: (Boolean) -> Unit) {
|
// fun uploadMultipleImages(goodsId:String, goodsName:String, files:List<File?>, callback: (Boolean) -> Unit) {
|
||||||
launchWithLoading {
|
// launchWithLoading {
|
||||||
val map = mutableMapOf<String, String>()
|
// val map = mutableMapOf<String, String>()
|
||||||
map["goodsId"] = goodsId
|
// map["goodsId"] = goodsId
|
||||||
map["goodsName"] = goodsName
|
// map["goodsName"] = goodsName
|
||||||
val fileList = files.filterNotNull()
|
// val fileList = files.filterNotNull()
|
||||||
if (fileList.isEmpty()) {
|
// if (fileList.isEmpty()) {
|
||||||
callback(false)
|
// callback(false)
|
||||||
return@launchWithLoading
|
// return@launchWithLoading
|
||||||
}
|
// }
|
||||||
val resp = repository.uploadMultipleImages(fileList = fileList, param = map)
|
// val resp = repository.uploadMultipleImages(fileList = fileList, param = map)
|
||||||
if (!parseResponse(resp)) {
|
// if (!parseResponse(resp)) {
|
||||||
callback(false)
|
// callback(false)
|
||||||
return@launchWithLoading
|
// return@launchWithLoading
|
||||||
}
|
// }
|
||||||
callback(resp.code == "00000")
|
// callback(resp.code == "00000")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
suspend fun uploadMultipleImages(
|
||||||
|
files: List<File?>,
|
||||||
|
params: HashMap<String, RequestBody>
|
||||||
|
): Boolean {
|
||||||
|
// val map = mutableMapOf<String, String>()
|
||||||
|
// map["goodsId"] = goodsId
|
||||||
|
// map["goodsName"] = goodsName
|
||||||
|
val fileList = files.filterNotNull()
|
||||||
|
if (fileList.isEmpty()) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
val resp = repository.uploadMultipleImages(fileList = fileList, params = params)
|
||||||
|
// if (!parseResponse(resp)) {
|
||||||
|
// callback(false)
|
||||||
|
// return@launchWithLoading
|
||||||
|
// }
|
||||||
|
return resp.code == "00000"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<solid android:color="@color/black" />
|
||||||
|
</shape>
|
||||||
@@ -353,18 +353,18 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1" />
|
android:layout_weight="1" />
|
||||||
|
|
||||||
<TextView
|
<!-- <TextView-->
|
||||||
android:id="@+id/btnUploadImage"
|
<!-- android:id="@+id/btnUploadImage"-->
|
||||||
android:layout_width="270dp"
|
<!-- android:layout_width="270dp"-->
|
||||||
android:layout_height="90dp"
|
<!-- android:layout_height="90dp"-->
|
||||||
android:layout_gravity="center_vertical"
|
<!-- android:layout_gravity="center_vertical"-->
|
||||||
android:layout_marginEnd="20dp"
|
<!-- android:layout_marginEnd="20dp"-->
|
||||||
android:background="@drawable/bg_blue_ripple"
|
<!-- android:background="@drawable/bg_blue_ripple"-->
|
||||||
android:gravity="center"
|
<!-- android:gravity="center"-->
|
||||||
android:text="待上传图片"
|
<!-- android:text="待上传图片"-->
|
||||||
android:textColor="@color/white"
|
<!-- android:textColor="@color/white"-->
|
||||||
android:textSize="26sp"
|
<!-- android:textSize="26sp"-->
|
||||||
android:textStyle="bold" />
|
<!-- android:textStyle="bold" />-->
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/btnSave"
|
android:id="@+id/btnSave"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/dialog_waiting"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:indeterminateTint="@color/teal_200"
|
||||||
|
android:indeterminateTintMode="src_atop" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTip"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="请稍等"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -27,4 +27,18 @@
|
|||||||
<item name="android:windowIsFloating">true</item>
|
<item name="android:windowIsFloating">true</item>
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!--圆角Dialog-->
|
||||||
|
<style name="MyDialog" parent="@android:style/Theme.Dialog">
|
||||||
|
<item name="android:windowFrame">@null</item>
|
||||||
|
<item name="android:windowIsFloating">true</item>
|
||||||
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:background">@android:color/transparent</item>
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
<item name="android:backgroundDimEnabled">true</item>
|
||||||
|
<item name="android:backgroundDimAmount">0.6</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user