增加支付接口相关逻辑

This commit is contained in:
2025-12-05 18:03:31 +08:00
parent 8899cae323
commit 04e318f47b
38 changed files with 830 additions and 316 deletions
@@ -121,6 +121,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private fun initData() { private fun initData() {
// viewModel.getEquipmentToken() // viewModel.getEquipmentToken()
viewModel.getUserFaceCache(pageNo = 1) viewModel.getUserFaceCache(pageNo = 1)
//viewModel.getUserFaceCache2()
// presentation?.step1() // presentation?.step1()
presentation?.step1FoodRecognizing() presentation?.step1FoodRecognizing()
} }
@@ -219,7 +221,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
ToastUtils.showToast("暂无识别数据,请搜索选择") ToastUtils.showToast("暂无识别数据,请搜索选择")
return@setOnClickListener return@setOnClickListener
} }
createOrder(checkedItem!!)
val realWeight = (lastWeight * 1000).roundToInt()
createOrder(foodInfo = checkedItem!!, foodWeight = realWeight, eatWeight = realWeight) {
presentation?.dismiss()
startActivity(Intent(this, PayActivity::class.java).apply {
putExtra(PayActivity.FOOD_INFO, checkedItem!!)
putExtra(PayActivity.FOOD_ORDER_ID, foodOrderId)
})
}
} }
} }
} }
@@ -656,19 +666,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
lastTouchTime = System.currentTimeMillis() lastTouchTime = System.currentTimeMillis()
} }
private fun createOrder(foodInfo: FoodInfo) { fun createOrder(foodInfo: FoodInfo, foodWeight: Int, eatWeight: Int, block:()-> Unit) {
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
val realWeight = (lastWeight * 1000).roundToInt()
val order = FoodOrder( val order = FoodOrder(
deviceId = GlobalData.deviceId, deviceId = GlobalData.deviceId,
foodId = foodInfo.foodId, foodId = foodInfo.foodId,
foodName = foodInfo.foodName ?: "", foodName = foodInfo.foodName ?: "",
foodMaterialId = foodInfo.foodMaterialId ?: "", foodMaterialId = foodInfo.foodMaterialId ?: "",
specId = foodInfo.specId ?: "", specId = foodInfo.specId ?: "",
foodWeight = realWeight, foodWeight = foodWeight,
eatWeight = realWeight, eatWeight = eatWeight,
//根据specId对应规格重量计算 //根据specId对应规格重量计算
eatNum = getEatNum(realWeight, foodInfo.specWeight ?: 0.0), eatNum = getEatNum(foodWeight, foodInfo.specWeight ?: 0.0),
userId = null, userId = null,
notPay = mode != 0, notPay = mode != 0,
) )
@@ -679,12 +688,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
return@runOnUiThread return@runOnUiThread
} }
foodOrderId = orderId foodOrderId = orderId
presentation?.dismiss() block()
startActivity(Intent(this, PayActivity::class.java).apply {
putExtra(PayActivity.FOOD_INFO, foodInfo)
putExtra(PayActivity.FOOD_ORDER_ID, orderId)
})
// ToastUtils.showToast("订单已生成")
} }
} }
} }
@@ -14,6 +14,7 @@ import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.presentation.pay.ScanQrCodePayPresentation import com.sw.dualscreen.presentation.pay.ScanQrCodePayPresentation
import com.sw.dualscreen.viewmodel.BaseViewModel import com.sw.dualscreen.viewmodel.BaseViewModel
import com.sw.dualscreen.viewmodel.UserViewModel import com.sw.dualscreen.viewmodel.UserViewModel
import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
class PayActivity : BaseActivity<ActivityPayBinding>() { class PayActivity : BaseActivity<ActivityPayBinding>() {
@@ -164,40 +165,63 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null
var memberInfo: MemberInfo? = null var memberInfo: MemberInfo? = null
fun showPayInfo(memberInfo: MemberInfo) { fun showPayInfo(type: Int = 1, isVip: Boolean = false, memberInfo: MemberInfo? = null) {
this.memberInfo = memberInfo this.memberInfo = memberInfo
payResultFragment = PayResultFragment.instance(1, memberInfo) payResultFragment = PayResultFragment.instance(type, memberInfo)
showFragment(payResultFragment!!, TAG_PAY_RESULT) showFragment(payResultFragment!!, TAG_PAY_RESULT)
if (displays.size > 1) { if (displays.size > 1) {
scanQrCodePayPresentation = ScanQrCodePayPresentation( scanQrCodePayPresentation = ScanQrCodePayPresentation(
activity = this, activity = this,
display = displays[1], display = displays[1],
type = 1 type = type
) { ) {
scanQrCodePayPresentation?.dismiss() scanQrCodePayPresentation?.dismiss()
}.also { }.also {
it.foodName = foodInfo?.foodName it.foodName = foodInfo?.foodName
it.totalPrice = foodInfo?.vipPrice?:0.0 //确认使用vipPrice 还是 specPrice
val totalPrice = if (isVip) foodInfo?.vipPrice else foodInfo?.specPrice
it.totalPrice = totalPrice ?: 0.0
} }
scanQrCodePayPresentation?.show() scanQrCodePayPresentation?.show()
} }
} }
fun showPaySuccess() { fun showPaySuccess(isVip: Boolean) {
payResultFragment = PayResultFragment.instance(2, memberInfo!!) showPayInfo(type = 2, isVip = isVip, memberInfo = memberInfo)
showFragment(payResultFragment!!, TAG_PAY_RESULT)
if (displays.size > 1) {
scanQrCodePayPresentation = ScanQrCodePayPresentation(
activity = this,
display = displays[1],
type = 2
) {
scanQrCodePayPresentation?.dismiss()
}.also {
it.foodName = foodInfo?.foodName
it.totalPrice = foodInfo?.vipPrice?:0.0
} }
scanQrCodePayPresentation?.show()
fun getQrCodeImg(orderId: String, userId: String? = null, block: (String?) -> Unit) {
userViewModel.getQrCodeImg(orderId = orderId, userId = userId) { qrCodeImg ->
runOnUiThread {
if (qrCodeImg.isNullOrBlank()) {
ToastUtils.showToast("获取二维码失败")
return@runOnUiThread
}
block(qrCodeImg)
}
}
}
fun cashPay(param: HashMap<String, String>, block: (Boolean) -> Unit) {
userViewModel.cashPay(param) {
runOnUiThread {
block(it)
}
}
}
fun memberPay(param: HashMap<String, String>, block: () -> Unit) {
userViewModel.memberPay(param) {
runOnUiThread {
block()
}
}
}
fun paySuccessCallback(isVip: Boolean, block: () -> Unit = {}) {
userViewModel.paySuccessCallback(queryType = 1, orderId = foodOrderId) {
showPaySuccess(isVip)
block()
} }
} }
@@ -7,11 +7,13 @@ import androidx.core.text.buildSpannedString
import com.sw.dualscreen.activity.PayActivity import com.sw.dualscreen.activity.PayActivity
import com.sw.dualscreen.activity.fragment.BaseFragment import com.sw.dualscreen.activity.fragment.BaseFragment
import com.sw.dualscreen.databinding.FragmentCashPayBinding import com.sw.dualscreen.databinding.FragmentCashPayBinding
import com.sw.dualscreen.ext.format2String
import com.sw.dualscreen.presentation.pay.CashPayPresentation import com.sw.dualscreen.presentation.pay.CashPayPresentation
import com.sw.plate.utils.ToastUtils
class CashPayFragment : BaseFragment<FragmentCashPayBinding>() { class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
private lateinit var payActivity: PayActivity private var payActivity: PayActivity? = null
private var foodName: String? = null private var foodName: String? = null
private var payAmount: String? = null private var payAmount: String? = null
@@ -22,12 +24,30 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
} }
override fun initialize() { override fun initialize() {
payActivity = requireActivity() as PayActivity payActivity = requireActivity() as? PayActivity
foodName = payActivity.foodInfo?.foodName foodName = payActivity?.foodInfo?.foodName
payAmount = "36.80" payAmount = payActivity?.foodInfo?.specPrice.format2String(2)
binding.tvRealAmount.text = getAmountText(payAmount?:"") binding.tvRealAmount.text = getAmountText(payAmount?:"")
binding.btnConfirmPayFinish.setOnClickListener {
payActivity?.cashPay(hashMapOf(
//标价金额(单位为元)
"totalFee" to (payAmount?:""),
//订单类型(0付款1会员充值)
"orderType" to "0",
//商户订单号
"orderNo" to (payActivity?.foodOrderId?:""),
//支付来源:0线下收款 、3:线上纯会员支付 101:支付宝主动、102:支付宝被动、201:微信主动、202:微信被动
"paySource" to "0"
)) { paySuccess ->
if (paySuccess.not()) {
ToastUtils.showToast("接口调用失败")
return@cashPay
}
payActivity?.showPaySuccess( false)
}
}
showSubScreen() showSubScreen()
} }
override fun onHiddenChanged(hidden: Boolean) { override fun onHiddenChanged(hidden: Boolean) {
@@ -36,7 +56,7 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
delayDismiss() delayDismiss()
return return
} }
showSubScreen() //showSubScreen()
} }
override fun onDestroy() { override fun onDestroy() {
@@ -54,7 +74,7 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
private fun showSubScreen() { private fun showSubScreen() {
// 查找副屏(通常索引为1 // 查找副屏(通常索引为1
if (displays.size > 1) { if (displays.size > 1) {
presentation = CashPayPresentation(activity = payActivity, display = displays[1]) { presentation = CashPayPresentation(activity = payActivity!!, display = displays[1]) {
presentation?.dismiss() presentation?.dismiss()
}.also { }.also {
it.foodName = foodName it.foodName = foodName
@@ -4,6 +4,7 @@ import android.graphics.Bitmap
import com.sw.dualscreen.activity.PayActivity import com.sw.dualscreen.activity.PayActivity
import com.sw.dualscreen.activity.fragment.BaseFragment import com.sw.dualscreen.activity.fragment.BaseFragment
import com.sw.dualscreen.databinding.FragmentFacePayBinding import com.sw.dualscreen.databinding.FragmentFacePayBinding
import com.sw.dualscreen.ext.format2String
import com.sw.dualscreen.presentation.pay.FacePayPresentation import com.sw.dualscreen.presentation.pay.FacePayPresentation
class FacePayFragment : BaseFragment<FragmentFacePayBinding>() { class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
@@ -22,7 +23,7 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
// payActivity?.showPayResult() // payActivity?.showPayResult()
// } // }
foodName = payActivity?.foodInfo?.foodName foodName = payActivity?.foodInfo?.foodName
payAmount = "36.80" payAmount = payActivity?.foodInfo?.specPrice.format2String(2)
showSubScreen() showSubScreen()
} }
@@ -32,7 +33,7 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
delayDismiss() delayDismiss()
return return
} }
showSubScreen() //showSubScreen()
} }
override fun onDestroy() { override fun onDestroy() {
@@ -32,7 +32,7 @@ class NumberPayFragment: BaseFragment<FragmentNumberPayBinding>() {
delayDismiss() delayDismiss()
return return
} }
showSubScreen() //showSubScreen()
} }
override fun onDestroy() { override fun onDestroy() {
@@ -1,12 +1,6 @@
package com.sw.dualscreen.activity.fragment.pay package com.sw.dualscreen.activity.fragment.pay
import android.os.Bundle import android.os.Bundle
import android.text.Spanned
import android.text.SpannedString
import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan
import androidx.core.graphics.toColorInt
import androidx.core.text.buildSpannedString
import com.sw.dualscreen.R import com.sw.dualscreen.R
import com.sw.dualscreen.activity.PayActivity import com.sw.dualscreen.activity.PayActivity
import com.sw.dualscreen.activity.fragment.BaseFragment import com.sw.dualscreen.activity.fragment.BaseFragment
@@ -16,7 +10,6 @@ import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.ext.invisible import com.sw.dualscreen.ext.invisible
import com.sw.dualscreen.ext.load import com.sw.dualscreen.ext.load
import com.sw.dualscreen.ext.visible import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.MemberInfo import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.model.response.TextBean import com.sw.dualscreen.model.response.TextBean
import com.sw.dualscreen.utils.SpannedUtils import com.sw.dualscreen.utils.SpannedUtils
@@ -30,7 +23,7 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
companion object { companion object {
const val PAGE_TYPE = "pageType" const val PAGE_TYPE = "pageType"
const val MEMBER_INFO = "memberInfo" const val MEMBER_INFO = "memberInfo"
fun instance(pageType: Int, memberInfo: MemberInfo): PayResultFragment { fun instance(pageType: Int, memberInfo: MemberInfo?): PayResultFragment {
return PayResultFragment().apply { return PayResultFragment().apply {
arguments = Bundle().also { arguments = Bundle().also {
it.putInt(PAGE_TYPE, pageType) it.putInt(PAGE_TYPE, pageType)
@@ -53,16 +46,24 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
binding.btnBack.setOnClickListener { binding.btnBack.setOnClickListener {
//payActivity?.showFacePay() //payActivity?.showFacePay()
} }
if (memberInfo != null) {
binding.layoutMemberInfo.visible()
} else {
binding.layoutMemberInfo.gone()
}
arguments?.let { arguments?.let {
pageType = it.getInt(PAGE_TYPE, 0) pageType = it.getInt(PAGE_TYPE, 0)
memberInfo = it.getParcelable(MEMBER_INFO) memberInfo = it.getParcelable(MEMBER_INFO)
} }
totalPrice = payActivity?.foodInfo?.vipPrice ?: 0.0 totalPrice = payActivity?.foodInfo?.vipPrice ?: 0.0
memberInfo?.let {
balance = (memberInfo?.topUpBalance ?: 0.0) + (memberInfo?.rewardBalance ?: 0.0) balance = (memberInfo?.topUpBalance ?: 0.0) + (memberInfo?.rewardBalance ?: 0.0)
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
expensesBalance = if (balance >= totalPrice) totalPrice else balance expensesBalance = if (balance >= totalPrice) totalPrice else balance
memberInfo?.let { loadUserInfo(it) } loadUserInfo(it)
}
when (pageType) { when (pageType) {
0 -> { 0 -> {
@@ -95,19 +96,24 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
) )
if (balance >= totalPrice) { if (balance >= totalPrice) {
binding.ivPayQrCode.invisible() binding.ivPayQrCode.invisible()
binding.btnConfirmPay.isEnabled = true binding.btnConfirmPay.run {
isEnabled = true
//点击支付,接口成功打开成功页面
setOnClickListener {
memberPay()
}
}
} else { } else {
binding.ivPayQrCode.visible() binding.ivPayQrCode.visible()
// binding.ivPayQrCode.load(payQrCodePic)
binding.btnConfirmPay.isEnabled = false binding.btnConfirmPay.isEnabled = false
payActivity?.getQrCodeImg(
orderId = payActivity!!.foodOrderId,
userId = memberInfo!!.id
) { qrCodeImg ->
binding.ivPayQrCode.load(qrCodeImg)
//扫码成功回调打开成功页面
payActivity?.paySuccessCallback(true)
} }
//点击支付接口成功打开成功页面,或者扫码手动成功回调打开成功页面
binding.btnConfirmPay.setOnClickListener {
payActivity?.showWaitingDialog("支付中,请稍后……")
binding.root.postDelayed({
payActivity?.hideWaitingDialog()
payActivity?.showPaySuccess()
},1000)
} }
} }
@@ -115,9 +121,22 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
binding.layoutPayInfo.gone() binding.layoutPayInfo.gone()
binding.layoutPaySuccess.visible() binding.layoutPaySuccess.visible()
if (memberInfo != null) {
val remainBalance = if (balance >= totalPrice) balance - totalPrice else 0.0
binding.tvUserBalance.text = SpannedUtils.getAmountText(
listOf(
TextBean(text = "¥", textSize = 24),
TextBean(text = remainBalance.format2String(2), textSize = 36),
)
)
binding.tvPayAmount.text = "收款金额 ${realPayPrice.format2String(2)}"
binding.tvPayInfo.text = binding.tvPayInfo.text =
"应收 ${totalPrice.format2String(2)} 元,余额扣除 ${expensesBalance.format2String(2)}" "应收 ${totalPrice.format2String(2)} 元,余额扣除 ${expensesBalance.format2String(2)}"
binding.tvPayAmount.text = "收款金额 ${realPayPrice.format2String(2)}" } else {
binding.tvPayAmount.text = "收款金额 ${totalPrice.format2String(2)}"
binding.tvPayInfo.text =
"应收 ${totalPrice.format2String(2)}"
}
} }
else -> {} else -> {}
@@ -168,6 +187,25 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
phone phone
} }
private fun memberPay() {
payActivity?.run {
showWaitingDialog("支付中,请稍后……")
memberPay(
hashMapOf(
//支付金额
"totalFee" to totalPrice.format2String(2),
//订单号
"orderNo" to payActivity!!.foodOrderId,
//用户id
"memberId" to memberInfo!!.id!!
)
) {
binding.root.postDelayed({
hideWaitingDialog()
showPaySuccess(true)
},1000)
}
}
}
} }
@@ -24,7 +24,7 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
private lateinit var payActivity: PayActivity private lateinit var payActivity: PayActivity
private var foodName: String? = null private var foodName: String? = null
private var payAmount: String? = null private var payAmount: String? = null
private var payQrCodePic: Any? = null private var payQrCodePic: String? = null
var presentation: ScanQrCodePayPresentation?=null var presentation: ScanQrCodePayPresentation?=null
private var countDownJob: Job? = null private var countDownJob: Job? = null
@@ -37,14 +37,19 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
foodName = payActivity.foodInfo?.foodName foodName = payActivity.foodInfo?.foodName
payAmount = payActivity.foodInfo?.specPrice.format2String(2) payAmount = payActivity.foodInfo?.specPrice.format2String(2)
payQrCodePic = R.drawable.ic_qrcode
binding.tvRealAmount.text = getAmountText(payAmount?:"") binding.tvRealAmount.text = getAmountText(payAmount?:"")
payActivity.getQrCodeImg(orderId = payActivity.foodOrderId) {
payQrCodePic = it
binding.ivPayQrCode.load(payQrCodePic) binding.ivPayQrCode.load(payQrCodePic)
binding.tvPayResult.text = "待支付(60s)..." binding.tvPayResult.text = "待支付(60s)..."
startCountDown() payActivity.paySuccessCallback(false)
showSubScreen() showSubScreen()
startCountDown()
}
} }
override fun onHiddenChanged(hidden: Boolean) { override fun onHiddenChanged(hidden: Boolean) {
@@ -53,7 +58,7 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
delayDismiss() delayDismiss()
return return
} }
showSubScreen() //showSubScreen()
} }
override fun onDestroy() { override fun onDestroy() {
@@ -104,4 +109,5 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
} }
) )
} }
} }
@@ -3,14 +3,8 @@ package com.sw.dualscreen.model.response
data class ApiResponse<T>( data class ApiResponse<T>(
val code: String, val code: String,
val msg: String? = "", val msg: String? = "",
val data: T? = null val data: T? = null,
) { val result: T? = null,
fun isSuccess(): Boolean = ("00000" == code) )
val result: T?
get() = data
val message: String?
get() = msg
}
@@ -50,6 +50,25 @@ data class MemberInfo(
data class TextBean( data class TextBean(
var text: String, var text: String,
var textSize: Int, var textSize: Int = 0,
var textColor: String? = null var textColor: String? = null
) )
data class UserNutrition(
//姓名
val name: String?,
//推荐能量
val recommendEnergy: Double?,
//热量
val calorie: Double?,
//果蔬
val fruitsVegetables: Double?,
//肉蛋
val meatEggs: Double?,
//主食
val stapleFood: Double?,
)
data class PayResult(
val paySuc: String? = null
)
@@ -16,13 +16,13 @@ data class FoodInfo(
//菜品名称 //菜品名称
val foodName:String? = null, val foodName:String? = null,
//能量 //能量
val calorie:String? = null, val calorie:Double? = null,
//蛋白质 //蛋白质
val protein:String? = null, val protein:Double? = null,
//脂肪 //脂肪
val fat:String? = null, val fat:Double? = null,
//碳水化合物 //碳水化合物
val carbohydrate:String? = null, val carbohydrate:Double? = null,
//规格售卖价格(元) //规格售卖价格(元)
val specPrice: Double? = null, val specPrice: Double? = null,
//VIP售卖价(元) //VIP售卖价(元)
@@ -33,6 +33,12 @@ data class FoodInfo(
val specId:String? = null, val specId:String? = null,
//规格重量(g) //规格重量(g)
val specWeight:Double? = null, val specWeight:Double? = null,
//主食
val stapleFood:Double? = null,
//果蔬
val fruitsVegetables:Double? = null,
//肉蛋
val meatEggs:Double? = null,
//----------------------------------- //-----------------------------------
var score: Int = 0, var score: Int = 0,
@@ -42,12 +48,12 @@ data class FoodInfo(
// @SerializedName("foodTypeAndRealIntakeVoList") // @SerializedName("foodTypeAndRealIntakeVoList")
// val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo>? = listOf(), // val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo>? = listOf(),
@SerializedName("stFoodInfoMaterial") // @SerializedName("stFoodInfoMaterial")
val stFoodInfoMaterial: StFoodInfoMaterial? = StFoodInfoMaterial(), // val stFoodInfoMaterial: StFoodInfoMaterial? = StFoodInfoMaterial(),
// @SerializedName("stFoodInfoPagoda") // @SerializedName("stFoodInfoPagoda")
// val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(), // val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(),
@SerializedName("stFoodInfoPagodaAPPVO") // @SerializedName("stFoodInfoPagodaAPPVO")
val stFoodInfoPagodaAPPVO: StFoodInfoPagodaAPPVO? = StFoodInfoPagodaAPPVO(), // val stFoodInfoPagodaAPPVO: StFoodInfoPagodaAPPVO? = StFoodInfoPagodaAPPVO(),
// @SerializedName("stFoodInfoSetting") // @SerializedName("stFoodInfoSetting")
// val stFoodInfoSetting: StFoodInfoSetting? = StFoodInfoSetting(), // val stFoodInfoSetting: StFoodInfoSetting? = StFoodInfoSetting(),
// @SerializedName("stFoodInfoSpecificationList") // @SerializedName("stFoodInfoSpecificationList")
@@ -22,3 +22,19 @@ data class UserFaceModel(
val userId: String? = "", val userId: String? = "",
val faceFeatureStr: String? = "" val faceFeatureStr: String? = ""
) : Parcelable ) : Parcelable
@Parcelize
data class UserFaceModel2(
val userId: String? = "",
val faceFeatureString: String? = "",
val face: String? = ""
) : Parcelable
data class FaceData(
val nextPageIndex:Int,
val total:Int,
val size:Int,
val current:Int,
val pages:Int,
val records: List<UserFaceModel2>?=null
)
@@ -4,11 +4,14 @@ import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerType import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FaceData
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.FoodSearchReq import com.sw.dualscreen.model.response.FoodSearchReq
import com.sw.dualscreen.model.response.FoodOrder import com.sw.dualscreen.model.response.FoodOrder
import com.sw.dualscreen.model.response.MemberInfo import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.model.response.PayResult
import com.sw.dualscreen.model.response.UserFaceModel import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.objbox.CollectedFoodInfo import com.sw.dualscreen.objbox.CollectedFoodInfo
import okhttp3.MultipartBody import okhttp3.MultipartBody
@@ -67,6 +70,13 @@ interface ApiService {
// @Query("pageSize") pageSize: Int // @Query("pageSize") pageSize: Int
): ApiResponse<List<UserFaceModel>> ): ApiResponse<List<UserFaceModel>>
@GET
suspend fun getUserFaceCache2(
@Url url: String = "http://192.168.1.230:2223/userface/swUserFaceimgSub/list",
@Query("pageNum") pageNum: Int,
@Query("pageSize") pageSize: Int
): ApiResponse<FaceData>
/** /**
* 获取已采集数据列表 * 获取已采集数据列表
*/ */
@@ -92,17 +102,37 @@ interface ApiService {
// @Query("foodName") foodName: String, // @Query("foodName") foodName: String,
): ApiResponse<List<FoodInfo>> ): ApiResponse<List<FoodInfo>>
// /**
// * 通过用户信息获取就餐数据
// */
// @GET
// suspend fun getUserNutritionData(
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getUserNutritionData/face",
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Query("restId") restId: String,
// @Query("userId") userId: String,
// @Query("foodId") foodId: String,
// ): ApiResponse<UserNutritionData>
/** /**
* 通过用户信息获取就餐数据 * 通过用户信息获取就餐数据
*/ */
@GET @GET
suspend fun getUserNutritionData( suspend fun getUserNutritionData(
@Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getUserNutritionData/face", @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/getUserCurrentFoodDetails",
@Query("appVersion") appVersion: String = GlobalData.appVersion, @Query("id") userId: String
@Query("restId") restId: String, ): ApiResponse<UserNutrition>
@Query("userId") userId: String,
@Query("foodId") foodId: String, /**
): ApiResponse<UserNutritionData> * 获取支付二维码
*/
@GET
suspend fun getQrCodeImg(
@Url url: String = "${GlobalData.appBaseUrl}/pay/yx-check-out-pay/getQrCodeImg",
@Query("orderNo") orderNo: String,
@Query("memberId") memberId: String?,
@Query("totalFee") totalFee: String?
): ApiResponse<String?>
/** /**
* 获取当前餐点类型 * 获取当前餐点类型
@@ -136,6 +166,33 @@ interface ApiService {
@Body req: FoodSearchReq @Body req: FoodSearchReq
): ApiResponse<List<FoodInfo>> ): ApiResponse<List<FoodInfo>>
/**
* 查询支付结果
*/
@POST
suspend fun queryOrderState(
@Url url: String = "${GlobalData.appBaseUrl}/pay/yx-check-out-pay/turnOrderInfo",
@Body param: HashMap<String, String>
): ApiResponse<PayResult?>
/**
* 现金支付
*/
@POST
suspend fun cashPay(
@Url url: String = "${GlobalData.appBaseUrl}/pay/yx-check-out-pay/cashPayment",
@Body param: HashMap<String, String>
): ApiResponse<Boolean?>
/**
* 会员支付
*/
@POST
suspend fun memberPay(
@Url url: String = "${GlobalData.appBaseUrl}/pay/yx-check-out-pay/memberPay",
@Body param: HashMap<String, String>
): ApiResponse<Any?>
/** /**
* 开餐-生成订单 * 开餐-生成订单
*/ */
@@ -20,6 +20,7 @@ class RequestInterceptor : Interceptor {
.header("Accept", "application/json") .header("Accept", "application/json")
// .header("Authorization", "Bearer ${getToken()}") // .header("Authorization", "Bearer ${getToken()}")
// .header("X-Access-Token", getToken(originalRequest)) // .header("X-Access-Token", getToken(originalRequest))
.header("X-Access-Token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjYW50ZWVuSWQiOiJiZTE1NDgzMS0zNDY2LTNiYTItYTJlYS01NzY1MmM5MTlmZWQiLCJ0eXBlIjoiNCIsInVzZXJJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDEifQ.sN40cOC-O5WQFrF4IDUs8fFlkNdUKLbJt_rHyTsgYYM")
// .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41") // .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41")
.header("X-DEVICE-CODE", GlobalData.deviceId) .header("X-DEVICE-CODE", GlobalData.deviceId)
.header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d") .header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d")
@@ -21,6 +21,7 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.arcsoft.face.ErrorInfo import com.arcsoft.face.ErrorInfo
import com.sw.dualscreen.GlobalKey import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.MyApp
import com.sw.dualscreen.R import com.sw.dualscreen.R
import com.sw.dualscreen.activity.MainActivity import com.sw.dualscreen.activity.MainActivity
import com.sw.dualscreen.databinding.PresentationMainScreenBinding import com.sw.dualscreen.databinding.PresentationMainScreenBinding
@@ -33,6 +34,7 @@ import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.DinnerType import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.utils.Debouncer import com.sw.dualscreen.utils.Debouncer
import com.sw.dualscreen.utils.SPUtil import com.sw.dualscreen.utils.SPUtil
@@ -90,7 +92,9 @@ class MainScreenPresentation(
private var detectWeight = 0.0 //识别菜品时的重量 private var detectWeight = 0.0 //识别菜品时的重量
private var lastWeight = 0.0 // 上一次的计算热量结果 private var lastWeight = 0.0 // 上一次的计算热量结果
private var userNutritionData: UserNutritionData? = null
// private var userNutritionData: UserNutritionData? = null
private var userNutrition: UserNutrition? = null
private var dinnerTypeInfo: DinnerType? = null private var dinnerTypeInfo: DinnerType? = null
private val debouncer = Debouncer(500) private val debouncer = Debouncer(500)
private var recognitionTime: Long = 0L // 人脸识别时的时间 private var recognitionTime: Long = 0L // 人脸识别时的时间
@@ -140,7 +144,8 @@ class MainScreenPresentation(
return return
} }
if (userNutritionData == null) { //if (userNutritionData == null) {
if (userNutrition == null) {
Timber.tag(TAG).e("updateWeight userNutritionData is null") Timber.tag(TAG).e("updateWeight userNutritionData is null")
return return
} }
@@ -206,17 +211,17 @@ class MainScreenPresentation(
} }
} }
} }
activity.lifecycleScope.launch { // activity.lifecycleScope.launch {
userViewModel.nutritionData.collect { // userViewModel.nutritionData.collect {
Timber.tag(TAG).d("registerDataChange nutritionData = $it") // Timber.tag(TAG).d("registerDataChange nutritionData = $it")
userNutritionData = it // userNutritionData = it
if (it == null) return@collect // if (it == null) return@collect
// step3ShowRecognizeResult() //// step3ShowRecognizeResult()
// //binding.nutritionInclude.tvUserName.text = it.userName.maskName() // //binding.nutritionInclude.tvUserName.text = it.userName.maskName()
// //binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${it.recommendMin}-${it.recommendMax}" // //binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${it.recommendMin}-${it.recommendMax}"
// //updateWeight(lastWeight / 1000) //// //updateWeight(lastWeight / 1000)
} // }
} // }
activity.lifecycleScope.launch { activity.lifecycleScope.launch {
userViewModel.dinnerTypeInfo.drop(1).collect { userViewModel.dinnerTypeInfo.drop(1).collect {
Timber.tag(TAG).d("registerDataChange dinnerTypeInfo = $it") Timber.tag(TAG).d("registerDataChange dinnerTypeInfo = $it")
@@ -311,9 +316,15 @@ class MainScreenPresentation(
tvProteinRate.text = "$proteinRate%" tvProteinRate.text = "$proteinRate%"
tvCarbohydrateRate.text = "$carbohydrateRate%" tvCarbohydrateRate.text = "$carbohydrateRate%"
viewFatLine.updateLayoutParams { height = (fatRate/100.0*84).roundToInt()*1.dp } viewFatLine.updateLayoutParams {
viewProteinLine.updateLayoutParams { height = (proteinRate/100.0*84).roundToInt()*1.dp } height = (fatRate / 100.0 * 84).roundToInt() * 1.dp
viewCarbohydrateLine.updateLayoutParams { height = (carbohydrateRate/100.0*84).roundToInt()*1.dp } }
viewProteinLine.updateLayoutParams {
height = (proteinRate / 100.0 * 84).roundToInt() * 1.dp
}
viewCarbohydrateLine.updateLayoutParams {
height = (carbohydrateRate / 100.0 * 84).roundToInt() * 1.dp
}
} }
} }
@@ -324,13 +335,14 @@ class MainScreenPresentation(
return (100.0 * value / total).roundToInt() return (100.0 * value / total).roundToInt()
} }
private fun getIntNutritionValue(text: String?): Int { private fun getIntNutritionValue(num: Double?): Int {
return if (text.isNullOrBlank()) 0 else text.toFloat().roundToInt() } return num?.roundToInt() ?: 0
}
/** /**
* 餐品识别成功,不计费模式 * 餐品识别成功,不计费模式
*/ */
fun loadUnbilledMode() { fun loadUnbilledMode(nutrition: UserNutrition) {
binding.calorieInclude.root.gone() binding.calorieInclude.root.gone()
binding.nutritionInclude.root.visible() binding.nutritionInclude.root.visible()
@@ -342,12 +354,13 @@ class MainScreenPresentation(
//binding.ivRecImage.gone() //binding.ivRecImage.gone()
//updateFoodInfo(foodInfo) //updateFoodInfo(foodInfo)
userNutritionData?.let { binding.nutritionInclude.tvUserName.text = nutrition.name.maskName()
binding.nutritionInclude.tvUserName.text = it.userName.maskName()
binding.nutritionInclude.tvRecommendHeat.text = binding.nutritionInclude.tvRecommendHeat.text =
"推荐热量:${it.recommendMin}-${it.recommendMax}kcal" "推荐热量:${nutrition.recommendEnergy ?: 0}kcal"
updateWeight(lastWeight / 1000) //updateWeight(lastWeight / 1000)
} // -------------------------------------------------
// 删除userNutritionData,改为userNutrition
calculateNutrition(recognitionWeight - lastWeight)
} }
/** /**
@@ -370,7 +383,8 @@ class MainScreenPresentation(
dinnerTypeInfo = null dinnerTypeInfo = null
currentFood = null currentFood = null
userNutritionData = null // userNutritionData = null
userNutrition = null
recognitionWeight = 0.0 recognitionWeight = 0.0
stepChangeCallback(currentStep) stepChangeCallback(currentStep)
@@ -434,7 +448,8 @@ class MainScreenPresentation(
binding.ivPreviewImage.gone() binding.ivPreviewImage.gone()
dinnerTypeInfo = null dinnerTypeInfo = null
userNutritionData = null // userNutritionData = null
userNutrition = null
recognitionWeight = 0.0 recognitionWeight = 0.0
stepChangeCallback(currentStep) stepChangeCallback(currentStep)
@@ -457,7 +472,8 @@ class MainScreenPresentation(
binding.ivPreviewImage.gone() binding.ivPreviewImage.gone()
binding.ivRecImage.let { binding.ivRecImage.let {
it.visible() it.visible()
val imageUrl = if (foodInfo.foodImg.isNullOrBlank()) foodInfo.photoUri else foodInfo.foodImg val imageUrl =
if (foodInfo.foodImg.isNullOrBlank()) foodInfo.photoUri else foodInfo.foodImg
it.load(imageUrl) it.load(imageUrl)
} }
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
@@ -506,11 +522,12 @@ class MainScreenPresentation(
Timber.tag(TAG) Timber.tag(TAG)
.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight") .d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
val dinnerType = dinnerTypeInfo!!.dinnerType!! val dinnerType = dinnerTypeInfo!!.dinnerType!!
Timber.tag(TAG) // Timber.tag(TAG)
.d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}") // .d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
val calcResultInfo = UserNutritionUtils.calculateNutrition( val calcResultInfo = UserNutritionUtils.calculateNutrition2(
currentFood!!, currentFood!!,
userNutritionData!!, // userNutritionData!!,
userNutrition!!,
weight, weight,
dinnerType = dinnerType dinnerType = dinnerType
) )
@@ -701,6 +718,7 @@ class MainScreenPresentation(
val faceEntity = compareResult.faceEntity val faceEntity = compareResult.faceEntity
val userId = faceEntity.userName val userId = faceEntity.userName
if (userId == null) return@Observer if (userId == null) return@Observer
ToastUtils.showToast("人脸识别成功,userId = $userId")
if (currentFood == null) { if (currentFood == null) {
currentFood = activity.checkedItem currentFood = activity.checkedItem
} }
@@ -710,17 +728,19 @@ class MainScreenPresentation(
return@runOnUiThread return@runOnUiThread
} }
} }
// TODO: ------------------人脸识别成功
//-------------------------------------------------
// TODO: ------------------人脸识别成功
step3ShowRecognizeResult() step3ShowRecognizeResult()
//根据接口数据更新热量数据-------------------------- //根据接口数据更新热量数据--------------------------
loadUnbilledMode() userViewModel.getUserNutritionData(userId = userId) { nutrition ->
// userViewModel.getUserNutritionData( activity.runOnUiThread {
// userId = userId, if (nutrition == null) {
// foodId = currentFood!!.foodId!! ToastUtils.showToast("未查询到营养数据")
// ) return@runOnUiThread
}
this@MainScreenPresentation.userNutrition = nutrition
loadUnbilledMode(nutrition)
// -------------------------------
}
}
}) })
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info -> recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
@@ -1013,7 +1033,8 @@ class MainScreenPresentation(
} }
val listIsEmpty = facePreviewInfoList.isEmpty() val listIsEmpty = facePreviewInfoList.isEmpty()
val listFirstTrackId = if (listIsEmpty.not()) facePreviewInfoList[0]!!.trackId else null val listFirstTrackId = if (listIsEmpty.not()) facePreviewInfoList[0]!!.trackId else null
Timber.tag(TAG).d("listIsEmpty=$listIsEmpty,lastFaceTrackId=$lastFaceTrackId,listFirstTrackId=$listFirstTrackId") Timber.tag(TAG)
.d("listIsEmpty=$listIsEmpty,lastFaceTrackId=$lastFaceTrackId,listFirstTrackId=$listFirstTrackId")
if (listIsEmpty || (lastFaceTrackId != listFirstTrackId)) { if (listIsEmpty || (lastFaceTrackId != listFirstTrackId)) {
if (lastFaceTrackId != -1) { if (lastFaceTrackId != -1) {
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0 mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
@@ -1032,9 +1053,9 @@ class MainScreenPresentation(
fun postUserData() { fun postUserData() {
Timber.tag(TAG).d("postUserData") Timber.tag(TAG).d("postUserData")
if (userNutritionData == null || currentFood == null) { if (userNutrition == null || currentFood == null) {
Timber.tag(TAG) Timber.tag(TAG)
.d("postUserData userNutritionData = ${userNutritionData == null}, currentFood = ${currentFood == null}") .d("postUserData userNutritionData = ${userNutrition == null}, currentFood = ${currentFood == null}")
return return
} }
var eatWeight = 0.0 var eatWeight = 0.0
@@ -1044,14 +1065,23 @@ class MainScreenPresentation(
} else { } else {
recognitionWeight - lastWeight recognitionWeight - lastWeight
} }
val userNutritionParam = UserNutritionParam( //val userNutritionParam = UserNutritionParam(
userId = userNutritionData?.userId!!, // userId = userNutritionData?.userId!!,
foodId = currentFood?.foodId!!, // foodId = currentFood?.foodId!!,
faceTime = recognitionTime, // faceTime = recognitionTime,
faceEndTime = System.currentTimeMillis(), // faceEndTime = System.currentTimeMillis(),
eatWeight = eatWeight,//lastWeight // eatWeight = eatWeight,//lastWeight
foodWeight = lastWeight // foodWeight = lastWeight
) //)
userViewModel.postUserNutritionData(listOf(userNutritionParam)) //userViewModel.postUserNutritionData(listOf(userNutritionParam))
activity.createOrder(
foodInfo = currentFood!!,
foodWeight = lastWeight.roundToInt(),
eatWeight = eatWeight.roundToInt()
) {
if (MyApp.DEBUG) {
ToastUtils.showToast("订单已生成")
}
}
} }
} }
@@ -4,6 +4,7 @@ package com.sw.dualscreen.presentation
import android.text.TextUtils import android.text.TextUtils
import com.sw.dualscreen.ext.toSafeDouble import com.sw.dualscreen.ext.toSafeDouble
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.model.response.UserNutritionData
import timber.log.Timber import timber.log.Timber
import kotlin.math.max import kotlin.math.max
@@ -16,62 +17,109 @@ object UserNutritionUtils {
/** /**
* 计算热量信息 * 计算热量信息
*/ */
fun calculateNutrition( fun calculateNutrition2(
foodInfo: FoodInfo, foodInfo: FoodInfo,
userModel: UserNutritionData, nutrition: UserNutrition,
weight: Double, weight: Double,
dinnerType: String dinnerType: String
): CalcResultInfo { ): CalcResultInfo {
// 初始化变量 // 初始化变量
var foodKcal = 0.0
var totalKcal = 0.0 var totalKcal = 0.0
var (vegetable, meat, fruits, grain) = List(4) { 0.0 } var (calorie, grain, fruitsVegetables, meatEggs) = List(4) { 0.0 }
// 处理食物信息 // 处理食物信息
foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight) calorie = calculateValue(foodInfo.calorie, weight)
Timber.d("calculateNutrition foodKcal = ${foodKcal}, energyKcal = ${foodInfo.stFoodInfoMaterial?.energyKcal}, weight = $weight") grain = calculateValue(foodInfo.stapleFood, weight)
grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight) fruitsVegetables = calculateValue(foodInfo.fruitsVegetables, weight)
fruits = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.fruitsValue(), weight) meatEggs = calculateValue(foodInfo.meatEggs, weight)
vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight)
meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight)
// 合并用户数据 // 合并用户数据
grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0 calorie += nutrition.calorie ?: 0.0
grain += nutrition.stapleFood ?: 0.0
fruitsVegetables += nutrition.fruitsVegetables ?: 0.0
meatEggs += nutrition.meatEggs ?: 0.0
fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0 totalKcal = max(calorie, 0.0)
vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0)
meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0
totalKcal = foodKcal + userModel.energyValue()
Timber.d("calculateNutrition totalKcal = ${totalKcal}, energyValue = ${userModel.energyValue()}")
if (totalKcal < 0){
totalKcal = 0.0
}
// 判断当餐最大热量 // 判断当餐最大热量
val maxKcal = //val maxKcal = userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10
userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10 //Timber.d("calculateNutrition maxKcal = ${maxKcal}, CalculateScoreValue = ${userModel.totalEnergyCalculateScoreValue()}")
Timber.d("calculateNutrition maxKcal = ${maxKcal}, CalculateScoreValue = ${userModel.totalEnergyCalculateScoreValue()}") // TODO: 测试数据-------------------------------
val pagoda = userModel.stFoodInfoPagoda val rate = calculateDinnerTypeRatio(dinnerType) / 10.0
val fruitsInfo = parseRecommend(pagoda?.fruitsRecommend, fruits) val maxKcal = totalKcal/ 0.26 / rate
val vegetableInfo = parseRecommend(pagoda?.vegetableRecommend, vegetable) val grainRecommend = "0-100"
val meatRecommend = "0-100"
val fruitsRecommend = "0-100"
// TODO: 测试数据-------------------------------
val calcResult = CalcResultInfo( val calcResult = CalcResultInfo(
totalKcal = CalcInfo( totalKcal = CalcInfo(
max = maxKcal, max = maxKcal,
min = 0.0, min = 0.0,
current = totalKcal current = totalKcal
), ),
grain = parseRecommend(pagoda?.grainRecommend, grain), grain = parseRecommend(grainRecommend, grain),
fruits = CalcInfo( // 果蔬 = 水果+蔬菜 fruits = parseRecommend(fruitsRecommend, fruitsVegetables),
max = fruitsInfo.max + vegetableInfo.max, meat = parseRecommend(meatRecommend, meatEggs)
min = fruitsInfo.min + vegetableInfo.min,
current = fruitsInfo.current + vegetableInfo.current
),
meat = parseRecommend(pagoda?.meatRecommend, meat)
) )
return calcResult return calcResult
} }
// fun calculateNutrition(
// foodInfo: FoodInfo,
// userModel: UserNutritionData,
//// userModel: UserNutrition,
// weight: Double,
// dinnerType: String
// ): CalcResultInfo {
//
// // 初始化变量
// var foodKcal = 0.0
// var totalKcal = 0.0
// var (vegetable, meat, fruits, grain) = List(4) { 0.0 }
//
// // 处理食物信息
// foodKcal = calculateValue(foodInfo.stFoodInfoMaterial?.energyKcal, weight)
// Timber.d("calculateNutrition foodKcal = ${foodKcal}, energyKcal = ${foodInfo.stFoodInfoMaterial?.energyKcal}, weight = $weight")
// grain = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.grainValue(), weight)
// fruits = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.fruitsValue(), weight)
// vegetable = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.vegetableValue(), weight)
// meat = calculateValue(foodInfo.stFoodInfoPagodaAPPVO?.meatValue(), weight)
//
// // 合并用户数据
// grain += userModel.stFoodInfoPagoda?.grainValue() ?: 0.0
//
// fruits += userModel.stFoodInfoPagoda?.fruitsValue() ?: 0.0
// vegetable = vegetable.plus(userModel.stFoodInfoPagoda?.vegetableValue() ?: 0.0)
// meat += userModel.stFoodInfoPagoda?.meatValue() ?: 0.0
//
// totalKcal = foodKcal + userModel.energyValue()
// Timber.d("calculateNutrition totalKcal = ${totalKcal}, energyValue = ${userModel.energyValue()}")
// if (totalKcal < 0) {
// totalKcal = 0.0
// }
// // 判断当餐最大热量
// val maxKcal =
// userModel.totalEnergyCalculateScoreValue() * calculateDinnerTypeRatio(dinnerType) / 10
// Timber.d("calculateNutrition maxKcal = ${maxKcal}, CalculateScoreValue = ${userModel.totalEnergyCalculateScoreValue()}")
// val pagoda = userModel.stFoodInfoPagoda
// val fruitsInfo = parseRecommend(pagoda?.fruitsRecommend, fruits)
// val vegetableInfo = parseRecommend(pagoda?.vegetableRecommend, vegetable)
// val calcResult = CalcResultInfo(
// totalKcal = CalcInfo(
// max = maxKcal,
// min = 0.0,
// current = totalKcal
// ),
// grain = parseRecommend(pagoda?.grainRecommend, grain),
// fruits = CalcInfo( // 果蔬 = 水果+蔬菜
// max = fruitsInfo.max + vegetableInfo.max,
// min = fruitsInfo.min + vegetableInfo.min,
// current = fruitsInfo.current + vegetableInfo.current
// ),
// meat = parseRecommend(pagoda?.meatRecommend, meat)
// )
// return calcResult
// }
fun parseRecommend(recommend: String?, current: Double): CalcInfo { fun parseRecommend(recommend: String?, current: Double): CalcInfo {
var newCurrent = if (current < 0) 0.0 else current var newCurrent = if (current < 0) 0.0 else current
if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) { if (TextUtils.isEmpty(recommend) || !recommend!!.contains("-")) {
@@ -29,8 +29,12 @@ import com.arcsoft.face.ErrorInfo
import com.sw.dualscreen.R import com.sw.dualscreen.R
import com.sw.dualscreen.activity.PayActivity import com.sw.dualscreen.activity.PayActivity
import com.sw.dualscreen.databinding.PresentationFacePayBinding import com.sw.dualscreen.databinding.PresentationFacePayBinding
import com.sw.dualscreen.ext.format2String
import com.sw.dualscreen.ext.load import com.sw.dualscreen.ext.load
import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.model.response.TextBean
import com.sw.dualscreen.utils.GsonUtils import com.sw.dualscreen.utils.GsonUtils
import com.sw.dualscreen.utils.SpannedUtils
import com.sw.dualscreen.view.CustomDialog import com.sw.dualscreen.view.CustomDialog
import com.sw.dualscreen.viewmodel.UserViewModel import com.sw.dualscreen.viewmodel.UserViewModel
import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.ToastUtils
@@ -99,7 +103,12 @@ class FacePayPresentation(
var payAmount: String? = null var payAmount: String? = null
private fun initView() { private fun initView() {
binding.tvFoodName.text = foodName binding.tvFoodName.text = foodName
binding.tvRealAmount.text = getAmountText(payAmount ?: "") binding.tvRealAmount.text = SpannedUtils.getAmountText(
listOf(
TextBean(text = "¥", textSize = 32),
TextBean(text = payAmount ?: "", textSize = 48),
)
)
// binding.ivPreviewImage.let { // binding.ivPreviewImage.let {
// it.outlineProvider = object : ViewOutlineProvider() { // it.outlineProvider = object : ViewOutlineProvider() {
// override fun getOutline(view: View, outline: Outline) { // override fun getOutline(view: View, outline: Outline) {
@@ -110,19 +119,13 @@ class FacePayPresentation(
// } // }
} }
private fun getAmountText(amount: String): SpannedString {
return buildSpannedString {
append("¥", AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
append(amount, AbsoluteSizeSpan(48, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
override fun onGlobalLayout() { override fun onGlobalLayout() {
Timber.tag(TAG).d("onGlobalLayout") Timber.tag(TAG).d("onGlobalLayout")
binding.dualCameraTexturePreviewRgb.getViewTreeObserver().removeOnGlobalLayoutListener(this) binding.dualCameraTexturePreviewRgb.getViewTreeObserver().removeOnGlobalLayoutListener(this)
//parentTextureView.getViewTreeObserver().removeOnGlobalLayoutListener(this) //parentTextureView.getViewTreeObserver().removeOnGlobalLayoutListener(this)
openCamera() openCamera()
} }
private fun openCamera() { private fun openCamera() {
Timber.tag(TAG).d("openCamera") Timber.tag(TAG).d("openCamera")
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
@@ -168,33 +171,13 @@ class FacePayPresentation(
} }
} }
} }
// activity.lifecycleScope.launch {
// userViewModel.nutritionData.collect {
// Timber.tag(TAG).d("registerDataChange nutritionData = $it")
// userNutritionData = it
// if (it == null) return@collect
// step3ShowRecognizeResult()
// //binding.nutritionInclude.tvUserName.text = it.userName.maskName()
// //binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${it.recommendMin}-${it.recommendMax}"
// //updateWeight(lastWeight / 1000)
// }
// }
// activity.lifecycleScope.launch {
// userViewModel.dinnerTypeInfo.drop(1).collect {
// Timber.tag(TAG).d("registerDataChange dinnerTypeInfo = $it")
// dinnerTypeInfo = it
// }
// }
} }
override fun onStop() { override fun onStop() {
if (rgbCameraHelper != null) { rgbCameraHelper?.release()
rgbCameraHelper!!.release()
rgbCameraHelper = null rgbCameraHelper = null
} irCameraHelper?.release()
if (irCameraHelper != null) {
irCameraHelper!!.release()
irCameraHelper = null irCameraHelper = null
}
recognizeViewModel.destroy() recognizeViewModel.destroy()
super.onStop() super.onStop()
} }
@@ -202,8 +185,8 @@ class FacePayPresentation(
fun resumeCamera() { fun resumeCamera() {
Timber.tag(TAG).d("resumeCamera isRecognition = $isRecognition") Timber.tag(TAG).d("resumeCamera isRecognition = $isRecognition")
isRecognition = true isRecognition = true
if (rgbCameraHelper != null && rgbCameraHelper!!.isStopped) { if (rgbCameraHelper?.isStopped == true) {
rgbCameraHelper!!.start() rgbCameraHelper?.start()
} }
} }
@@ -249,7 +232,8 @@ class FacePayPresentation(
recognizeViewModel.recognizeConfiguration recognizeViewModel.recognizeConfiguration
.observe(activity, Observer { recognizeConfiguration: RecognizeConfiguration? -> .observe(activity, Observer { recognizeConfiguration: RecognizeConfiguration? ->
Timber.tag(TAG).i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}") Timber.tag(TAG)
.i("recognizeConfiguration: observe = ${recognizeConfiguration.toString()}")
}) })
recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? -> recognizeViewModel.recognizeNotice.observe(activity, Observer { notice: String? ->
Timber.tag(TAG).i("recognizeNotice observe notice = $notice") Timber.tag(TAG).i("recognizeNotice observe notice = $notice")
@@ -258,45 +242,15 @@ class FacePayPresentation(
recognizeViewModel.recognizeUserId.observe( recognizeViewModel.recognizeUserId.observe(
activity, activity,
Observer { compareResult: CompareResult -> Observer { compareResult: CompareResult ->
Timber.tag(TAG).i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}") Timber.tag(TAG)
.i("recognizeUserId observe compareResult = ${compareResult.trackId}, userId = ${compareResult.faceEntity.userName}")
// recognitionTime = System.currentTimeMillis() // recognitionTime = System.currentTimeMillis()
// recognitionWeight = lastWeight // recognitionWeight = lastWeight
lastFaceTrackId = compareResult.trackId lastFaceTrackId = compareResult.trackId
val faceEntity = compareResult.faceEntity val faceEntity = compareResult.faceEntity
val userId = faceEntity.userName val userId = faceEntity.userName
if (userId == null) return@Observer if (userId == null) return@Observer
activity.runOnUiThread { faceRecSuccess(userId)
//ToastUtils.showToast("用户人脸识别成功,挑战支付页面")
showWaitingDialog("刷脸支付中,请稍后……")
userViewModel.getMemberInfo(memberId = userId) { memberInfo ->
activity.runOnUiThread {
if (memberInfo == null) {
ToastUtils.showToast("查询会员信息失败,请稍后重试")
return@runOnUiThread
}
userViewModel.bindOrder(userId, activity.foodOrderId) { bindResult ->
activity.runOnUiThread {
if (bindResult.not()) {
hideWaitingDialog()
ToastUtils.showToast("订单绑定失败")
return@runOnUiThread
}
binding.root.postDelayed({
hideWaitingDialog()
activity.showPayInfo(memberInfo)
binding.root.postDelayed({
dismiss()
},500)
},1500)
}
}
}
}
}
// userViewModel.getUserNutritionData(
// userId = userId,
// foodId = currentFood!!.id!!
// )
}) })
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info -> recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
@@ -388,7 +342,8 @@ class FacePayPresentation(
displayOrientation: Int, displayOrientation: Int,
isMirror: Boolean isMirror: Boolean
) { ) {
Timber.tag(TAG).d("initRgbCamera Rgb onCameraOpened: cameraId = $cameraId, displayOrientation = $displayOrientation") Timber.tag(TAG)
.d("initRgbCamera Rgb onCameraOpened: cameraId = $cameraId, displayOrientation = $displayOrientation")
activity.runOnUiThread({ activity.runOnUiThread({
val previewSizeRgb = camera.getParameters().getPreviewSize() val previewSizeRgb = camera.getParameters().getPreviewSize()
val layoutParams = adjustPreviewViewSize( val layoutParams = adjustPreviewViewSize(
@@ -397,8 +352,10 @@ class FacePayPresentation(
previewSizeRgb, displayOrientation, 0.6F previewSizeRgb, displayOrientation, 0.6F
) )
Timber.tag(TAG).d("initRgbCamera previewSizeRgb = ${previewSizeRgb.width}-${previewSizeRgb.height}") Timber.tag(TAG)
Timber.tag(TAG).d("initRgbCamera layoutParams = ${layoutParams.width}-${layoutParams.height}") .d("initRgbCamera previewSizeRgb = ${previewSizeRgb.width}-${previewSizeRgb.height}")
Timber.tag(TAG)
.d("initRgbCamera layoutParams = ${layoutParams.width}-${layoutParams.height}")
Timber.tag(TAG).d( Timber.tag(TAG).d(
"initRgbCamera isMirror = ${isMirror}, isDrawRgbRectHorizontalMirror = ${ "initRgbCamera isMirror = ${isMirror}, isDrawRgbRectHorizontalMirror = ${
ConfigUtil.isDrawRgbRectHorizontalMirror( ConfigUtil.isDrawRgbRectHorizontalMirror(
@@ -454,16 +411,19 @@ class FacePayPresentation(
} }
override fun onCameraConfigurationChanged(cameraID: Int, displayOrientation: Int) { override fun onCameraConfigurationChanged(cameraID: Int, displayOrientation: Int) {
Timber.tag(TAG).i("initRgbCamera onCameraConfigurationChanged: threadName = ${Thread.currentThread().name}") Timber.tag(TAG)
.i("initRgbCamera onCameraConfigurationChanged: threadName = ${Thread.currentThread().name}")
if (rgbFaceRectTransformer != null) { if (rgbFaceRectTransformer != null) {
rgbFaceRectTransformer!!.cameraDisplayOrientation = displayOrientation rgbFaceRectTransformer!!.cameraDisplayOrientation = displayOrientation
} }
Timber.tag(TAG).i("initRgbCamera onCameraConfigurationChanged: $cameraID $displayOrientation") Timber.tag(TAG)
.i("initRgbCamera onCameraConfigurationChanged: $cameraID $displayOrientation")
} }
} }
val measuredWidth = binding.dualCameraTexturePreviewRgb.measuredWidth val measuredWidth = binding.dualCameraTexturePreviewRgb.measuredWidth
val measuredHeight = binding.dualCameraTexturePreviewRgb.measuredHeight val measuredHeight = binding.dualCameraTexturePreviewRgb.measuredHeight
Timber.tag(TAG).i("initRgbCamera measuredWidth=$measuredWidthmeasuredHeight=$measuredHeight") Timber.tag(TAG)
.i("initRgbCamera measuredWidth=$measuredWidthmeasuredHeight=$measuredHeight")
val previewConfig: PreviewConfig = recognizeViewModel.previewConfig val previewConfig: PreviewConfig = recognizeViewModel.previewConfig
rgbCameraHelper = DualCameraHelper.Builder() rgbCameraHelper = DualCameraHelper.Builder()
@@ -498,7 +458,8 @@ class FacePayPresentation(
displayOrientation: Int, displayOrientation: Int,
isMirror: Boolean isMirror: Boolean
) { ) {
Timber.tag(TAG).d("initIrCamera IR onCameraOpened: cameraId = $cameraId, displayOrientation = $displayOrientation") Timber.tag(TAG)
.d("initIrCamera IR onCameraOpened: cameraId = $cameraId, displayOrientation = $displayOrientation")
val previewSizeIr = camera.getParameters().getPreviewSize() val previewSizeIr = camera.getParameters().getPreviewSize()
val layoutParams = adjustPreviewViewSize( val layoutParams = adjustPreviewViewSize(
binding.dualCameraTexturePreviewRgb, binding.dualCameraTexturePreviewRgb,
@@ -539,7 +500,8 @@ class FacePayPresentation(
if (irFaceRectTransformer != null) { if (irFaceRectTransformer != null) {
irFaceRectTransformer!!.cameraDisplayOrientation = displayOrientation irFaceRectTransformer!!.cameraDisplayOrientation = displayOrientation
} }
Timber.tag(TAG).i("initIrCamera onCameraConfigurationChanged: cameraID = $cameraID, displayOrientation = $displayOrientation") Timber.tag(TAG)
.i("initIrCamera onCameraConfigurationChanged: cameraID = $cameraID, displayOrientation = $displayOrientation")
} }
} }
@@ -600,8 +562,10 @@ class FacePayPresentation(
} }
} }
} }
private var lastFaceTrackId: Int = -1 // 上一次的人脸信息 private var lastFaceTrackId: Int = -1 // 上一次的人脸信息
private var mDialogWaiting: CustomDialog? = null private var mDialogWaiting: CustomDialog? = null
/** /**
* 显示等待提示框 * 显示等待提示框
*/ */
@@ -627,4 +591,49 @@ class FacePayPresentation(
super.onDisplayRemoved() super.onDisplayRemoved()
onDismissListener() onDismissListener()
} }
private fun faceRecSuccess(userId: String) {
activity.runOnUiThread {
showWaitingDialog("加载中,请稍后……")
}
getMemberInfo(userId) { memberInfo ->
bindOrder(userId) {
binding.root.postDelayed({
hideWaitingDialog()
activity.showPayInfo(type = 1, isVip = true, memberInfo = memberInfo)
binding.root.postDelayed({
dismiss()
}, 500)
}, 1500)
}
}
}
private fun bindOrder(userId:String, block:()-> Unit) {
userViewModel.bindOrder(userId, activity.foodOrderId) { bindResult ->
activity.runOnUiThread {
if (bindResult.not()) {
hideWaitingDialog()
ToastUtils.showToast("订单绑定失败")
return@runOnUiThread
}
block()
}
}
}
private fun getMemberInfo(userId: String, block:(MemberInfo)-> Unit) {
userViewModel.getMemberInfo(memberId = userId) { memberInfo ->
activity.runOnUiThread {
if (memberInfo == null) {
hideWaitingDialog()
ToastUtils.showToast("查询会员信息失败,请稍后重试")
return@runOnUiThread
}
block(memberInfo)
}
}
}
} }
@@ -4,11 +4,14 @@ import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerType import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FaceData
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.FoodSearchReq import com.sw.dualscreen.model.response.FoodSearchReq
import com.sw.dualscreen.model.response.FoodOrder import com.sw.dualscreen.model.response.FoodOrder
import com.sw.dualscreen.model.response.MemberInfo import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.model.response.PayResult
import com.sw.dualscreen.model.response.UserFaceModel import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.network.api.ApiService import com.sw.dualscreen.network.api.ApiService
import com.sw.dualscreen.objbox.CollectedFoodInfo import com.sw.dualscreen.objbox.CollectedFoodInfo
@@ -73,6 +76,18 @@ class RemoteRepository constructor(
} }
} }
suspend fun getUserFaceCache2(
pageNum: Int,
pageSize: Int = 160,
): ApiResponse<FaceData> {
return safeApiCall {
apiService.getUserFaceCache2(
pageNum = pageNum,
pageSize = pageSize
)
}
}
/** /**
* 获取人脸数据 * 获取人脸数据
*/ */
@@ -107,16 +122,38 @@ class RemoteRepository constructor(
} }
} }
// /**
// * 通过用户信息获取就餐数据
// */
// suspend fun getUserNutritionData(
// restId: String = GlobalData.restId,
// userId: String,
// foodId: String,
// ): ApiResponse<UserNutritionData> {
// return safeApiCall {
// apiService.getUserNutritionData(restId = restId, userId = userId, foodId = foodId)
// }
// }
/** /**
* 通过用户信息获取就餐数据 * 通过用户信息获取就餐数据
*/ */
suspend fun getUserNutritionData( suspend fun getUserNutritionData(userId: String): ApiResponse<UserNutrition> {
restId: String = GlobalData.restId,
userId: String,
foodId: String,
): ApiResponse<UserNutritionData> {
return safeApiCall { return safeApiCall {
apiService.getUserNutritionData(restId = restId, userId = userId, foodId = foodId) apiService.getUserNutritionData(userId = userId)
}
}
/**
* 获取支付二维码
*/
suspend fun getQrCodeImg(
orderNo: String,
memberId: String? = null,
totalFee: String? = null
): ApiResponse<String?> {
return safeApiCall {
apiService.getQrCodeImg(orderNo = orderNo, memberId = memberId, totalFee = totalFee)
} }
} }
@@ -150,12 +187,42 @@ class RemoteRepository constructor(
} }
} }
/**
* 创建订单
*/
suspend fun createOrder(order: FoodOrder): ApiResponse<Any?> { suspend fun createOrder(order: FoodOrder): ApiResponse<Any?> {
return safeApiCall { return safeApiCall {
apiService.createOrder(order = order) apiService.createOrder(order = order)
} }
} }
/**
* 现金支付
*/
suspend fun cashPay(param: HashMap<String, String>): ApiResponse<Boolean?> {
return safeApiCall {
apiService.cashPay(param = param)
}
}
/**
* 查询订单状态
*/
suspend fun queryOrderState(param: HashMap<String, String>): ApiResponse<PayResult?> {
return safeApiCall {
apiService.queryOrderState(param = param)
}
}
/**
* 会员支付
*/
suspend fun memberPay(param: HashMap<String, String>): ApiResponse<Any?> {
return safeApiCall {
apiService.memberPay(param = param)
}
}
suspend fun bindOrder(userId: String, orderId: String): ApiResponse<Any?> { suspend fun bindOrder(userId: String, orderId: String): ApiResponse<Any?> {
return safeApiCall { return safeApiCall {
apiService.bindOrder(userId = userId, orderId = orderId) apiService.bindOrder(userId = userId, orderId = orderId)
@@ -10,20 +10,19 @@ import com.sw.dualscreen.model.response.TextBean
object SpannedUtils { object SpannedUtils {
const val SPAN_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
public fun getAmountText(list: List<TextBean>): SpannedString { public fun getAmountText(list: List<TextBean>): SpannedString {
return buildSpannedString { return buildSpannedString {
list.forEach { list.forEach {
append( val start = length
it.text, append(it.text)
AbsoluteSizeSpan(it.textSize, true), val end = length
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE if (it.textSize != 0) {
) setSpan(AbsoluteSizeSpan(it.textSize, true), start, end, SPAN_FLAGS)
}
if (it.textColor.isNullOrBlank().not()) { if (it.textColor.isNullOrBlank().not()) {
append( setSpan(ForegroundColorSpan(it.textColor!!.toColorInt()), start, end, SPAN_FLAGS)
it.text,
ForegroundColorSpan(it.textColor!!.toColorInt()),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
} }
} }
} }
@@ -56,7 +56,7 @@ abstract class BaseViewModel() : ViewModel() {
if (code == "00000" || code == "200" || code == "0") { if (code == "00000" || code == "200" || code == "0") {
return true return true
} }
val message = response.message?:response.msg val message = response.msg
Timber.d("msg = ${message}, code = $code") Timber.d("msg = ${message}, code = $code")
ToastUtils.showToast("${message}(${code})") ToastUtils.showToast("${message}(${code})")
return false return false
@@ -10,7 +10,10 @@ import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.FoodOrder import com.sw.dualscreen.model.response.FoodOrder
import com.sw.dualscreen.model.response.MemberInfo import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.model.response.PayResult
import com.sw.dualscreen.model.response.UserFaceModel import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserFaceModel2
import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.model.response.UserNutritionData import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.objbox.CollectedFoodInfo import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.utils.GsonUtils import com.sw.dualscreen.utils.GsonUtils
@@ -94,7 +97,7 @@ class UserViewModel : BaseViewModel() {
// 获取成功一次后缓存状态 // 获取成功一次后缓存状态
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true) SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val list: List<UserFaceModel> = response.result ?: emptyList() val list: List<UserFaceModel> = response.data ?: emptyList()
val item = list.firstOrNull { it.userId == "1951105919342936066" } val item = list.firstOrNull { it.userId == "1951105919342936066" }
Timber.tag(TAG).d("getUserFaceCache userId = ${item?.userId}") Timber.tag(TAG).d("getUserFaceCache userId = ${item?.userId}")
val faceEntity = list.map { val faceEntity = list.map {
@@ -119,6 +122,31 @@ class UserViewModel : BaseViewModel() {
} }
} }
fun getUserFaceCache2(index: Int = 0) {
Timber.d("getUserFaceCache index = $index")
launch {
_loadFaceResult.value = false
val response = repository.getUserFaceCache2(index)
if (parseResponse(response)) {
// 获取成功一次后缓存状态
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
withContext(Dispatchers.Default) {
val list: List<UserFaceModel2> = response.result?.records ?: emptyList()
val faceEntity = list.map {
FaceEntity(it.userId, null, Base64.decode(it.face))
}
faceApi.updateFaceData2(index, faceEntity)
}
val nextPageIndex = response.result?.nextPageIndex ?: -1
if (nextPageIndex > 0) {
getUserFaceCache2(nextPageIndex)
} else {
_loadFaceResult.value = true
}
}
}
}
fun getCollectedFoodList( fun getCollectedFoodList(
pageNo: Int = 1, pageNo: Int = 1,
pageSize: Int = 100, pageSize: Int = 100,
@@ -130,7 +158,7 @@ class UserViewModel : BaseViewModel() {
val response = repository.getCollectedFoodList(pageNum = pageNo, pageSize = pageSize, foodName = foodName) val response = repository.getCollectedFoodList(pageNum = pageNo, pageSize = pageSize, foodName = foodName)
if (parseResponse(response)) { if (parseResponse(response)) {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val list: List<CollectedFoodInfo> = response.result ?: emptyList() val list: List<CollectedFoodInfo> = response.data ?: emptyList()
block(list) block(list)
} }
} }
@@ -199,9 +227,9 @@ class UserViewModel : BaseViewModel() {
launchWithLoading { launchWithLoading {
val response = repository.getRestInfoFoodsByType(foodName = foodName) val response = repository.getRestInfoFoodsByType(foodName = foodName)
if (parseResponse(response)) { if (parseResponse(response)) {
val list = response.result ?: emptyList() val list = response.data ?: emptyList()
action(list) action(list)
_identifiedFoodInfoList.value = response.result ?: emptyList() _identifiedFoodInfoList.value = response.data ?: emptyList()
} }
} }
} }
@@ -211,16 +239,46 @@ class UserViewModel : BaseViewModel() {
_searchFoodInfoList.value = emptyList<FoodInfo>() _searchFoodInfoList.value = emptyList<FoodInfo>()
} }
// /**
// * 获取用户就餐数据
// */
// fun getUserNutritionData(userId: String, foodId: String) {
// Timber.tag(TAG).d("getUserNutritionData userId = ${userId}, foodId = $foodId")
// _nutritionData.value = null
// launch {
// val response = repository.getUserNutritionData(userId = userId, foodId = foodId)
// if (parseResponse(response)) {
// _nutritionData.value = response.result
// }
// }
// }
/** /**
* 获取用户就餐数据 * 获取用户就餐数据
*/ */
fun getUserNutritionData(userId: String, foodId: String) { fun getUserNutritionData(userId: String, block: (UserNutrition?) -> Unit) {
Timber.tag(TAG).d("getUserNutritionData userId = ${userId}, foodId = $foodId") Timber.tag(TAG).d("getUserNutritionData userId = $userId")
_nutritionData.value = null
launch { launch {
val response = repository.getUserNutritionData(userId = userId, foodId = foodId) val response = repository.getUserNutritionData(userId = userId)
if (parseResponse(response)) { if (parseResponse(response)) {
_nutritionData.value = response.result block(response.data)
} else {
block(null)
}
}
}
/**
* 获取用户就餐数据
*/
fun getQrCodeImg(orderId: String, userId: String?=null, block: (String?) -> Unit) {
Timber.tag(TAG).d("getQrCodeImg orderId = $orderId, userId = $userId")
launch {
val response = repository.getQrCodeImg(orderNo = orderId, memberId = userId)
if (parseResponse(response)) {
block(response.data)
} else {
block(null)
} }
} }
} }
@@ -231,7 +289,7 @@ class UserViewModel : BaseViewModel() {
launch { launch {
val response = repository.getDinnerType() val response = repository.getDinnerType()
if (parseResponse(response)) { if (parseResponse(response)) {
_dinnerTypeInfo.value = response.result _dinnerTypeInfo.value = response.data
} }
} }
} }
@@ -254,7 +312,7 @@ class UserViewModel : BaseViewModel() {
launchWithLoading { launchWithLoading {
val response = repository.getFoodInfo(foodName = foodName) val response = repository.getFoodInfo(foodName = foodName)
if (parseResponse(response)) { if (parseResponse(response)) {
val list = response.result ?: emptyList() val list = response.data ?: emptyList()
_identifiedFoodInfoList.value = list _identifiedFoodInfoList.value = list
action(list) action(list)
} else { } else {
@@ -275,6 +333,90 @@ class UserViewModel : BaseViewModel() {
} }
} }
/**
* 现金支付
*/
fun cashPay(param: HashMap<String, String>, block:(Boolean)-> Unit) {
Timber.tag(TAG).d("cashPay")
launchWithLoading {
val response = repository.cashPay(param)
if (parseResponse(response)) {
block(response.data?:false)
} else {
block(false)
}
}
}
/**
* 查询订单状态
*
* @param queryType 查询类型 1支付2退款
* @param orderId 订单号
*/
fun queryOrderState(queryType:Int, orderId:String, block:(PayResult?)-> Unit) {
Timber.tag(TAG).d("queryOrderState")
val param = hashMapOf(
"queryType" to "$queryType",
"payOrderNo" to orderId
)
launchWithLoading {
val response = repository.queryOrderState(param)
if (parseResponse(response)) {
block(response.data)
} else {
block(null)
}
}
}
/**
* 扫码成功回调
*
* @param queryType 查询类型 1支付2退款
* @param orderId 订单号
*/
fun paySuccessCallback(queryType:Int, orderId:String, block:()-> Unit) {
Timber.tag(TAG).d("paySuccessCallback")
val param = hashMapOf(
"queryType" to "$queryType",
"payOrderNo" to orderId
)
launchWithLoading {
var orderState = false
while (orderState.not()) {
val response = repository.queryOrderState(param)
if (parseResponse(response)) {
orderState = response.data?.paySuc == "1"
if (orderState) {
block()
}
}else {
orderState = false
}
}
}
}
/**
* 会员支付
*/
fun memberPay(param: HashMap<String, String>, block:(Boolean)-> Unit) {
Timber.tag(TAG).d("memberPay")
launchWithLoading {
val response = repository.memberPay(param)
if (parseResponse(response)) {
block(true)
} else {
block(false)
}
}
}
/**
* 绑定订单
*/
fun bindOrder(userId: String, orderId: String, block:(Boolean)-> Unit){ fun bindOrder(userId: String, orderId: String, block:(Boolean)-> Unit){
Timber.tag(TAG).d("bindOrder") Timber.tag(TAG).d("bindOrder")
launchWithLoading { launchWithLoading {
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

+2 -1
View File
@@ -90,7 +90,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_margin="27dp" android:layout_margin="27dp"
android:background="@drawable/preview_border" /> android:background="@drawable/ic_camera_rect" />
<!-- preview_border-->
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
+2 -2
View File
@@ -17,8 +17,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginTop="30dp" android:layout_marginTop="20dp"
android:layout_marginBottom="90dp" android:layout_marginBottom="70dp"
android:textColor="#ff0a1428" android:textColor="#ff0a1428"
android:textSize="60sp" android:textSize="60sp"
android:textStyle="bold" android:textStyle="bold"
+2 -1
View File
@@ -4,8 +4,9 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<RelativeLayout <RelativeLayout
android:layout_width="240dp" android:layout_width="wrap_content"
android:layout_height="80dp" android:layout_height="80dp"
android:paddingHorizontal="20dp"
android:background="@drawable/dialog_waiting"> android:background="@drawable/dialog_waiting">
@@ -25,4 +25,21 @@
android:textColor="#ffff3232" android:textColor="#ffff3232"
android:textSize="36sp" android:textSize="36sp"
android:textStyle="bold" /> android:textStyle="bold" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirmPayFinish"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginHorizontal="32dp"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_btn_save2"
android:text="已支付确认"
android:enabled="true"
android:textColor="@color/white"
android:textSize="40sp" />
</LinearLayout> </LinearLayout>
@@ -9,6 +9,7 @@
tools:background="#FFF4FAFF"> tools:background="#FFF4FAFF">
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:id="@+id/layoutMemberInfo"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardBackgroundColor="@color/white" app:cardBackgroundColor="@color/white"
@@ -146,9 +147,9 @@
<androidx.appcompat.widget.AppCompatButton <androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirmPay" android:id="@+id/btnConfirmPay"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="120dp" android:layout_height="100dp"
android:layout_marginHorizontal="32dp" android:layout_marginHorizontal="32dp"
android:layout_marginBottom="32dp" android:layout_marginBottom="20dp"
android:background="@drawable/bg_btn_save2" android:background="@drawable/bg_btn_save2"
android:text="确认支付" android:text="确认支付"
android:enabled="true" android:enabled="true"
@@ -79,6 +79,7 @@
android:id="@+id/ivPreviewImage" android:id="@+id/ivPreviewImage"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="456dp" android:layout_height="456dp"
android:scaleType="centerCrop"
app:shapeAppearance="@style/round10dpCornerStyle" app:shapeAppearance="@style/round10dpCornerStyle"
tools:background="@mipmap/ic_launcher"/> tools:background="@mipmap/ic_launcher"/>
@@ -86,6 +87,7 @@
android:id="@+id/ivRecImage" android:id="@+id/ivRecImage"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="456dp" android:layout_height="456dp"
android:scaleType="centerCrop"
tools:background="@mipmap/ic_launcher_round" tools:background="@mipmap/ic_launcher_round"
app:shapeAppearance="@style/round10dpCornerStyle" app:shapeAppearance="@style/round10dpCornerStyle"
android:visibility="gone"/> android:visibility="gone"/>
@@ -231,8 +233,8 @@
<FrameLayout <FrameLayout
android:id="@+id/flRecognizeIr" android:id="@+id/flRecognizeIr"
android:layout_width="1.3333dp" android:layout_width="133.33dp"
android:layout_height="1dp" android:layout_height="100dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:visibility="gone"> android:visibility="gone">
@@ -39,6 +39,16 @@ public class FaceApi {
faceDao.insert(list); faceDao.insert(list);
} }
public void updateFaceData2(int index, List<FaceEntity> list) {
Log.d(TAG, "updateFaceData: index = " + index + ", listSize = " + list.size());
FaceDao faceDao = FaceDatabase.getInstance(App.getContext()).faceDao();
if (index == 0) {
faceDao.deleteAll();
faceDao.resetId();
}
faceDao.insert(list);
}
/** /**
* 激活arcsoft 人脸 * 激活arcsoft 人脸
* *
@@ -283,6 +283,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback {
} }
// 填入在设置界面设置好的配置信息 // 填入在设置界面设置好的配置信息
boolean enableLive = !ConfigUtil.getLivenessDetectType(context).equals(context.getString(R.string.value_liveness_type_disable)); boolean enableLive = !ConfigUtil.getLivenessDetectType(context).equals(context.getString(R.string.value_liveness_type_disable));
// enableLive = false;
boolean enableFaceQualityDetect = ConfigUtil.isEnableImageQualityDetect(context); boolean enableFaceQualityDetect = ConfigUtil.isEnableImageQualityDetect(context);
boolean enableFaceMoveLimit = ConfigUtil.isEnableFaceMoveLimit(context); boolean enableFaceMoveLimit = ConfigUtil.isEnableFaceMoveLimit(context);
boolean enableFaceSizeLimit = ConfigUtil.isEnableFaceSizeLimit(context); boolean enableFaceSizeLimit = ConfigUtil.isEnableFaceSizeLimit(context);