接口联调

This commit is contained in:
2025-11-28 18:46:41 +08:00
parent 9bcd7c9983
commit 29188c5944
39 changed files with 1882 additions and 1662 deletions
@@ -11,7 +11,7 @@
//import com.sw.dualscreen.dialog.WarnDialog
//import com.sw.dualscreen.ext.addOnActionSearchListener
//import com.sw.dualscreen.ext.hideKeyboard
//import com.sw.dualscreen.objbox.CollectedFoodBean
//import com.sw.dualscreen.objbox.CollectedFoodInfo
//import com.sw.dualscreen.objbox.Food
//import com.sw.dualscreen.objbox.ObjectBox
//import com.sw.dualscreen.viewmodel.BaseViewModel
@@ -31,7 +31,7 @@
// return ActivityCollectedDataBinding.inflate(layoutInflater)
// }
//
// private val list: MutableList<CollectedFoodBean> = mutableListOf()
// private val list: MutableList<CollectedFoodInfo> = mutableListOf()
// private val adapter by lazy {
// CollectedFoodAdapter(list).apply {
// isStateViewEnable = true
@@ -88,7 +88,7 @@
// queryList = queryList?.filter { it.name?.contains(searchName) == true }
// }
// queryList?.forEach {
// list.add(CollectedFoodBean(foodName = it.name))
// list.add(CollectedFoodInfo(foodName = it.name))
// }
// adapter.notifyDataSetChanged()
// if (list.isEmpty()) {
@@ -11,7 +11,7 @@ import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
import com.sw.dualscreen.dialog.WarnDialog
import com.sw.dualscreen.ext.addOnActionSearchListener
import com.sw.dualscreen.ext.hideKeyboard
import com.sw.dualscreen.objbox.CollectedFoodBean
import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.viewmodel.BaseViewModel
@@ -30,7 +30,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
return ActivityCollectedFoodBinding.inflate(layoutInflater)
}
private val list: MutableList<CollectedFoodBean> = mutableListOf()
private val list: MutableList<CollectedFoodInfo> = mutableListOf()
private val adapter by lazy {
CollectedFoodNewAdapter(list).apply {
isStateViewEnable = true
@@ -88,7 +88,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
val totalList = box?.all
?.filter { it.name!=null }
?.groupBy { it.name!! }
?.map { CollectedFoodBean(foodName = it.key, count = it.value.size) }
?.map { CollectedFoodInfo(foodName = it.key, foodCount = it.value.size) }
//var queryMap:Map<String, List<Food>> ?= null
if (searchName.isNullOrBlank().not()) {
//queryMap = totalMap?.filter { it.key.contains(searchName) }
@@ -106,8 +106,19 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
loadEmptyView()
}
binding.root.hideKeyboard()
viewModel.getCollectedFoodList(pageNo = pageNo) {
if (it.isNotEmpty()) {
list.addAll(it)
runOnUiThread {
adapter.notifyDataSetChanged()
}
}
}
}
private var pageNo = 1
private var emptyBinding: LayoutEmptySearchBinding? = null
private fun loadEmptyView() {
if (emptyBinding == null) {
@@ -29,20 +29,23 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
override fun initialize() {
super.initialize()
val isSuccess = viewModel.checkEquipmentInfo()
if (isSuccess) {
binding.root.postDelayed({
goMainActivity()
return
}
binding.imgQr.setImageBitmap(
QRCodeUtil.generateQRCode(
content = GlobalData.deviceId,
size = 200
)
)
binding.initButton.setOnClickListener {
viewModel.getDeviceToken()
}
}, 1000)
// val isSuccess = viewModel.checkEquipmentInfo()
// if (isSuccess) {
// goMainActivity()
// return
// }
// binding.imgQr.setImageBitmap(
// QRCodeUtil.generateQRCode(
// content = GlobalData.deviceId,
// size = 200
// )
// )
// binding.initButton.setOnClickListener {
// viewModel.getDeviceToken()
// }
}
override fun registerDataChange() {
@@ -114,7 +114,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
private fun initData() {
viewModel.getEquipmentToken()
// viewModel.getEquipmentToken()
viewModel.getUserFaceCache(pageNo = 1)
// presentation?.step1()
presentation?.step1FoodRecognizing()
}
@@ -200,10 +201,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.tvFoodName.setOnClickListener {
SensorScaleUtils.zero()
}
binding.tvRescan.setOnClickListener {
debouncer.debounce { recognizeFood() }
}
// binding.tvRescan.setOnClickListener {
// debouncer.debounce { recognizeFood() }
// }
binding.btnPay.setOnClickListener {
if (checkedItem == null) {
ToastUtils.showToast("暂无识别数据,请搜索选择")
return@setOnClickListener
}
presentation?.dismiss()
startActivity(Intent(this, PayActivity::class.java).apply {
putExtra(PayActivity.FOOD_INFO, checkedItem)
@@ -317,9 +322,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (TextUtils.isEmpty(foodName)) {
LightManager.closeGreenLight()
LightManager.closeRedLight()
binding.layoutRescan.visibility = View.VISIBLE
//binding.layoutRescan.visibility = View.VISIBLE
binding.flPay.visible()
binding.tvToSearch.let {
it.text = "未识别到,去手动搜索"
it.visible()
}
} else {
binding.layoutRescan.visibility = View.GONE
//binding.layoutRescan.visibility = View.GONE
viewModel.getFoodInfo(foodName) { list ->
runOnUiThread {
updateFoodInfo(list.toMutableList(), scoreList)
@@ -367,7 +377,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
LightManager.closeRedLight()
binding.flPay.visible()
binding.tvToSearch.visible()
binding.tvToSearch.let {
it.text = "以上都不是,手动搜索"
it.visible()
}
} else {
binding.flPay.gone()
binding.tvToSearch.gone()
@@ -65,9 +65,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
if (binding.btnPayCash.isChecked) {
return@setOnClickListener
}
if (cashPayFragment == null) {
cashPayFragment = CashPayFragment()
}
cashPayFragment = CashPayFragment()
showFragment(cashPayFragment!!, TAG_PAY_CASH)
switchButton(false, true, false, false)
}
@@ -75,9 +73,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
if (binding.btnPayNumber.isChecked) {
return@setOnClickListener
}
if (numberPayFragment == null) {
numberPayFragment = NumberPayFragment()
}
numberPayFragment = NumberPayFragment()
showFragment(numberPayFragment!!, TAG_PAY_NUMBER)
switchButton(false, false, true, false)
}
@@ -92,9 +88,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
}
private fun showScanQrCodePay() {
if (qrCodePayFragment == null) {
qrCodePayFragment = ScanQrCodePayFragment()
}
qrCodePayFragment = ScanQrCodePayFragment()
showFragment(qrCodePayFragment!!, TAG_PAY_QR_CODE)
switchButton(true, false, false, false)
}
@@ -107,9 +101,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
}
fun showFacePay() {
if (facePayFragment == null) {
facePayFragment = FacePayFragment()
}
facePayFragment = FacePayFragment()
showFragment(facePayFragment!!, TAG_PAY_FACE)
switchButton(false, false, false, true)
}
@@ -149,9 +141,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
// }
fun showPayResult() {
if (payResultFragment == null) {
payResultFragment = PayResultFragment()
}
payResultFragment = PayResultFragment()
showFragment(payResultFragment!!, TAG_PAY_RESULT)
}
@@ -162,9 +152,10 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
facePayFragment?.presentation?.dismiss()
super.onDestroy()
}
private var scanQrCodePayPresentation: ScanQrCodePayPresentation?=null
private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null
fun paySuccess() {
showFragment(PayResultFragment(),"")
showFragment(PayResultFragment(), "")
if (displays.size > 1) {
scanQrCodePayPresentation = ScanQrCodePayPresentation(
activity = this,
@@ -15,7 +15,7 @@ import kotlin.text.replace
class SettingActivity : BaseActivity<ActivitySettingBinding>() {
private val viewModel by viewModels<UserViewModel>()
val viewModel by viewModels<UserViewModel>()
override fun getViewModel(): BaseViewModel {
return viewModel
}
@@ -34,12 +34,16 @@ import com.sw.dualscreen.utils.ImageUtil
import com.sw.plate.utils.ToastUtils
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.File
import kotlin.getValue
class CollectFragment : BaseFragment<FragmentCollectBinding>() {
companion object {
private const val TAG = "CollectFragment"
const val MAX_COUNT = 5
}
private var selectedFoodId: String? = ""
@@ -59,7 +63,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
SearchFoodAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position ->
checkedItem = searchFoodList[position]
selectedFoodId = checkedItem!!.id
selectedFoodId = checkedItem!!.foodId
selectedFoodName = checkedItem!!.foodName
val isChecked = checkedItem!!.isChecked
searchFoodList[position].isChecked = isChecked.not()
@@ -78,8 +82,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
foodCollectionList[position].let {
it.bitmap = null
it.imageVector = null
it.imageFile = null
it.isShowCamera = true
it.isFinish = false
it.uploadSuccess = false
}
notifyItemChanged(position)
}
@@ -91,28 +98,45 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
private val cameraCallback: (Uri) -> Unit = { uri ->
val index = foodCollectionList.indexOfFirst { it.bitmap == null }
if (index == -1) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
rerurn@cameraCallback
}
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
// val cropBitmap = BitmapCropper.cropCenter(
// original = bitmap,
// targetWidth = 1300, targetHeight = 900,
// //offsetX = 30, offsetY = 100
// )
val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
foodCollectionList[index].let {
it.bitmap = bitmap
it.isShowCamera = false
it.imageUri = file?.toUri()
try {
val index = foodCollectionList.indexOfFirst { it.imageFile == null }
if (index == -1) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
rerurn@cameraCallback
}
collectionAdapter.notifyItemChanged(index)
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
// val cropBitmap = BitmapCropper.cropCenter(
// original = bitmap,
// targetWidth = 1300, targetHeight = 900,
// //offsetX = 30, offsetY = 100
// )
initBox()
val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap)
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("操作失败")
return@let
}
val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
foodCollectionList[index].let {
it.imageVector = imageVector
it.bitmap = null
it.isShowCamera = false
it.imageFile = file
}
collectionAdapter.notifyItemChanged(index)
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
}
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("程序异常")
}
}
@@ -157,7 +181,9 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
Toast.makeText(requireActivity(), "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
vectorThread()
vectorThread(){
upload()
}
}
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
@@ -190,13 +216,43 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}
}
private fun vectorThread() {
private fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
(requireActivity() as SettingActivity).viewModel.uploadCollectFoodPics(files,params, callback)
}
private fun upload() {
val params = HashMap<String, RequestBody>()
//params["placeId"] = restId.toRequestBody()
params["foodId"] = checkedItem!!.foodId.toRequestBody()
params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
//params["foodVector"] = foodVector.toRequestBody()
for (index in foodCollectionList.indices step 5) {
val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
val subList = foodCollectionList.subList(index, end)
val subFiles = subList.map { it.imageFile }
uploadCollectFoodPics(subFiles, params) { isSuccess->
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
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()
// }
// }
}
}
}
private fun vectorThread(block:()-> Unit) {
settingActivity?.showWaitingDialog("加载中……")
Thread {
foodCollectionList
.filter { it.bitmap != null }
// .filter { it.bitmap != null }
.filter { it.imageVector != null }
.forEachIndexed { index, it ->
image2VectorTask(it, index)
image2VectorTask(imageVector = it.imageVector!!, index)
}
activity?.runOnUiThread {
binding.root.postDelayed({
@@ -212,25 +268,24 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}
}
private fun image2VectorTask(item: FoodCollectionBean, position: Int) {
private fun image2VectorTask(imageVector: FloatArray, position: Int) {
initBox()
val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
// Timber.tag("mzf1").e(base64Str)
//// viewModel.postImageData(
//// context,
//// foodId = selectedFoodId.toString(),
//// foodName = selectedFoodName.toString(),
//// foodVector = base64Str,
//// uri = item.imageUri!!
//// )
// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
//
//// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
//// Timber.tag("mzf1").e(base64Str)
////// viewModel.postImageData(
////// context,
////// foodId = selectedFoodId.toString(),
////// foodName = selectedFoodName.toString(),
////// foodVector = base64Str,
////// uri = item.imageUri!!
////// )
box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector))
foodCollectionList[position].let {
it.imageVector = imageVector
// it.imageVector = imageVector
it.isFinish = true
}
activity?.runOnUiThread {
collectionAdapter.notifyItemChanged(position)
}
@@ -33,14 +33,24 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -29,14 +29,24 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
fun loadBitmap(frame: Bitmap) {
binding.ivFaceImage.setImageBitmap(frame)
}
@@ -29,14 +29,24 @@ class NumberPayFragment: BaseFragment<FragmentNumberPayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -25,6 +25,8 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
private var payAmount: String? = null
private var payQrCodePic: Any? = null
var presentation: ScanQrCodePayPresentation?=null
private var countDownJob: Job? = null
override fun inflateViewBinding(): FragmentScanQrcodePayBinding {
return FragmentScanQrcodePayBinding.inflate(layoutInflater)
}
@@ -47,14 +49,25 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
countDownJob?.cancel() // 自动取消订阅,防止内存泄漏
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -90,9 +103,4 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
}
)
}
private var countDownJob: Job? = null
override fun onDestroy() {
super.onDestroy()
countDownJob?.cancel() // 自动取消订阅,防止内存泄漏
}
}