From 57f8920442837813aea895772540836da89be7fe Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Thu, 26 Mar 2026 18:57:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=A2=E5=8D=95=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E6=A1=A3=E5=8F=A3=E6=9C=BA=E6=A0=87=E8=AF=86=EF=BC=9B?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BD=93=E5=89=8D=E8=8F=9C=E5=93=81=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sw/dualscreen/adapter/FoodOrderAdapter.kt | 6 +- .../presentation/MainScreenPresentation.kt | 177 ++++++++++++------ .../main/res/layout/list_item_food_order.xml | 20 +- 3 files changed, 138 insertions(+), 65 deletions(-) diff --git a/app/src/main/java/com/sw/dualscreen/adapter/FoodOrderAdapter.kt b/app/src/main/java/com/sw/dualscreen/adapter/FoodOrderAdapter.kt index 2628a08..8fab7cd 100644 --- a/app/src/main/java/com/sw/dualscreen/adapter/FoodOrderAdapter.kt +++ b/app/src/main/java/com/sw/dualscreen/adapter/FoodOrderAdapter.kt @@ -2,6 +2,7 @@ package com.sw.dualscreen.adapter import android.annotation.SuppressLint import android.content.Context +import android.graphics.Color import android.view.LayoutInflater import android.view.ViewGroup import android.widget.TextView @@ -31,13 +32,15 @@ class FoodOrderAdapter(list: MutableList) : @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: VH, position: Int, item: FoodItem?) { val binding = holder.binding + setTextColor(binding.tvFoodName, binding.tvPriceNorm, binding.tvWeight, binding.tvAmount) item?.let { binding.tvFoodName.text = it.foodName + binding.tvFoodName.setTextColor(if (it.isLocalData) Color.GREEN else "#FF33446A".toColorInt()) if (it.orderFrom == 2) { binding.tvPriceNorm.text = if (it.specName.isNullOrBlank()) "${it.specWeight}克" else "${it.specName}/${it.specWeight}克" } else { val foodPrice = it.foodPrice.format2String(2) - binding.tvPriceNorm.text = "${foodPrice}/${it.num}克" + binding.tvPriceNorm.text = "${foodPrice}/100克" } //if (it.specName.isNullOrBlank().not()) { // binding.tvPriceFlag.text = "[${it.specName}]" @@ -48,7 +51,6 @@ class FoodOrderAdapter(list: MutableList) : if (it.orderFrom == 2) visible() else gone() } } - setTextColor(binding.tvFoodName, binding.tvPriceNorm, binding.tvWeight, binding.tvAmount) binding.root.updateLayoutParams { topMargin = 2.dp bottomMargin = 2.dp diff --git a/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt b/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt index 6e1962d..d43682f 100644 --- a/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt +++ b/app/src/main/java/com/sw/dualscreen/presentation/MainScreenPresentation.kt @@ -8,6 +8,7 @@ import android.graphics.Bitmap import android.graphics.Point import android.hardware.Camera import android.os.Bundle +import android.util.Log import android.view.Display import android.view.View import android.view.ViewGroup @@ -15,6 +16,7 @@ import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.core.content.ContextCompat import androidx.core.view.isVisible +import androidx.core.view.postDelayed import androidx.core.view.updateLayoutParams import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope @@ -31,6 +33,7 @@ import com.sw.dualscreen.ext.format2String import com.sw.dualscreen.ext.gone import com.sw.dualscreen.ext.load import com.sw.dualscreen.ext.maskName +import com.sw.dualscreen.ext.roundedDecimalPlace import com.sw.dualscreen.ext.screenSize import com.sw.dualscreen.ext.visible import com.sw.dualscreen.model.response.DinnerType @@ -190,8 +193,8 @@ class MainScreenPresentation( // Timber.tag(TAG).e("updateWeight dinnerType is null") // return // } - if (chargeMode == 1) { - //不计费 + if (chargeMode == 1 || activity.settlementMode == 0) { + //不计费或者联合支付模式更新营养热量数据 if (mealPickupMode == 0) { //即放即取 calculateNutrition(lastWeight) @@ -279,6 +282,14 @@ class MainScreenPresentation( private fun setTopInfoVisible() { binding.llTopInfo.visible() binding.flFoodDetail.gone() + if (activity.settlementMode == 0) { + try { + foodOrderList.clear() + foodOrderAdapter.submitList(foodOrderList) + } catch (e: Exception) { + e.printStackTrace() + } + } binding.llTopInfo.updateLayoutParams { height = activity.screenSize[1] / 2 + 120.dp } @@ -288,14 +299,32 @@ class MainScreenPresentation( * 显示识别出的菜品信息 */ fun step3ShowRecognizeResult(userId: String) { - Timber.tag(TAG).d("main,step3,耗时:${System.currentTimeMillis() - startTime}") - LightManager.closeRedLight() - LightManager.openGreenLight() - currentStep = 3 - stepChangeCallback(currentStep) + step3Debouncer.debounce { + Timber.tag(TAG).d("main,step3,耗时:${System.currentTimeMillis() - startTime}") + LightManager.closeRedLight() + LightManager.openGreenLight() + currentStep = 3 + stepChangeCallback(currentStep) - setTopInfoVisible() - //根据接口数据更新热量数据-------------------------- + setTopInfoVisible() + if (activity.settlementMode == 0) { + //判断是联合支付调用接口查询就餐信息后,再查询热量营养数据 + loadOrderList(userId) { + loadUserNutritionData(userId) + } + } else { + //独立支队 + loadUserNutritionData(userId) + } + } + } + + private val step3Debouncer = Debouncer(10*1000) + + /** + * 根据接口数据更新热量、营养数据 + */ + private fun loadUserNutritionData(userId: String) { userViewModel.getUserNutritionData(userId = userId) { nutrition -> activity.runOnUiThread { if (nutrition == null) { @@ -316,11 +345,6 @@ class MainScreenPresentation( activity.hideWaitingDialog() } } - - // TODO: 判断是联合支付调用接口查询就餐信息------------------------ - if (activity.settlementMode == 0) { - loadOrderList(userId) - } } private fun initView() { @@ -417,7 +441,7 @@ class MainScreenPresentation( } private var isLoadUnbilledMode = false - private val df by lazy { DecimalFormat("#.##") } +// private val df by lazy { DecimalFormat("#.##") } /** * 餐品识别成功,不计费模式 @@ -456,15 +480,20 @@ class MainScreenPresentation( //updateFoodInfo(foodInfo) binding.nutritionInclude.tvUserName.text = userNutrition?.name.maskName() - val recommendCalorie = userNutrition?.recommendCalorie ?: 0.0 + val recommendCalorie = (userNutrition?.recommendCalorie ?: 0.0).roundedDecimalPlace(1) binding.nutritionInclude.tvRecommendHeat.text = - "推荐热量:${df.format(recommendCalorie)}kcal" + "推荐热量:${recommendCalorie.roundedDecimalPlace(1)}kcal" // binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${recommendCalorie.removeTrailingZeros()}kcal" //updateWeight(lastWeight / 1000) // ------------------------------------------------- // 删除userNutritionData,改为userNutrition - calculateNutrition(recognitionWeight - lastWeight) + //0-即放即取,1-余量计量 + mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0 + calculateNutrition( + if (mealPickupMode == 1) recognitionWeight - lastWeight + else recognitionWeight + ) binding.root.postDelayed({ isLoadUnbilledMode = false }, 10000) @@ -672,23 +701,26 @@ class MainScreenPresentation( private var lastAddWeight = 0 private fun addFoodToOrder(weight: Int, foodInfo: FoodInfo) { + Log.d(TAG, "addFoodToOrder: ${weight == lastAddWeight}") if (weight == lastAddWeight) return lastAddWeight = weight if (weight <= 10) { - if (foodOrderList.isNotEmpty()) { + //0-即放即取,1-余量计量 + mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0 + if (foodOrderList.isNotEmpty() && mealPickupMode == 1) { val last = foodOrderList.last() if (last.isLocalData) { foodOrderList.remove(last) foodOrderAdapter.submitList(foodOrderList) - //foodOrderAdapter.notifyDataSetChanged() + //foodOrderAdapter.notifyDataSetChanged() } } return } val foodPrice = if (isMember) foodInfo.vipPrice else foodInfo.specPrice val eatNum = activity.getEatNum(weight.toDouble(), foodInfo.specWeight) - val price = eatNum * (foodPrice?:0.0) - if (foodOrderList.isNotEmpty()) { + val price = eatNum * (foodPrice ?: 0.0) + if (foodOrderList.isNotEmpty() && mealPickupMode == 1) { val last = foodOrderList.last() if (last.isLocalData) { last.eatNum = eatNum @@ -699,24 +731,40 @@ class MainScreenPresentation( return } } - foodOrderList.add(FoodItem( - id = System.currentTimeMillis().toString(), - foodId = foodInfo.foodId, - foodName = foodInfo.foodName, - price = price, - specId = foodInfo.specId, - foodMaterialId = foodInfo.foodMaterialId, - specWeight = foodInfo.specWeight?.toInt() ?: 0, - orderFrom = 2, - num = weight, - eatNum = eatNum, - isLocalData = true - )) + foodOrderList.add( + FoodItem( + id = System.currentTimeMillis().toString(), + foodId = foodInfo.foodId, + foodName = foodInfo.foodName, + price = price, + specId = foodInfo.specId, + foodMaterialId = foodInfo.foodMaterialId, + specWeight = foodInfo.specWeight?.toInt() ?: 0, + orderFrom = 2, + num = weight, + eatNum = eatNum, + isLocalData = true + ) + ) foodOrderAdapter.submitList(foodOrderList) + Log.d( + TAG, + "addFoodToOrder: size=${foodOrderList.size},新增数据:${foodOrderList.last()}" + ) //foodOrderAdapter.notifyDataSetChanged() + var eatWeightSum = 0 + foodOrderList.forEach { + eatWeightSum += it.num + } + binding.detailInclude.tvTotalWeight.text = "总重量:${eatWeightSum}克" + Log.d(TAG, "addFoodToOrder: 更新总重量,新增数据------------------------------") } private fun calculateNutrition(value: Int) { + Log.d( + TAG, + "addFoodToOrder: weight = $value, recognitionWeight = $recognitionWeight foodInfo = $currentFood" + ) if (currentFood == null || userNutrition == null) { return } @@ -751,6 +799,9 @@ class MainScreenPresentation( val fruitsVegetables = energy.fruitsVegetables val meatEggs = energy.meatEggs + binding.detailInclude.tvTotalCalorie.text = + "总热量:${totalKcal.roundedDecimalPlace(1)}千卡" + val include = binding.nutritionInclude // 设置热量--------------------------------------------------------------------- @@ -769,7 +820,7 @@ class MainScreenPresentation( // 避免0作为被除数 maxKcal = if (maxKcal <= 0.0) 1.0 else maxKcal Timber.tag(TAG).d("maxKcal 1 = $maxKcal") - include.totalKcalTv.text = totalKcal.format2String(2) + include.totalKcalTv.text = totalKcal.roundedDecimalPlace(1).toString() var totalKcalHeight = (totalKcal / maxKcal).toFloat() if (totalKcalHeight == 0F) { include.divKcalView.visible() @@ -787,7 +838,7 @@ class MainScreenPresentation( ) val grainIndex = UserNutritionUtils.findCalorieIndex(energy.grain, grainArray) include.customFoodColumn.setImageDrawable(false, grainIndex) - include.totalFoodTv.text = grain.format2String(2) + include.totalFoodTv.text = grain.roundedDecimalPlace(1).toString() columnMax = if (columnMax <= 0.0) 1.0 else columnMax var grainHeight = (grain / columnMax).toFloat() if (grainHeight == 0F) { @@ -807,7 +858,7 @@ class MainScreenPresentation( val fruitsIndex = UserNutritionUtils.findCalorieIndex(energy.fruitsVegetables, fruitsArray) include.customVegetableColumn.setImageDrawable(false, fruitsIndex) - include.totalVegetableTv.text = fruitsVegetables.format2String(2) + include.totalVegetableTv.text = fruitsVegetables.roundedDecimalPlace(1).toString() var fruitsHeight = (fruitsVegetables / columnMax).toFloat() if (fruitsHeight == 0F) { include.divVegetableView.visible() @@ -826,7 +877,7 @@ class MainScreenPresentation( val meatEggsIndex = UserNutritionUtils.findCalorieIndex(energy.meatEggs, meatEggsArray) include.customMeatColumn.setImageDrawable(false, meatEggsIndex) - include.totalMeatTv.text = meatEggs.format2String(2) + include.totalMeatTv.text = meatEggs.roundedDecimalPlace(1).toString() var meatHeight = (meatEggs / columnMax).toFloat() if (meatHeight == 0F) { include.divMeatView.visible() @@ -885,6 +936,7 @@ class MainScreenPresentation( recognizeViewModel.onPreviewFrame(ByteArray(1382400), true) //triggerReidentify() } + /** * 重置人脸跟踪状态,让已在画面中的人脸重新触发识别 * 适用场景:切换按钮后需要重新识别当前画面中的人脸 @@ -900,6 +952,7 @@ class MainScreenPresentation( // isRecognition 保持 true,相机继续送帧,下一帧真实人脸会产生新 trackId recognizeViewModel.onPreviewFrame(ByteArray(1382400), true) } + private var recognizeTime = 0L private fun initArcViewModel() { recognizeViewModel.setLiveType(livenessType) @@ -1275,16 +1328,16 @@ class MainScreenPresentation( // activity.isAnalyzing = false // step1FoodRecognizing() // } else { - if (mealPickupMode == 1) { - step2FaceRecognizing(currentFood!!) - isKeepFaceState = false - if (activity.settlementMode == 0) { - setTopInfoVisible() - } - } else { - activity.isAnalyzing = false - step1FoodRecognizing() + if (mealPickupMode == 1) { + step2FaceRecognizing(currentFood!!) + isKeepFaceState = false + if (activity.settlementMode == 0) { + setTopInfoVisible() } + } else { + activity.isAnalyzing = false + step1FoodRecognizing() + } // } }) } @@ -1385,7 +1438,7 @@ class MainScreenPresentation( * 加载订单列表 */ @SuppressLint("NotifyDataSetChanged", "SetTextI18n") - private fun loadOrderList(userId: String) { + private fun loadOrderList(userId: String, callback: () -> Unit) { binding.llTopInfo.gone() binding.flFoodDetail.visible() binding.detailInclude.let { @@ -1400,17 +1453,21 @@ class MainScreenPresentation( } } userViewModel.getFoodOrderList(userId) { model -> - activity.runOnUiThread { - if (model == null) return@runOnUiThread - foodOrderList.clear() - foodOrderList.addAll(model.list?:emptyList()) - foodOrderAdapter.submitList(foodOrderList) - //foodOrderAdapter.notifyDataSetChanged() - binding.detailInclude.tvTotalWeight.text = "总重量:${model.eatWeightSum}克" - binding.detailInclude.tvTotalCalorie.text = - "总热量:${model.calorie.roundToInt()}千卡" - jointPaymentQueryFinish = true - } + activity.runOnUiThread { + if (model == null) return@runOnUiThread + foodOrderList.clear() + foodOrderList.addAll(model.list ?: emptyList()) + foodOrderAdapter.submitList(foodOrderList) + //foodOrderAdapter.notifyDataSetChanged() + binding.detailInclude.tvTotalWeight.text = "总重量:${model.eatWeightSum}克" + Log.d(TAG, "addFoodToOrder: 更新总重量,订单列表------------------------------") + binding.detailInclude.tvTotalCalorie.text = + "总热量:${model.calorie.roundedDecimalPlace(1)}千卡" + jointPaymentQueryFinish = true + + //重新加载营养信息 + callback() + } } } } diff --git a/app/src/main/res/layout/list_item_food_order.xml b/app/src/main/res/layout/list_item_food_order.xml index 8bf22b1..bffd429 100644 --- a/app/src/main/res/layout/list_item_food_order.xml +++ b/app/src/main/res/layout/list_item_food_order.xml @@ -2,12 +2,13 @@ - - +