From cb96a3db01e58366e5415f9a7ef215a9cb00158c Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 31 Oct 2025 16:07:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=89=A9=E5=93=81=E9=87=87?= =?UTF-8?q?=E9=9B=86=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + .../main/java/com/sw/inbound/GlobalData.kt | 3 +- .../activity/FoodCollectionActivity.kt | 364 ++++++++++++++++++ .../sw/inbound/activity/GoodsListActivity.kt | 57 ++- .../sw/inbound/activity/ReceiptActivity.kt | 3 + .../inbound/adapter/FoodCollectionAdapter.kt | 47 +++ .../sw/inbound/adapter/ReceiptGoodsAdapter.kt | 3 +- .../inbound/adapter/SelfProcurementAdapter.kt | 8 +- .../sw/inbound/dialog/GoodsRecognizeDialog.kt | 1 + .../com/sw/inbound/dialog/GoodsStoreDialog.kt | 19 +- .../com/sw/inbound/dialog/LoadingDialog.kt | 148 +++++++ .../com/sw/inbound/model/bean/DataBean.kt | 48 --- .../sw/inbound/model/response/GoodsInfo.kt | 6 +- .../network/interceptor/RequestInterceptor.kt | 1 + .../java/com/sw/inbound/objbox/DataBean.kt | 47 +++ .../java/com/sw/inbound/objbox/FoodModule.kt | 24 +- .../sw/inbound/ui/page/PurchaseOrderScreen.kt | 20 +- .../com/sw/inbound/ui/weight/TopTitleBar.kt | 19 +- .../java/com/sw/inbound/utils/CameraUtils.kt | 8 +- .../sw/inbound/viewmodel/ReceiptViewModel.kt | 305 +++++++-------- app/src/main/res/drawable/bg_gray.xml | 7 + app/src/main/res/drawable/shape_dialog.xml | 6 + .../res/layout/activity_food_collection.xml | 244 ++++++++++++ app/src/main/res/layout/dialog_loading.xml | 28 ++ .../res/layout/list_item_food_collection.xml | 32 ++ .../res/layout/list_item_goods_search.xml | 1 + app/src/main/res/mipmap-xxhdpi/ic_back.png | Bin 0 -> 3082 bytes .../main/res/mipmap-xxhdpi/ic_camera256.png | Bin 0 -> 8661 bytes .../main/res/mipmap-xxhdpi/ic_delete_red.png | Bin 0 -> 1465 bytes app/src/main/res/mipmap-xxhdpi/ic_finish.png | Bin 0 -> 5509 bytes app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/themes.xml | 10 +- 32 files changed, 1195 insertions(+), 266 deletions(-) create mode 100644 app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt create mode 100644 app/src/main/java/com/sw/inbound/adapter/FoodCollectionAdapter.kt create mode 100644 app/src/main/java/com/sw/inbound/dialog/LoadingDialog.kt delete mode 100644 app/src/main/java/com/sw/inbound/model/bean/DataBean.kt create mode 100644 app/src/main/res/drawable/bg_gray.xml create mode 100644 app/src/main/res/drawable/shape_dialog.xml create mode 100644 app/src/main/res/layout/activity_food_collection.xml create mode 100644 app/src/main/res/layout/dialog_loading.xml create mode 100644 app/src/main/res/layout/list_item_food_collection.xml create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_back.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_camera256.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_delete_red.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_finish.png diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 28afd2a..5bc90d4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,6 +52,7 @@ + diff --git a/app/src/main/java/com/sw/inbound/GlobalData.kt b/app/src/main/java/com/sw/inbound/GlobalData.kt index d2c800f..6eb08ca 100644 --- a/app/src/main/java/com/sw/inbound/GlobalData.kt +++ b/app/src/main/java/com/sw/inbound/GlobalData.kt @@ -43,7 +43,8 @@ object GlobalData { /** * 具体业务baseurl */ - var appBaseUrl: String = "http://192.168.1.201:14801" + //var appBaseUrl: String = "http://192.168.1.201:14801" + var appBaseUrl: String = "http://dev.yixiong-tech.com:8081" /** * 设备id diff --git a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt new file mode 100644 index 0000000..8d23025 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt @@ -0,0 +1,364 @@ +package com.sw.inbound.activity + +import android.annotation.SuppressLint +import android.graphics.Bitmap +import android.net.Uri +import android.os.Bundle +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.viewModels +import androidx.camera.view.PreviewView +import androidx.core.view.updateLayoutParams +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import com.sw.inbound.R +import com.sw.inbound.adapter.FoodCollectionAdapter +import com.sw.inbound.adapter.GoodsSearchAdapter +import com.sw.inbound.databinding.ActivityFoodCollectionBinding +import com.sw.inbound.databinding.LayoutCameraPreviewBinding +import com.sw.inbound.databinding.LayoutEmptySearchBinding +import com.sw.inbound.dialog.Loading +import com.sw.inbound.model.response.SearchGoodsInfo +import com.sw.inbound.objbox.Food +import com.sw.inbound.objbox.FoodCollectionBean +import com.sw.inbound.objbox.FoodModule +import com.sw.inbound.objbox.ObjectBox +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.addOnActionSearchListener +import com.sw.inbound.utils.ext.clickWithDebounce +import com.sw.inbound.utils.ext.dp +import com.sw.inbound.utils.ext.hideKeyboard +import com.sw.inbound.utils.ext.toast +import com.sw.inbound.viewmodel.ReceiptViewModel +import dagger.hilt.android.AndroidEntryPoint +import io.objectbox.Box +import io.objectbox.kotlin.boxFor +import kotlinx.coroutines.runBlocking +import timber.log.Timber + +@AndroidEntryPoint +class FoodCollectionActivity : ComponentActivity() { + + private val TAG = "FoodCollectionActivity" + private var selectedFoodName: String = "" + + private var box: Box? = null + private val collectList: MutableList = mutableListOf( + FoodCollectionBean(isShowCamera = true), + FoodCollectionBean(isShowCamera = true), + FoodCollectionBean(isShowCamera = true), + FoodCollectionBean(isShowCamera = true), + FoodCollectionBean(isShowCamera = true), + FoodCollectionBean(isShowCamera = true) + ) + private lateinit var binding: ActivityFoodCollectionBinding + private lateinit var previewView: PreviewView + + val viewModel: ReceiptViewModel by viewModels() + val PAGE_SIZE = 30 + private val cameraUtils: CameraUtils by lazy { + CameraUtils(this) + } + private val collectionAdapter: FoodCollectionAdapter by lazy { + FoodCollectionAdapter(collectList).apply { +// setOnItemClickListener { _, _, position -> +// if (collectList[position].isShowCamera) { +// takePhoto() +// } +// } + addOnItemChildClickListener(R.id.ivDelete) { _, _, position -> + collectList[position].let { + it.bitmap = null + it.isFinish = false + it.isShowCamera = true + } + collectionAdapter.notifyItemChanged(position) +// if (position == collectList.size - 1) { +// +// return@addOnItemChildClickListener +// } +// collectList.removeAt(position) +// adapter.notifyItemRemoved(position) +// adapter.notifyItemRangeChanged(position, collectList.size) + } + } + } + + override fun onResume() { + super.onResume() + cameraUtils.bind() + } + + override fun onPause() { + super.onPause() + cameraUtils.unbind() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityFoodCollectionBinding.inflate(layoutInflater) + setContentView(binding.root) + cameraUtils.initCamera() + val previewBinding = + LayoutCameraPreviewBinding.inflate(layoutInflater, binding.flCameraPreview) + previewView = previewBinding.previewView.also { + it.updateLayoutParams { + width = 420.dp + height = 420.dp + } + } + cameraUtils.setPreviewController(previewView) + binding.btnBack.setOnClickListener { finish() } + binding.rvFoodCollection.let { + it.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false) + it.adapter = collectionAdapter + } + + binding.ivGoodsSearch.setOnClickListener { searchGoods() } + binding.etGoodsInput.let { v -> + v.addOnActionSearchListener { + searchGoods() + } + } + + binding.btnSave.setOnClickListener { + if (clickIndex == -1) { + Toast.makeText(this, "请选择物品名称", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + val count = collectList.count {it.bitmap!=null} + if (count == 0) { + Toast.makeText(this, "请拍摄物品照片", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + vectorThread() + } + binding.btnTakePhoto.clickWithDebounce { + takePhoto() + } + binding.btnAddDefault.clickWithDebounce { + Thread{ + FoodModule.initDefFoodData(this) { + runOnUiThread { + toast("添加完成") + } + } + }.start() + } + binding.btnRemoveDefault.clickWithDebounce { + if (box == null) { + box = ObjectBox.boxStore.boxFor(Food::class) + } + val list = box?.all?.filter { it.foodIdx == FoodModule.DEFAULT_FOOD_INDEX } + if (list.isNullOrEmpty()) { + toast("不存在默认数据") + return@clickWithDebounce + } + box?.removeByIds(list!!.map { it.id }) + toast("移除完成") + } + binding.btnClearData.setOnClickListener { clearData() } + binding.rvSearch.let { + it.layoutManager = GridLayoutManager(this, 2, LinearLayoutManager.VERTICAL, false) + it.adapter = searchAdapter + } + binding.refreshLayout.let { + it.setEnableRefresh(true) + it.setEnableLoadMore(false) + it.setOnRefreshListener { + pageNo = 1 + searchGoods() + } + it.setOnLoadMoreListener { + searchGoods() + } + } + loadEmptyView() + } + + private var pageNo = 1 + private var clickIndex = -1 + + private val searchGoodsList: MutableList = mutableListOf() + private val searchAdapter by lazy { + GoodsSearchAdapter(searchGoodsList).apply { + isStateViewEnable = true + setOnItemClickListener { adapter, view, position -> + clickIndex = position + if (list[position].isSelected) { + return@setOnItemClickListener + } + list.forEach { item -> + item.isSelected = false + } + list[position].isSelected = true + notifyDataSetChanged() + } + } + } + + private fun finishRefresh() { + binding.refreshLayout.let { + if (pageNo == 1) { + it.finishRefresh(500) + } else { + it.finishLoadMore(500) + } + } + } + + @SuppressLint("NotifyDataSetChanged") + private fun takePhoto() { + val count = collectList.count { it.bitmap != null } + if (count == 6) { + toast("每次只允许保存6条数据") + return + } + cameraUtils.takePhoto(cameraCallback) + } + + @SuppressLint("NotifyDataSetChanged") + private fun clearData() { + collectList.forEach { + it.bitmap = null + it.isShowCamera = true + it.isFinish = false + } + collectionAdapter.notifyDataSetChanged() + + clickIndex = -1 + binding.etGoodsInput.setText("") + searchGoodsList.clear() + searchAdapter.notifyDataSetChanged() + loadEmptyView() + } + + private val cameraCallback:(Uri) -> Unit = { uri-> + val index = collectList.indexOfFirst { it.bitmap == null } + if (index == -1) { + toast("每次只允许保存6条数据") + rerurn@cameraCallback + } + ImageUtil.uriToBitmap(this, uri)?.let { bitmap -> + val cropBitmap = BitmapCropper.cropCenter( + original = bitmap, + targetWidth = 1000, targetHeight = 1300, + offsetX = 30, offsetY = 100 + ) + val file = BitmapSaver.saveToAppFilesDir( + cropBitmap, this, "IMG_CROP_${System.currentTimeMillis()}.jpg" + ) + Timber.d("${this.javaClass.simpleName}-searchFood-裁剪bitmap保存文件路径:${file?.absolutePath}") + + collectList[index].let { + it.bitmap = cropBitmap + it.isShowCamera = false + } + collectionAdapter.notifyItemChanged(index) +// if (collectList.size < 6) { +// collectList.add(collectList.size - 1, FoodCollectionBean(bitmap = cropBitmap)) +// } else { +// collectList[collectList.size - 1] = FoodCollectionBean(bitmap = cropBitmap) +// } +// adapter.notifyDataSetChanged() + } + } + + private fun vectorThread() { + Loading.show(this) + Thread { + collectList.filter { it.bitmap != null } + .forEachIndexed { index, it -> + image2VectorTask(it.bitmap!!, index) + } + runOnUiThread { + window.decorView.postDelayed({ + Loading.dismiss() + toast("保存成功") + }, 1000) + } + }.start() + } + + private fun image2VectorTask(bitmap: Bitmap, position: Int) { + if (box == null) { + box = ObjectBox.boxStore.boxFor(Food::class) + } + val imageVector = FoodModule.bitmap2FloatArray(bitmap) + box?.put(Food(name = searchGoodsList[clickIndex].goodsName, foodIdx = 0, foodVector = imageVector)) + collectList[position].let { + it.imageVector = imageVector + it.isFinish = true + } + runOnUiThread { + collectionAdapter.notifyItemChanged(position) + } + } + + @SuppressLint("NotifyDataSetChanged") + private fun searchGoods() { + val searchName = binding.etGoodsInput.text.toString().trim() + if (searchName.isBlank()) { + toast("请输入物品名称") + finishRefresh() + return + } + searchGoods( + searchName = searchName, + pageNo = pageNo + ) { records -> + finishRefresh() + binding.etGoodsInput.hideKeyboard() + if (pageNo == 1) { + searchGoodsList.clear() + } + searchGoodsList.addAll(records) + if (searchGoodsList.isEmpty()) { + loadEmptyView() + return@searchGoods + } + val enableLoadMore = records.size >= PAGE_SIZE + binding.refreshLayout.setEnableLoadMore(enableLoadMore) + if (enableLoadMore) { + pageNo++ + } + binding.rvSearch.layoutManager = + GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false) + searchAdapter.notifyDataSetChanged() + } + } + + private var emptyBinding: LayoutEmptySearchBinding? = null + private fun loadEmptyView() { + binding.rvSearch.layoutManager = + LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + if (emptyBinding == null) { + emptyBinding = LayoutEmptySearchBinding.inflate(layoutInflater, binding.rvSearch, false) + } + emptyBinding?.root?.let { layout -> + layout.setOnClickListener { layout.hideKeyboard() } + searchAdapter.stateView = layout + } + } + fun searchGoods( + searchName: String, + pageNo: Int, + pageSize: Int = PAGE_SIZE, + callback: (List) -> Unit + ) { + runBlocking { + val records = viewModel.searchGoodsInfoList2( + goodsName = searchName, + pageNo = pageNo, + pageSize = pageSize + ) + runOnUiThread { + callback(records) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt index 4c4fff9..235efbf 100644 --- a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt @@ -114,12 +114,23 @@ abstract class GoodsListActivity : ComponentActivity() { dropdownPopup?.showAsDropDown(v) } binding.tvPurchaseNo.setOnClickListener { + isShowRecognizeDialog = false GoodsRecognizeDialog( context = this, list = mutableListOf() ) { GoodsSearchDialog(this).show() - }.show() + }.apply { + setOnDismissListener { + isShowRecognizeDialog = true + } + setOnShowListener { + isShowRecognizeDialog = false + } + if (isFinishing.not() && isDestroyed.not()) { + show() + } + } } binding.tvUserName.text = GlobalData.deviceId binding.tvUserName.gone() @@ -183,7 +194,7 @@ abstract class GoodsListActivity : ComponentActivity() { } } - private var isShowRecognizeDialog = true + var isShowRecognizeDialog = true private fun searchFood(uri: Uri) { ImageUtil.uriToBitmap(this, uri)?.let { bitmap -> val newBmp = BitmapCropper.cropCenter( @@ -214,7 +225,11 @@ abstract class GoodsListActivity : ComponentActivity() { } } - private fun handleGoodsResult(goodsList: List, file: File?, name: String) { + private fun handleGoodsResult( + goodsList: List, + file: File?, + name: String + ) { runOnUiThread { if (goodsRecognizeDialog?.isShowing == true) { isShowRecognizeDialog = false @@ -276,12 +291,18 @@ abstract class GoodsListActivity : ComponentActivity() { //isCameraReady = false } - fun Double?.plus2(value:Double?):Double { - return (this?:0.0) + (value?:0.0) + fun Double?.plus2(value: Double?): Double { + return (this ?: 0.0) + (value ?: 0.0) } fun addGoods(goods: GoodsInfo) { - val item = goodsList.firstOrNull {it.goodId == goods.goodId} + if (!isReceiptPage) { + goods.isSelected = true + goodsList.add(goods) + binding.rvGoodsList.adapter?.notifyItemInserted(goodsList.size - 1) + return + } + val item = goodsList.firstOrNull { it.goodId == goods.goodId } if (item == null) { goods.isSelected = true goodsList.add(goods) @@ -291,12 +312,12 @@ abstract class GoodsListActivity : ComponentActivity() { item.isSelected = true val finalNum = item.receivedNum.plus2(goods.receivedNum) val finalAmount = item.recUnitPriceTaxIn.plus2(goods.recUnitPriceTaxIn) - 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 - receiveCountAll = finalAmount recUnitPriceTaxIn = goods.recUnitPriceTaxIn - receivePriceIn = finalPrice.toSafeDouble() + recPriceInItem = finalPrice.toSafeDouble() goodsWeight = goods.goodsWeight } binding.rvGoodsList.adapter?.notifyItemChanged(goodsList.indexOf(item)) @@ -376,20 +397,18 @@ abstract class GoodsListActivity : ComponentActivity() { toast("请选择仓库") return } - val submitData = goodsList.filter { it.isSelected }.also { - it.forEach { goodsInfo -> - goodsInfo.warehouseId = binding.tvWareHouse.tag.toString() - goodsInfo.warehouseName = binding.tvWareHouse.text.toString() - } + goodsList.forEach { goodsInfo -> + goodsInfo.warehouseId = binding.tvWareHouse.tag.toString() + goodsInfo.warehouseName = binding.tvWareHouse.text.toString() } - if (submitData.isEmpty()) { + if (goodsList.isEmpty()) { toast("请选择收货物品") return } val uploadInfo = UploadInfo( id = id, supplierId = supplierId, - receiveGoodsInfos = submitData + receiveGoodsInfos = goodsList ) Timber.tag("SelfProcurementActivity") .d("receiptSubmit确认收货提交数据:${uploadInfo.toJsonString()}") @@ -413,9 +432,9 @@ abstract class GoodsListActivity : ComponentActivity() { goodsId = it.goodId ?: "", goodsName = it.goodName, kcUnitId = it.kcUnitId, - goodsCount = it.receiveCount ?: 0.0, - goodsUnitPrice = it.recUnitPriceTaxIn ?: 0.0, - goodsPrice = it.recPriceExItem ?: 0.0, + goodsCount = it.goodsCount ?: 0.0, + goodsUnitPrice = it.goodsUnitPrice ?: 0.0, + goodsPrice = it.goodsPrice ?: 0.0, //goodPurId = it.goodsPurId, warehouseId = binding.tvWareHouse.tag.toString(), buyToInventoryValue = it.consumeValue ?: "" diff --git a/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt b/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt index 08db23b..83c7320 100644 --- a/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/ReceiptActivity.kt @@ -50,6 +50,9 @@ class ReceiptActivity : GoodsListActivity() { } binding.tvPurchaseNo.text = "采购单号:${detail.purCode}" val list = detail.receiveGoodsInfoList + list.forEach { goodsInfo -> + goodsInfo.recUnitPriceTaxIn2 = goodsInfo.recUnitPriceTaxIn + } goodsList.addAll(list) adapter.notifyDataSetChanged() val confirmOrderCount = list.count { it.isAdjusted } diff --git a/app/src/main/java/com/sw/inbound/adapter/FoodCollectionAdapter.kt b/app/src/main/java/com/sw/inbound/adapter/FoodCollectionAdapter.kt new file mode 100644 index 0000000..a49ea57 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/adapter/FoodCollectionAdapter.kt @@ -0,0 +1,47 @@ +package com.sw.inbound.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import coil.load +import com.chad.library.adapter4.BaseQuickAdapter +import com.chad.library.adapter4.viewholder.QuickViewHolder +import com.sw.inbound.R +import com.sw.inbound.databinding.ListItemFoodCollectionBinding +import com.sw.inbound.objbox.FoodCollectionBean +import kotlin.let +import kotlin.run + +class FoodCollectionAdapter (var list: MutableList) : + BaseQuickAdapter(list) { + + inner class VH(var binding: ListItemFoodCollectionBinding) : QuickViewHolder(binding.root) + + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val inflater = LayoutInflater.from(context) + val binding = ListItemFoodCollectionBinding.inflate(inflater, parent, false) + return VH(binding) + } + + override fun onBindViewHolder(holder: VH, position: Int, item: FoodCollectionBean?) { + val binding = holder.binding + item?.let { + binding.ivFinish.visibility = if (it.isFinish) View.VISIBLE else View.GONE + binding.ivDelete.visibility = if (it.isShowCamera) View.GONE else View.VISIBLE + binding.imageView.run { + if (it.isShowCamera) { + scaleType = ImageView.ScaleType.CENTER + setImageResource(R.mipmap.ic_camera256) + } else { + scaleType = ImageView.ScaleType.FIT_CENTER + //setImageURI(it.imageUri) + //load(it.bitmap) + setImageBitmap(it.bitmap!!) + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/adapter/ReceiptGoodsAdapter.kt b/app/src/main/java/com/sw/inbound/adapter/ReceiptGoodsAdapter.kt index 9a2195f..8ba1f37 100644 --- a/app/src/main/java/com/sw/inbound/adapter/ReceiptGoodsAdapter.kt +++ b/app/src/main/java/com/sw/inbound/adapter/ReceiptGoodsAdapter.kt @@ -12,7 +12,6 @@ import com.chad.library.adapter4.viewholder.QuickViewHolder import com.sw.inbound.R import com.sw.inbound.databinding.ListItemReceiptGoodsBinding import com.sw.inbound.ext.toSafeDouble -import com.sw.inbound.model.bean.ReceiptGoodsInfo import com.sw.inbound.model.response.GoodsInfo import com.sw.inbound.utils.ext.dp import com.sw.inbound.utils.ext.gone @@ -51,7 +50,7 @@ class ReceiptGoodsAdapter(var list: MutableList) : tvGoodsName.text = item.goodName.ifNullOrBlank("-") tvProcurementUnit.text = item.unitName.ifNullOrBlank("-") tvProcurementCount.text = item.receiveCount.ifNullOrZero("-") - tvProcurementPrice.text = item.recUnitPriceTaxIn.toSafeDouble(2).ifNullOrZero("-") + tvProcurementPrice.text = item.recUnitPriceTaxIn2.toSafeDouble(2).ifNullOrZero("-") tvProcurementAmount.text = item.recPriceExItem.toSafeDouble(2).ifNullOrZero("-") tvReceiptCount.text = item.receivedNum.toSafeDouble(2).ifNullOrZero("-") tvGoodsWeight.text = item.goodsWeight?.toDouble().toSafeDouble(2).ifNullOrZero("-") diff --git a/app/src/main/java/com/sw/inbound/adapter/SelfProcurementAdapter.kt b/app/src/main/java/com/sw/inbound/adapter/SelfProcurementAdapter.kt index 5522ae1..925b790 100644 --- a/app/src/main/java/com/sw/inbound/adapter/SelfProcurementAdapter.kt +++ b/app/src/main/java/com/sw/inbound/adapter/SelfProcurementAdapter.kt @@ -10,10 +10,12 @@ import androidx.recyclerview.widget.RecyclerView import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.viewholder.QuickViewHolder import com.sw.inbound.databinding.ListItemSelfProcurementBinding +import com.sw.inbound.ext.toSafeDouble import com.sw.inbound.model.response.GoodsInfo import com.sw.inbound.utils.ext.dp import com.sw.inbound.utils.ext.gone import com.sw.inbound.utils.ext.ifNullOrBlank +import com.sw.inbound.utils.ext.ifNullOrZero import com.sw.inbound.utils.ext.setShapeDrawable import com.sw.inbound.utils.ext.visible @@ -46,9 +48,9 @@ class SelfProcurementAdapter(var list: MutableList) : ) tvGoodsName.text = item.goodName.ifNullOrBlank("-") tvProcurementUnit.text = item.unitName.ifNullOrBlank("-") - tvProcurementCount.text = item.receiveCountStr.ifNullOrBlank("-") - tvProcurementPrice.text = item.recUnitPriceTaxInStr.ifNullOrBlank("-") - tvProcurementAmount.text = item.recPriceExItemStr.ifNullOrBlank("-") + tvProcurementCount.text = item.goodsCount.ifNullOrZero("-") + tvProcurementPrice.text = item.goodsUnitPrice.toSafeDouble(2).ifNullOrZero("-") + tvProcurementAmount.text = item.goodsPrice.toSafeDouble(2).ifNullOrZero("-") tvState.gone() ivState.visible() diff --git a/app/src/main/java/com/sw/inbound/dialog/GoodsRecognizeDialog.kt b/app/src/main/java/com/sw/inbound/dialog/GoodsRecognizeDialog.kt index 56378e8..07bda60 100644 --- a/app/src/main/java/com/sw/inbound/dialog/GoodsRecognizeDialog.kt +++ b/app/src/main/java/com/sw/inbound/dialog/GoodsRecognizeDialog.kt @@ -75,6 +75,7 @@ class GoodsRecognizeDialog( } binding.btnAgainRecognize.setOnClickListener { dismiss() + activity?.isShowRecognizeDialog = true activity?.recognizeFood() } } diff --git a/app/src/main/java/com/sw/inbound/dialog/GoodsStoreDialog.kt b/app/src/main/java/com/sw/inbound/dialog/GoodsStoreDialog.kt index 53eec23..c3b3636 100644 --- a/app/src/main/java/com/sw/inbound/dialog/GoodsStoreDialog.kt +++ b/app/src/main/java/com/sw/inbound/dialog/GoodsStoreDialog.kt @@ -185,6 +185,13 @@ class GoodsStoreDialog( context.toast("请录入入库单价") return } + if (realWeight <= 0) { + context.toast("物品重量需大于0") + return + } + val count = countText.toDoubleOrNull() + val price = priceText.toDoubleOrNull() + val totalPrice = amountText.toDoubleOrNull() confirmBlock( GoodsInfo( goodId = goods.id, @@ -193,11 +200,15 @@ class GoodsStoreDialog( //goodsPurId = binding.tvProcurementUnit.tag.toString(), kcUnitId = binding.tvProcurementUnit.tag.toString(), unitName = unit, - receivedNum = countText.toDoubleOrNull(), - recUnitPriceTaxIn = priceText.toDoubleOrNull(), - receivePriceIn = amountText.toDoubleOrNull(), + receivedNum = count, + recUnitPriceTaxIn = price, + recPriceInItem = totalPrice, goodsWeight = realWeight.toBigDecimal(), - isLocalGoods = true + isLocalGoods = true, + + goodsCount = count, + goodsUnitPrice = price, + goodsPrice = totalPrice, ) ) dismiss() diff --git a/app/src/main/java/com/sw/inbound/dialog/LoadingDialog.kt b/app/src/main/java/com/sw/inbound/dialog/LoadingDialog.kt new file mode 100644 index 0000000..444ca18 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/dialog/LoadingDialog.kt @@ -0,0 +1,148 @@ +package com.sw.inbound.dialog + +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 + +object Loading { + + private var dialog: LoadingDialog? = null + + fun show(context: Context) { + try { + if (dialog?.isShowing == true) { + dialog?.dismiss() + } + + if (dialog == null) { + dialog = LoadingDialog(context) + } + dialog?.show() + } catch (e: Exception) { + e.printStackTrace() + } + } + + fun dismiss() { + try { + dialog?.let { + if (it.isShowing) { + it.dismiss() + } + } + dialog = null + } catch (e: Exception) { + e.printStackTrace() + } + } + +} + +class LoadingDialog( + context: Context, + message: String = "加载中……", + private var onDismiss: () -> Unit = {} +) : Dialog(context, R.style.LoadingDialog) { + init { + 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() + } + } +} + +//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) +// } +// +//} diff --git a/app/src/main/java/com/sw/inbound/model/bean/DataBean.kt b/app/src/main/java/com/sw/inbound/model/bean/DataBean.kt deleted file mode 100644 index a462ee6..0000000 --- a/app/src/main/java/com/sw/inbound/model/bean/DataBean.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.sw.inbound.model.bean - -data class ReceiptGoodsInfo( - var goodsId: String? = "", - var goodsName: String? = "", - var procurementUnit: String? = "", - var procurementCount: Int? = 0, - var procurementPrice: Double? = 0.0, - var procurementAmount: Double? = 0.0, - var receiptCount: Int? = 0, - var goodsWeight: Int? = 0, - var goodsState: String? = "", - var isSelected: Boolean = false, - var isLocalGoods: Boolean = false -) - -//data class DropdownInfo( -// var id: String, -// var name: String -//) - -//data class RecognizeResult( -// var name: String? = null, -// var image: String? = null, -// var isSelected: Boolean = false -//) - -//data class GoodsSearchInfo( -// var id: String? = null, -// var name: String? = null, -// var isSelected: Boolean = false -//) - -data class OperateBean( - var obj: Any? = null, - var typeList: MutableList = mutableListOf(), - var isSelected: Boolean = false, - var isLocalGoods: Boolean = false, - var isReceiptPage: Boolean = true -) - -data class OperateType( - var value: String = "", - var width: Int = 0, - var textColor: String = "#FF999999", - var isBoldFont: Boolean = false, - var isShowIcon: Boolean = false -) \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/model/response/GoodsInfo.kt b/app/src/main/java/com/sw/inbound/model/response/GoodsInfo.kt index ccc9e69..7fd91ef 100644 --- a/app/src/main/java/com/sw/inbound/model/response/GoodsInfo.kt +++ b/app/src/main/java/com/sw/inbound/model/response/GoodsInfo.kt @@ -29,6 +29,7 @@ data class GoodsInfo( * 单价 */ var recUnitPriceTaxIn: Double? = null, + var recUnitPriceTaxIn2: Double? = null, // 单价 界面显示 var recUnitPriceTaxInTemp: String = "", @@ -103,7 +104,10 @@ data class GoodsInfo( var isLocalGoods: Boolean = false, var kcUnitId: String?="", - var receivePriceIn:Double?=null + var recPriceInItem:Double?=null, + var goodsCount:Double?=null, + var goodsUnitPrice:Double?=null, + var goodsPrice:Double?=null //-------------------------------------------------------- ) : Parcelable, BaseBean() { diff --git a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt index b9f46dc..53b2c1a 100644 --- a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt +++ b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt @@ -19,6 +19,7 @@ class RequestInterceptor : Interceptor { .header("deviceId", GlobalData.deviceId) .header("X-DEVICE-CODE", GlobalData.deviceId) .header("x-access-token", GlobalData.appToken) + .header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d") // .header("Authorization", "Bearer ${getToken()}") // .header("x-access-token", getToken()) diff --git a/app/src/main/java/com/sw/inbound/objbox/DataBean.kt b/app/src/main/java/com/sw/inbound/objbox/DataBean.kt index 87443eb..ff03ab1 100644 --- a/app/src/main/java/com/sw/inbound/objbox/DataBean.kt +++ b/app/src/main/java/com/sw/inbound/objbox/DataBean.kt @@ -16,3 +16,50 @@ data class FoodCollectionBean( var isShowCamera: Boolean = false, var isFinish:Boolean = false ) + +data class ReceiptGoodsInfo( + var goodsId: String? = "", + var goodsName: String? = "", + var procurementUnit: String? = "", + var procurementCount: Int? = 0, + var procurementPrice: Double? = 0.0, + var procurementAmount: Double? = 0.0, + var receiptCount: Int? = 0, + var goodsWeight: Int? = 0, + var goodsState: String? = "", + var isSelected: Boolean = false, + var isLocalGoods: Boolean = false +) + +//data class DropdownInfo( +// var id: String, +// var name: String +//) + +//data class RecognizeResult( +// var name: String? = null, +// var image: String? = null, +// var isSelected: Boolean = false +//) + +//data class GoodsSearchInfo( +// var id: String? = null, +// var name: String? = null, +// var isSelected: Boolean = false +//) + +data class OperateBean( + var obj: Any? = null, + var typeList: MutableList = mutableListOf(), + var isSelected: Boolean = false, + var isLocalGoods: Boolean = false, + var isReceiptPage: Boolean = true +) + +data class OperateType( + var value: String = "", + var width: Int = 0, + var textColor: String = "#FF999999", + var isBoldFont: Boolean = false, + var isShowIcon: Boolean = false +) diff --git a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt index c208d53..489da9f 100644 --- a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt +++ b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt @@ -28,17 +28,18 @@ object FoodModule { private lateinit var classInfo: FoodClassInfo val NO_MEAN_RGB = floatArrayOf(0.0f, 0.0f, 0.0f) val NO_STD_RGB = floatArrayOf(1.0f, 1.0f, 1.0f) + val DEFAULT_FOOD_INDEX = -1 fun init(context: Context) { 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.isEmpty()) { - initFoodData(context) - } + //if (box.all.isNotEmpty()) { + // box.removeAll() + //} + //if (box.all.isEmpty()) { + // initDefFoodData(context) + //} }.start() } @@ -100,10 +101,10 @@ object FoodModule { } - private fun initFoodData(context: Context) { - if (box.all.isNotEmpty()) { - return - } + fun initDefFoodData(context: Context, action:()-> Unit={}) { + //if (box.all.isNotEmpty()) { + // return + //} val embeddingsJson = AssetsTool.readAssetsFile(context, "data/embeddings.json") val labelsJson = AssetsTool.readAssetsFile(context, "data/labels.json") val classInfoJson = AssetsTool.readAssetsFile(context, "data/class_info.json") @@ -119,8 +120,9 @@ object FoodModule { val classIdx = labelsList[index] val foodName = foodMap["$classIdx"] val array = floatList.toFloatArray() - box.put(Food(name = foodName, foodVector = array, foodIdx = index)) + box.put(Food(name = foodName, foodVector = array, foodIdx = DEFAULT_FOOD_INDEX)) } + action() } diff --git a/app/src/main/java/com/sw/inbound/ui/page/PurchaseOrderScreen.kt b/app/src/main/java/com/sw/inbound/ui/page/PurchaseOrderScreen.kt index 630dbe9..da4dc75 100644 --- a/app/src/main/java/com/sw/inbound/ui/page/PurchaseOrderScreen.kt +++ b/app/src/main/java/com/sw/inbound/ui/page/PurchaseOrderScreen.kt @@ -151,17 +151,17 @@ fun PurchaseOrderScreen( contentPadding = PaddingValues(16.dp), horizontalArrangement = Arrangement.spacedBy(30.dp) ) { - items(items = products, key = { it!!.id?:"" }) { - PurchaseOrderItem(it!!) { - navController.navigate( - Screen.ReceiptProduct.createRoute( - it.id, - it.supplierId - ) - ) + items(items = products, key = { it!!.id?:"" }) { product -> + PurchaseOrderItem(product!!) { +// navController.navigate( +// Screen.ReceiptProduct.createRoute( +// it.id, +// it.supplierId +// ) +// ) navController.context.startActivity { - putExtra(GoodsListActivity.ID,it!!.id) - putExtra(GoodsListActivity.SUPPLIER_ID,it.supplierId) + putExtra(GoodsListActivity.ID,product!!.id) + putExtra(GoodsListActivity.SUPPLIER_ID,product.supplierId) putExtra(GoodsListActivity.IS_RECEIPT_PAGE,true) putExtra(GoodsListActivity.IS_NEW_RECEIPT,false) } diff --git a/app/src/main/java/com/sw/inbound/ui/weight/TopTitleBar.kt b/app/src/main/java/com/sw/inbound/ui/weight/TopTitleBar.kt index 92bd45b..1994788 100644 --- a/app/src/main/java/com/sw/inbound/ui/weight/TopTitleBar.kt +++ b/app/src/main/java/com/sw/inbound/ui/weight/TopTitleBar.kt @@ -1,5 +1,6 @@ package com.sw.inbound.ui.weight +import android.content.Intent import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -12,6 +13,8 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -28,11 +31,14 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.sw.inbound.MyApp import com.sw.inbound.R +import com.sw.inbound.activity.FoodCollectionActivity import com.sw.inbound.ext.medium import com.sw.inbound.model.response.User import com.sw.inbound.ui.theme.AppTypography import com.sw.inbound.utils.DateTimeUtils +import com.sw.inbound.utils.ext.startActivity import kotlinx.coroutines.delay @@ -77,9 +83,20 @@ fun TopTitleBar( color = colorResource(R.color.title), fontSize = 36.sp ), - modifier = Modifier.weight(1f) + modifier = Modifier.wrapContentSize() + .clickable(onClick = { + MyApp.instance?.run { + startActivity( + Intent(this, FoodCollectionActivity::class.java).apply{ + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) + } + }) ) + Spacer(modifier = Modifier.weight(1f)) + if (user != null) { Row( verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/java/com/sw/inbound/utils/CameraUtils.kt b/app/src/main/java/com/sw/inbound/utils/CameraUtils.kt index fe43eb0..9f823d4 100644 --- a/app/src/main/java/com/sw/inbound/utils/CameraUtils.kt +++ b/app/src/main/java/com/sw/inbound/utils/CameraUtils.kt @@ -1,17 +1,18 @@ package com.sw.inbound.utils import android.net.Uri +import androidx.activity.ComponentActivity 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) { +class CameraUtils(private var activity: ComponentActivity) { private var cameraController: LifecycleCameraController? = null private var photoCaptureHelper: PhotoCaptureHelper? = null -// private var isCameraReady = false + + // private var isCameraReady = false fun takePhoto(callback: (Uri) -> Unit) { cameraController?.let { if (photoCaptureHelper == null) { @@ -69,6 +70,7 @@ class CameraUtils(private var activity: GoodsListActivity) { fun bind() { cameraController?.bindToLifecycle(activity) } + fun unbind() { cameraController?.unbind() } diff --git a/app/src/main/java/com/sw/inbound/viewmodel/ReceiptViewModel.kt b/app/src/main/java/com/sw/inbound/viewmodel/ReceiptViewModel.kt index 00a008f..57c8a53 100644 --- a/app/src/main/java/com/sw/inbound/viewmodel/ReceiptViewModel.kt +++ b/app/src/main/java/com/sw/inbound/viewmodel/ReceiptViewModel.kt @@ -1,31 +1,14 @@ package com.sw.inbound.viewmodel import android.net.Uri -import android.util.Log -import androidx.lifecycle.viewModelScope -import com.sw.inbound.ext.toFormattedString -import com.sw.inbound.ext.toSafeBigDecimal -import com.sw.inbound.ext.toSafeDouble -import com.sw.inbound.ext.toSafeFloat import com.sw.inbound.model.request.GoodsAddParam import com.sw.inbound.model.request.PurchaseWarehouseParam import com.sw.inbound.model.request.UploadInfo -import com.sw.inbound.model.response.DictType -import com.sw.inbound.model.response.GoodsInfo import com.sw.inbound.model.response.PurchaseInfo import com.sw.inbound.model.response.SearchGoodsInfo import com.sw.inbound.repository.RemoteRepository -import com.sw.inbound.utils.ToastUtils import com.sw.inbound.utils.ext.toJsonString import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -37,72 +20,72 @@ class ReceiptViewModel @Inject constructor( private val repository: RemoteRepository ) : BaseViewModel(repository) { // 调整状态 - private val _adjustState = MutableStateFlow(true) - val adjustState: StateFlow = _adjustState +// private val _adjustState = MutableStateFlow(true) +// val adjustState: StateFlow = _adjustState +// +// private val _showReceiptDialog = MutableStateFlow(false) +// val showReceiptDialog: StateFlow = _showReceiptDialog +// +// // 当前要收货的供应商 +// private val _currentPurchaseInfo = MutableStateFlow(null) +// val currentPurchaseInfo: StateFlow = _currentPurchaseInfo +// +// private val _orders = MutableStateFlow>(emptyList()) +// val orders: StateFlow> = _orders.asStateFlow() - private val _showReceiptDialog = MutableStateFlow(false) - val showReceiptDialog: StateFlow = _showReceiptDialog +// fun initOrders() { +// _orders.value = _currentPurchaseInfo.value?.receiveGoodsInfoList ?: emptyList() +// } +// +// // 已调整列表 +// val adjustedOrders: StateFlow> = _orders +// .map { orders -> orders.filter { it.isAdjusted } } +// .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) +// +// // 未调整列表 +// val unadjustedOrders: StateFlow> = _orders +// .map { orders -> orders.filter { !it.isAdjusted } } +// .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) +// +// // 选中的商品 +// private val _selectedItem = MutableStateFlow(null) +// val selectedItem: StateFlow = _selectedItem +// +// // 收货请求结果 +// private val _receiptResult = MutableStateFlow(false) +// val receiptResult: StateFlow = _receiptResult +// +// // 物品数量 是否由用户输入 +// private val _countUserInput = MutableStateFlow(false) +// private val _priceUserInput = MutableStateFlow(false) +// private val _amountUserInput = MutableStateFlow(false) - // 当前要收货的供应商 - private val _currentPurchaseInfo = MutableStateFlow(null) - val currentPurchaseInfo: StateFlow = _currentPurchaseInfo - - private val _orders = MutableStateFlow>(emptyList()) - val orders: StateFlow> = _orders.asStateFlow() - - fun initOrders() { - _orders.value = _currentPurchaseInfo.value?.receiveGoodsInfoList ?: emptyList() - } - - // 已调整列表 - val adjustedOrders: StateFlow> = _orders - .map { orders -> orders.filter { it.isAdjusted } } - .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) - - // 未调整列表 - val unadjustedOrders: StateFlow> = _orders - .map { orders -> orders.filter { !it.isAdjusted } } - .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) - - // 选中的商品 - private val _selectedItem = MutableStateFlow(null) - val selectedItem: StateFlow = _selectedItem - - // 收货请求结果 - private val _receiptResult = MutableStateFlow(false) - val receiptResult: StateFlow = _receiptResult - - // 物品数量 是否由用户输入 - private val _countUserInput = MutableStateFlow(false) - private val _priceUserInput = MutableStateFlow(false) - private val _amountUserInput = MutableStateFlow(false) - - /** - * 更新调整状态 - * @param isAdjustState true 已调整 false 未调整 - */ - fun updateAdjustState(isAdjustState: Boolean) { - _adjustState.value = isAdjustState - } - - fun StateFlow>.getValidOrders(): List { - return this.value.filter { it.goodId != null } - } - - /** - * 更新收货提示弹窗 - */ - fun updateReceiptDialog(showDialog: Boolean) { - if (_orders.getValidOrders().isEmpty()) { - ToastUtils.showToast("订单为空或包含异常数据") - return - } -// if (!unadjustedOrders.value.isEmpty()) { -// ToastUtils.showToast("请先确认物品信息") +// /** +// * 更新调整状态 +// * @param isAdjustState true 已调整 false 未调整 +// */ +// fun updateAdjustState(isAdjustState: Boolean) { +// _adjustState.value = isAdjustState +// } +// +// fun StateFlow>.getValidOrders(): List { +// return this.value.filter { it.goodId != null } +// } +// +// /** +// * 更新收货提示弹窗 +// */ +// fun updateReceiptDialog(showDialog: Boolean) { +// if (_orders.getValidOrders().isEmpty()) { +// ToastUtils.showToast("订单为空或包含异常数据") // return // } - _showReceiptDialog.value = showDialog - } +//// if (!unadjustedOrders.value.isEmpty()) { +//// ToastUtils.showToast("请先确认物品信息") +//// return +//// } +// _showReceiptDialog.value = showDialog +// } // fun updateSelectedItemWithSwitch(purchaseOrder: GoodsInfo?) { // viewModelScope.launch { @@ -159,48 +142,48 @@ class ReceiptViewModel @Inject constructor( val response = repository.getReceiveDetail(id) if (parseResponse(response)) { action(response.result) - _currentPurchaseInfo.value = response.result - initOrders() +// _currentPurchaseInfo.value = response.result +// initOrders() } } } - /** - * 更新当前供应商信息 - */ - fun updateCurrentPurchaseInfo(purchaseInfo: PurchaseInfo?) { - _currentPurchaseInfo.value = purchaseInfo - } - - // 添加订单 - fun addPurchaseItem(purchaseOrder: GoodsInfo) { - _orders.update { currentList -> - // 当已经添加过则忽略 - if (currentList.any { it.goodId == purchaseOrder.goodId }) { - currentList - } else { - currentList + purchaseOrder - } - } - } - - // 更新订单 - fun updatePurchaseItem(purchaseOrder: GoodsInfo) { - _orders.update { currentList -> - currentList.map { order -> - if (order.id == purchaseOrder.id) purchaseOrder else order - } - } - } - - /** - * 有异常的订单数量 - */ - fun hasWrongCount(): Boolean { - return _orders.value.any { - it.receiveCount != it.receivedNum - } - } +// /** +// * 更新当前供应商信息 +// */ +// fun updateCurrentPurchaseInfo(purchaseInfo: PurchaseInfo?) { +// _currentPurchaseInfo.value = purchaseInfo +// } +// +// // 添加订单 +// fun addPurchaseItem(purchaseOrder: GoodsInfo) { +// _orders.update { currentList -> +// // 当已经添加过则忽略 +// if (currentList.any { it.goodId == purchaseOrder.goodId }) { +// currentList +// } else { +// currentList + purchaseOrder +// } +// } +// } +// +// // 更新订单 +// fun updatePurchaseItem(purchaseOrder: GoodsInfo) { +// _orders.update { currentList -> +// currentList.map { order -> +// if (order.id == purchaseOrder.id) purchaseOrder else order +// } +// } +// } +// +// /** +// * 有异常的订单数量 +// */ +// fun hasWrongCount(): Boolean { +// return _orders.value.any { +// it.receiveCount != it.receivedNum +// } +// } /** * 更新所有商品仓库 @@ -223,31 +206,31 @@ class ReceiptViewModel @Inject constructor( // } // } - // 清空列表 - fun clearPurchaseOrders() { - _orders.value = emptyList() - } - - /** - * 更新数量输入状态 - */ - fun updateCountInputState(boolean: Boolean) { - _countUserInput.value = boolean - } - - /** - * 更新单价输入状态 - */ - fun updatePriceInputState(boolean: Boolean) { - _priceUserInput.value = boolean - } - - /** - * 更新金额输入状态 - */ - fun updateAmountInputState(boolean: Boolean) { - _amountUserInput.value = boolean - } +// // 清空列表 +// fun clearPurchaseOrders() { +// _orders.value = emptyList() +// } +// +// /** +// * 更新数量输入状态 +// */ +// fun updateCountInputState(boolean: Boolean) { +// _countUserInput.value = boolean +// } +// +// /** +// * 更新单价输入状态 +// */ +// fun updatePriceInputState(boolean: Boolean) { +// _priceUserInput.value = boolean +// } +// +// /** +// * 更新金额输入状态 +// */ +// fun updateAmountInputState(boolean: Boolean) { +// _amountUserInput.value = boolean +// } //private var weightCallback: ((Int) -> Unit)? = null //fun readWeight(callback: (Int) -> Unit) { @@ -318,25 +301,25 @@ class ReceiptViewModel @Inject constructor( // } } - fun partialReceipt(uploadInfo: UploadInfo) { - launchWithLoading { - val response = repository.partialReceipt(uploadInfo) - if (parseResponse(response)) { - ToastUtils.showToast("部分收货成功") - _receiptResult.value = true - } - } - } - - fun confirmReceipt(uploadInfo: UploadInfo) { - launchWithLoading { - val response = repository.confirmReceipt(uploadInfo) - if (parseResponse(response)) { - ToastUtils.showToast("收货成功") - _receiptResult.value = true - } - } - } +// fun partialReceipt(uploadInfo: UploadInfo) { +// launchWithLoading { +// val response = repository.partialReceipt(uploadInfo) +// if (parseResponse(response)) { +// ToastUtils.showToast("部分收货成功") +// _receiptResult.value = true +// } +// } +// } +// +// fun confirmReceipt(uploadInfo: UploadInfo) { +// launchWithLoading { +// val response = repository.confirmReceipt(uploadInfo) +// if (parseResponse(response)) { +// ToastUtils.showToast("收货成功") +// _receiptResult.value = true +// } +// } +// } fun confirmReceipt(uploadInfo: UploadInfo, callback: (Boolean) -> Unit) { launchWithLoading { diff --git a/app/src/main/res/drawable/bg_gray.xml b/app/src/main/res/drawable/bg_gray.xml new file mode 100644 index 0000000..e5df3c9 --- /dev/null +++ b/app/src/main/res/drawable/bg_gray.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_dialog.xml b/app/src/main/res/drawable/shape_dialog.xml new file mode 100644 index 0000000..c7e4546 --- /dev/null +++ b/app/src/main/res/drawable/shape_dialog.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_food_collection.xml b/app/src/main/res/layout/activity_food_collection.xml new file mode 100644 index 0000000..8ec622c --- /dev/null +++ b/app/src/main/res/layout/activity_food_collection.xml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_loading.xml b/app/src/main/res/layout/dialog_loading.xml new file mode 100644 index 0000000..67410fa --- /dev/null +++ b/app/src/main/res/layout/dialog_loading.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_food_collection.xml b/app/src/main/res/layout/list_item_food_collection.xml new file mode 100644 index 0000000..2567322 --- /dev/null +++ b/app/src/main/res/layout/list_item_food_collection.xml @@ -0,0 +1,32 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_goods_search.xml b/app/src/main/res/layout/list_item_goods_search.xml index 75378d8..34e46b5 100644 --- a/app/src/main/res/layout/list_item_goods_search.xml +++ b/app/src/main/res/layout/list_item_goods_search.xml @@ -16,6 +16,7 @@ android:textColor="#ff666666" android:textSize="30sp" android:maxLines="1" + android:layout_marginHorizontal="10dp" android:ellipsize="end" android:textStyle="bold" /> \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/ic_back.png b/app/src/main/res/mipmap-xxhdpi/ic_back.png new file mode 100644 index 0000000000000000000000000000000000000000..d7692ebe13ed4face435db761b10c3615abbac00 GIT binary patch literal 3082 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_camera256.png b/app/src/main/res/mipmap-xxhdpi/ic_camera256.png new file mode 100644 index 0000000000000000000000000000000000000000..cc72a98c88b416e2cb8ad5da2509ac3e73bea50c GIT binary patch literal 8661 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_delete_red.png b/app/src/main/res/mipmap-xxhdpi/ic_delete_red.png new file mode 100644 index 0000000000000000000000000000000000000000..ff006408948afbe088264f381ba30d05e12b3b7b GIT binary patch literal 1465 zcmbW1X*d)J9LE1MlP1$TrpWGyY$UT=j)szRveFo##gk*BDY>IDuE;Tz6_qQ>L}Qd| z<(PF98qJfU9mkN{7LtrL!%D`vn$`E+XP;+3y#M!o{=aYUhd23@-3b{C4g&x()+9@Z zO{ag+wym4D#q3-=fK-sRFF!CkvKBOqU8uHg`Tj3 z97Rg@UERWsU|m&E$RceE#sfB8-r&JD%K(#-TU(UIhMNM62{k$+=l&cR{g}HP`=Buc zyS5zLnK#5JAI)Rp%$atn&zN?t^%olmZ-4TM@FwQU7Oz43%Zw-1wX!Ot7NXMMIl_qHa6IStM}HKb+g8` z8)p1ye&fo7@VylGF_s@{1Q0rfGgXA^_2jA6bbpYikyef1lq%KNr$~zX!Co*UlOOtHP7FgaWVl zdKEO(hMgRa1(rs4r65zuH< zGHD8GCa;TM#Hc8IHUoK8%Gp(5Rb72Ph6W4N z$$iRDNOSPrV*q`vPMY)1GY=VsHNq>mQs4yhsO;!Eql>nSb} ziqW(9{{5kL$zfQ?(mh}51M~vTu?`u)ss9{>f*)*~8Ooql!KcrXw4edd;+K;lH2jJ+@v~B<$hyF~Mc;x>Ocgv$d_6l`8 zIaoC@`sRXBU!kl0k~!DIof8-}ac4L_%VR%kd}5H37BpvHN&OHu?)W||(=l_i`SLoQ z=~SM8=%02Q$^I1AbQbKNT0qw%{(HPPdL-Q_4{|N6K$ z&0Lf^iI2=3Nt}dq?x&_WW~%dP`$j(h%)1!@m#~m&GCSBR3Eu_NrG)&rjVJ8&^*ig) zE&b}ABAW=wADBUN*~?}|Y2F@3`5iI~=}#9$HVe}_o4YHKMBD67+YDR3EH4UnmuL)0 SM}>$sKVW^_&a%>ilJGZ=T#Z)% literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_finish.png b/app/src/main/res/mipmap-xxhdpi/ic_finish.png new file mode 100644 index 0000000000000000000000000000000000000000..7f433bf81c110bbe18ab54411375c96e66ab847b GIT binary patch literal 5509 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 975a495..bb7bf82 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -17,5 +17,6 @@ #D9E3F9 #141428 #96A0AA + #F6F6F6 \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 24709a0..9814017 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,9 +1,10 @@ - + + + \ No newline at end of file