This commit is contained in:
马增飞
2025-11-27 15:06:30 +08:00
parent 1e46a5ace7
commit 5b7b73dd55
10 changed files with 395 additions and 64 deletions
+1
View File
@@ -56,6 +56,7 @@
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity android:name="com.sw.inbound.activity.FoodCollectionActivity" <activity android:name="com.sw.inbound.activity.FoodCollectionActivity"
android:windowSoftInputMode="adjustPan" /> android:windowSoftInputMode="adjustPan" />
<activity android:name="com.sw.inbound.activity.LocalImagePreviewActivity" />
<!-- <activity--> <!-- <activity-->
<!-- android:name=".InitActivity"--> <!-- android:name=".InitActivity"-->
@@ -27,13 +27,13 @@ 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.ImageUtil import com.sw.inbound.utils.ImageUtil
import com.sw.inbound.utils.ToastUtils
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
import com.sw.inbound.utils.ext.dp import com.sw.inbound.utils.ext.dp
import com.sw.inbound.utils.ext.gone import com.sw.inbound.utils.ext.gone
import com.sw.inbound.utils.ext.hideKeyboard import com.sw.inbound.utils.ext.hideKeyboard
import com.sw.inbound.utils.ext.invisible import com.sw.inbound.utils.ext.invisible
import com.sw.inbound.utils.ext.startActivity
import com.sw.inbound.utils.ext.toObject import com.sw.inbound.utils.ext.toObject
import com.sw.inbound.utils.ext.toast import com.sw.inbound.utils.ext.toast
import com.sw.inbound.utils.ext.visible import com.sw.inbound.utils.ext.visible
@@ -69,11 +69,16 @@ class FoodCollectionActivity : ComponentActivity() {
FoodCollectionAdapter(collectList).apply { FoodCollectionAdapter(collectList).apply {
addOnItemChildClickListener(R.id.ivDelete) { _, _, position -> addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
collectList[position].let { collectList[position].let {
it.imageFile = null
it.imageVector = null
it.bitmap = null it.bitmap = null
it.isFinish = false it.isFinish = false
it.isShowCamera = true it.isShowCamera = true
it.uploadSuccess = false
} }
collectionAdapter.notifyItemChanged(position) collectionAdapter.notifyItemChanged(position)
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
binding.btnUploadImage.text = "待上传图片${count}"
} }
} }
} }
@@ -130,7 +135,14 @@ class FoodCollectionActivity : ComponentActivity() {
searchGoods() searchGoods()
} }
} }
binding.btnUploadImage.setOnClickListener {
val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
if (count == 0) {
toast("已全部上传成功")
return@setOnClickListener
}
uploadAllImage()
}
binding.btnSave.setOnClickListener { _ -> binding.btnSave.setOnClickListener { _ ->
if (clickIndex == -1) { if (clickIndex == -1) {
toast("请选择物品名称") toast("请选择物品名称")
@@ -142,7 +154,6 @@ class FoodCollectionActivity : ComponentActivity() {
return@setOnClickListener return@setOnClickListener
} }
vectorThread() vectorThread()
uploadAllImage() uploadAllImage()
} }
binding.btnTakePhoto.clickWithDebounce { binding.btnTakePhoto.clickWithDebounce {
@@ -170,9 +181,18 @@ class FoodCollectionActivity : ComponentActivity() {
loadEmptyView() loadEmptyView()
// binding.tvTitle.setOnClickListener { binding.tvTitle.setOnClickListener {
// uploadImage(goodsImageList[7]) startActivity<LocalImagePreviewActivity> { }
// }
// val goodsImage = GoodsImage(goodsId = "1993493094888140802", goodsName = "多宝鱼", startTime = 1764120531856L, endTime = 1764121842825L)
// uploadImage(goodsImage)
// val goodsImage = GoodsImage(goodsId = "1986366073649287170", goodsName = "黑鱼(整条鱼)", startTime = 1764122703093L, endTime = 1764123156022L)
// uploadImage(goodsImage)
// val goodsImage = GoodsImage(goodsId = "1986699063868801025", goodsName = "鸡腿肉", startTime = 1764123375841L, endTime = 1764124039162L)
// uploadImage(goodsImage)
}
} }
private var pageNo = 1 private var pageNo = 1
@@ -224,8 +244,11 @@ class FoodCollectionActivity : ComponentActivity() {
it.bitmap?.recycle() it.bitmap?.recycle()
} }
it.bitmap = null it.bitmap = null
it.imageVector = null
it.imageFile = null
it.isShowCamera = true it.isShowCamera = true
it.isFinish = false it.isFinish = false
it.uploadSuccess = false
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }
@@ -238,6 +261,7 @@ class FoodCollectionActivity : ComponentActivity() {
searchAdapter.notifyDataSetChanged() searchAdapter.notifyDataSetChanged()
loadEmptyView() loadEmptyView()
binding.ivFinish.invisible() binding.ivFinish.invisible()
binding.btnUploadImage.text = "待上传图片${0}"
} }
private val cameraCallback: (Uri) -> Unit = { uri -> private val cameraCallback: (Uri) -> Unit = { uri ->
@@ -279,6 +303,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() }
binding.btnUploadImage.text = "待上传图片${count}"
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
@@ -409,20 +435,35 @@ class FoodCollectionActivity : ComponentActivity() {
} }
} }
// private val failList = mutableListOf<File>()
// private var successCount = 0
private fun uploadAllImage() { private fun uploadAllImage() {
val goods = searchGoodsList[clickIndex] Loading.show(this)
val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! } val files = collectList.filter { it.imageFile!=null }.map { it.imageFile!! }
if (files.isEmpty()) { if (files.isEmpty()) {
return return
} }
for (index in files.indices step 5) { // successCount = 0
val end = if(index + 5 < files.size - 1) index + 5 else files.size - 1 // failList.clear()
val list = files.subList(index, end) val goods = searchGoodsList[clickIndex]
viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, list) { for (index in collectList.indices step 5) {
Timber.tag(TAG).d("uploadMultipleImages: ${it}") val end = if(index + 5 < collectList.size - 1) index + 5 else collectList.size - 1
val subList = collectList.subList(index, end)
val subFiles = subList.map { it.imageFile }
viewModel.uploadMultipleImages(goods.id!!, goods.goodsName!!, subFiles) {isSuccess->
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
//{"code":"00000","data":null,"msg":"成功","total":0} //{"code":"00000","data":null,"msg":"成功","total":0}
// val resp = it?.toObject<RespData>() // val resp = result?.toObject<RespData>()
// val isSuccess = resp?.code == "00000" // val isSuccess = resp?.code == "00000"
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 { // binding.ivFinish.run {
// if (isSuccess) visible() else invisible() // if (isSuccess) visible() else invisible()
// } // }
@@ -515,52 +556,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
// ) { data -> ) { 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
// ) { data -> ) { 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()
// } }
} }
@@ -0,0 +1,97 @@
package com.sw.inbound.activity
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.activity.ComponentActivity
import androidx.recyclerview.widget.GridLayoutManager
import coil.load
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.sw.inbound.databinding.ActivityLocalImagePreviewBinding
import com.sw.inbound.databinding.ListItemImagePreviewBinding
import com.sw.inbound.dialog.Loading
import com.sw.inbound.utils.ext.copyText
import java.io.File
class LocalImagePreviewActivity : ComponentActivity() {
private lateinit var binding: ActivityLocalImagePreviewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLocalImagePreviewBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.let {
it.layoutManager = GridLayoutManager(this, 6, GridLayoutManager.VERTICAL, false)
it.adapter = imageAdapter
}
binding.btnBack.setOnClickListener { finish() }
loadData()
}
fun loadData() {
Thread {
runOnUiThread {
Loading.show(this)
}
val cropFile = File(this.cacheDir, "crop")
cropFile.listFiles()?.forEach {
if (it.isDirectory) {
return@forEach
}
val start = "IMG_CROP_".length
val end = it.name.indexOf(".jpg")
val time = it.name.substring(start, end).toLong()
if (time >= 1764086400L) {
imageList.add(ImageBean(file = it, name = "$time"))
}
}
imageList.sortBy { it.name.toLong() }
runOnUiThread {
imageAdapter.notifyDataSetChanged()
Loading.dismiss()
}
}.start()
}
private var isCycle = true
private val imageList = mutableListOf<ImageBean>()
private val imageAdapter: ImageAdapter by lazy {
ImageAdapter(imageList).apply {
setOnItemClickListener { _, _, position ->
imageList[position].name.copyText(this@LocalImagePreviewActivity)
}
}
}
data class ImageBean(
var file: File,
var name: String
)
inner class ImageAdapter(var list: MutableList<ImageBean>) :
BaseQuickAdapter<ImageBean, ImageAdapter.VH>(list) {
inner class VH(var binding: ListItemImagePreviewBinding) : QuickViewHolder(binding.root)
override fun onBindViewHolder(holder: VH, position: Int, item: ImageBean?) {
holder.binding.let {
it.imageView.load(item!!.file)
it.textView.text = item.name
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
val inflater = LayoutInflater.from(context)
val binding = ListItemImagePreviewBinding.inflate(inflater, parent, false)
return VH(binding)
}
}
}
@@ -159,7 +159,8 @@ interface ApiService {
@Multipart @Multipart
@POST @POST
suspend fun uploadMultipleImages( suspend fun uploadMultipleImages(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/inboundWeighingScale/add", // @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/inboundWeighingScale/add",
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/inbound/pad/inboundWeighingScale/add",
@PartMap params: HashMap<String, RequestBody>, @PartMap params: HashMap<String, RequestBody>,
@Part goodsPics: List<MultipartBody.Part> @Part goodsPics: List<MultipartBody.Part>
): ApiResponse<String> ): ApiResponse<String>
@@ -16,7 +16,8 @@ data class FoodCollectionBean(
var imageFile: File? = null, var imageFile: File? = null,
var imageVector: FloatArray? = null, var imageVector: FloatArray? = null,
var isShowCamera: Boolean = false, var isShowCamera: Boolean = false,
var isFinish:Boolean = false var isFinish:Boolean = false,
var uploadSuccess:Boolean = false
) )
data class ReceiptGoodsInfo( data class ReceiptGoodsInfo(
@@ -2,6 +2,8 @@ package com.sw.inbound.utils.ext
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
@@ -225,3 +227,25 @@ fun View.hideKeyboard() {
imm.hideSoftInputFromWindow(this.windowToken, 0) imm.hideSoftInputFromWindow(this.windowToken, 0)
this.clearFocus() // 清除焦点避免键盘再次弹出 this.clearFocus() // 清除焦点避免键盘再次弹出
} }
/**
* 复制文本到剪贴板
* @param context 上下文
* @param text 要复制的文本内容
* @param showToast 是否显示复制成功提示,默认为true
*/
fun String.copyText(context: Context, showToast: Boolean = true) {
// 获取剪贴板管理器
val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// 创建ClipData对象,包含要复制的文本
val clipData = ClipData.newPlainText("label", this)
// 将数据设置到剪贴板
clipboardManager.setPrimaryClip(clipData)
// 显示复制成功提示
if (showToast) {
Toast.makeText(context, "文本已复制到剪贴板", Toast.LENGTH_SHORT).show()
}
}
@@ -377,17 +377,22 @@ class ReceiptViewModel @Inject constructor(
callback(true) callback(true)
} }
} }
fun uploadMultipleImages(goodsId:String, goodsName:String, files:List<File>, callback: (String?) -> 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 resp = repository.uploadMultipleImages(fileList = files, param = map) val fileList = files.filterNotNull()
if (!parseResponse(resp)) { if (fileList.isEmpty()) {
callback(null) callback(false)
return@launchWithLoading return@launchWithLoading
} }
callback(resp.data) val resp = repository.uploadMultipleImages(fileList = fileList, param = map)
if (!parseResponse(resp)) {
callback(false)
return@launchWithLoading
}
callback(resp.code == "00000")
} }
} }
@@ -340,7 +340,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" /> android:layout_weight="1" />
<ImageView <ImageView
android:id="@+id/ivFinish" android:id="@+id/ivFinish"
android:layout_width="30dp" android:layout_width="30dp"
@@ -354,6 +353,19 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" /> android:layout_weight="1" />
<TextView
android:id="@+id/btnUploadImage"
android:layout_width="270dp"
android:layout_height="90dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_blue_ripple"
android:gravity="center"
android:text="待上传图片"
android:textColor="@color/white"
android:textSize="26sp"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/btnSave" android:id="@+id/btnSave"
android:layout_width="270dp" android:layout_width="270dp"
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg"
android:orientation="vertical"
tools:ignore="HardcodedText">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="出入库管理"
android:textColor="#141428"
android:textSize="36sp"
android:textStyle="bold" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginHorizontal="20dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_white_alpha40_radius6"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="6"
tools:itemCount="20"
tools:listitem="@layout/list_item_image_preview" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="130dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/btnBack"
android:layout_width="270dp"
android:layout_height="90dp"
android:layout_marginStart="20dp"
android:background="@drawable/bg_blue_ripple">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawableStart="@mipmap/ic_back_white2"
android:drawablePadding="32dp"
android:gravity="center"
android:text="返回"
android:textColor="@color/white"
android:textSize="36sp"
android:textStyle="bold"
tools:ignore="UseCompatTextViewDrawableXml" />
</FrameLayout>
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<TextView
android:id="@+id/tvConfirmNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="60dp"
android:textColor="#ff141428"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="已确认 3" />
<TextView
android:id="@+id/tvNotConfirmNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="60dp"
android:textColor="#ff141428"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="未确认 6" />
<!-- <TextView-->
<!-- android:id="@+id/btnConfirmReceipt"-->
<!-- android:layout_width="270dp"-->
<!-- android:layout_height="90dp"-->
<!-- android:layout_gravity="center"-->
<!-- android:layout_marginEnd="20dp"-->
<!-- android:background="@drawable/bg_blue_ripple"-->
<!-- android:gravity="center"-->
<!-- android:text="确认收货"-->
<!-- android:textColor="@color/white"-->
<!-- android:textSize="36sp"-->
<!-- android:textStyle="bold" />-->
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="220dp"
android:scaleType="centerCrop"
tools:src="@drawable/ic_launcher_background" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:textSize="26sp"
tools:text="1231231231" />
</LinearLayout>
</androidx.cardview.widget.CardView>