增加消费码支付功能、支付逻辑优化、金额问题优化、订单绑定优化

This commit is contained in:
2025-12-12 17:50:51 +08:00
parent a0847d21b7
commit 1d0e1a62e2
24 changed files with 507 additions and 247 deletions
@@ -78,9 +78,11 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
hideWaitingDialog() hideWaitingDialog()
val view = View.inflate(this, R.layout.dialog_waiting, null) val view = View.inflate(this, R.layout.dialog_waiting, null)
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog) mDialogWaiting = CustomDialog(this, view, R.style.MyDialog).apply {
mDialogWaiting!!.show() setCancelable(true)
mDialogWaiting!!.setCancelable(true) setCanceledOnTouchOutside(true)
show()
}
return mDialogWaiting return mDialogWaiting
} }
@@ -63,6 +63,7 @@ import kotlin.math.roundToInt
class MainActivity : BaseActivity<ActivityMainBinding>() { class MainActivity : BaseActivity<ActivityMainBinding>() {
companion object { companion object {
private const val TAG = "MainActivity"
const val TIME_OUT = 5 * 60 * 1000L const val TIME_OUT = 5 * 60 * 1000L
} }
@@ -237,32 +238,35 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
//计费 //计费
if (mealPickupMode == 0) { if (mealPickupMode == 0) {
//即放即取 //即放即取
eatWeight = presentation!!.lastWeight eatWeight = lastWeight * 1000
foodWeight = presentation!!.lastWeight foodWeight = lastWeight * 1000
} else { } else {
//余量计量 //余量计量
eatWeight = presentation!!.recognitionWeight - presentation!!.lastWeight eatWeight = (recognizeWeight - lastWeight) * 1000
foodWeight = presentation!!.recognitionWeight foodWeight = recognizeWeight * 1000
} }
} else { } else {
//不计费 //不计费
foodWeight = presentation!!.recognitionWeight foodWeight = recognizeWeight * 1000
eatWeight = if (mealPickupMode == 0) { eatWeight = if (mealPickupMode == 0) {
//即放即取 //即放即取
presentation!!.recognitionWeight recognizeWeight * 1000
} else { } else {
//余量计量 //余量计量
presentation!!.recognitionWeight - presentation!!.lastWeight (recognizeWeight - lastWeight) * 1000
} }
} }
val eatNum = getEatNum(eatWeight, checkedItem!!.specWeight)
createOrder( createOrder(
foodInfo = checkedItem!!, foodInfo = checkedItem!!,
foodWeight = foodWeight.roundToInt(), foodWeight = foodWeight.roundToInt(),
eatWeight = eatWeight.roundToInt() eatWeight = eatWeight.roundToInt(),
eatNum = eatNum
) { ) {
presentation?.dismiss() presentation?.dismiss()
startActivity(Intent(this, PayActivity::class.java).apply { startActivity(Intent(this, PayActivity::class.java).apply {
putExtra(PayActivity.FOOD_INFO, checkedItem!!) putExtra(PayActivity.FOOD_INFO, checkedItem!!)
putExtra(PayActivity.FOOD_EAT_NUM, eatNum)
putExtra(PayActivity.FOOD_ORDER_ID, foodOrderId) putExtra(PayActivity.FOOD_ORDER_ID, foodOrderId)
}) })
} }
@@ -270,6 +274,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} }
} }
private var recognizeWeight = 0.0
fun updateCurrentFood(foodInfo: FoodInfo?) { fun updateCurrentFood(foodInfo: FoodInfo?) {
if (foodInfo == null) { if (foodInfo == null) {
binding.tvFoodName.text = "-" binding.tvFoodName.text = "-"
@@ -280,6 +285,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
return return
} }
pauseAnalysis() pauseAnalysis()
recognizeWeight = lastWeight
presentation?.updateFood(foodInfo) presentation?.updateFood(foodInfo)
binding.tvFoodName.text = foodInfo.foodName binding.tvFoodName.text = foodInfo.foodName
binding.previewView.visibility = View.GONE binding.previewView.visibility = View.GONE
@@ -393,13 +399,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun updateFoodInfo(list: MutableList<FoodInfo>, scoreList: List<IdNameScore>) { private fun updateFoodInfo(list: MutableList<FoodInfo>, scoreList: List<IdNameScore>) {
Timber.d( val queryData = GsonUtils.toJson(list)
"registerDataChange识别后查询接口数据:${GsonUtils.toJson(list)},识别数据:${ val recData = GsonUtils.toJson(scoreList)
GsonUtils.toJson( Timber.d("registerDataChange识别后查询接口数据:$queryData,识别数据:$recData")
scoreList
)
}"
)
list.forEach { foodInfo -> list.forEach { foodInfo ->
val scoreItem = scoreList.firstOrNull { it.name == foodInfo.foodName } val scoreItem = scoreList.firstOrNull { it.name == foodInfo.foodName }
val score = scoreItem?.score ?: 0.0 val score = scoreItem?.score ?: 0.0
@@ -702,12 +704,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
lastTouchTime = System.currentTimeMillis() lastTouchTime = System.currentTimeMillis()
} }
fun createOrder(foodInfo: FoodInfo, foodWeight: Int, eatWeight: Int, block: () -> Unit) { fun createOrder(
foodInfo: FoodInfo,
foodWeight: Int,
eatWeight: Int,
eatNum: Int,
block: () -> Unit
) {
Timber.tag(TAG).d("foodWeight=$foodWeight,eatWeight=$eatWeight")
if (foodWeight <= 5 || eatWeight <= 5) { if (foodWeight <= 5 || eatWeight <= 5) {
ToastUtils.showToast("请取走餐品") ToastUtils.showToast("请取走餐品")
return return
} }
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
val order = FoodOrder( val order = FoodOrder(
deviceId = GlobalData.deviceId, deviceId = GlobalData.deviceId,
foodId = foodInfo.foodId, foodId = foodInfo.foodId,
@@ -717,9 +727,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
foodWeight = foodWeight, foodWeight = foodWeight,
eatWeight = eatWeight, eatWeight = eatWeight,
//根据specId对应规格重量计算 //根据specId对应规格重量计算
eatNum = getEatNum(foodWeight, foodInfo.specWeight ?: 0.0), eatNum = eatNum,
userId = null, userId = null,
notPay = mode != 0, notPay = chargeMode != 0,
//即放即取-1,称重-2
mode = if (pickupMode == 1) 1 else 2
) )
viewModel.createOrder(order) { orderId -> viewModel.createOrder(order) { orderId ->
runOnUiThread { runOnUiThread {
@@ -733,8 +745,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} }
} }
private fun getEatNum(realWeight: Int, specWeight: Double): Int { fun getEatNum(realWeight: Double?, specWeight: Double?): Int {
if (realWeight == 0 || specWeight == 0.0) return 0 if (realWeight == null || realWeight == 0.0 || specWeight == null || specWeight == 0.0) return 1
return (realWeight / specWeight).roundToInt() return (realWeight / specWeight).roundToInt()
} }
@@ -2,6 +2,7 @@ package com.sw.dualscreen.activity
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.R import com.sw.dualscreen.R
import com.sw.dualscreen.activity.fragment.pay.CashPayFragment import com.sw.dualscreen.activity.fragment.pay.CashPayFragment
import com.sw.dualscreen.activity.fragment.pay.FacePayFragment import com.sw.dualscreen.activity.fragment.pay.FacePayFragment
@@ -13,6 +14,7 @@ import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.model.response.FoodInfo 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.presentation.pay.ScanQrCodePayPresentation import com.sw.dualscreen.presentation.pay.ScanQrCodePayPresentation
import com.sw.dualscreen.utils.SPUtil
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.ToastUtils
@@ -25,6 +27,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
const val FOOD_INFO = "foodInfo" const val FOOD_INFO = "foodInfo"
const val TOTAL_AMOUNT = "totalAmount" const val TOTAL_AMOUNT = "totalAmount"
const val FOOD_ORDER_ID = "foodOrderId" const val FOOD_ORDER_ID = "foodOrderId"
const val FOOD_EAT_NUM = "foodEatNum"
// const val MEMBER_INFO = "memberInfo" // const val MEMBER_INFO = "memberInfo"
const val TAG_PAY_QR_CODE = "tagPayQrCode" const val TAG_PAY_QR_CODE = "tagPayQrCode"
@@ -55,13 +58,14 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
private var payResultFragment: PayResultFragment? = null private var payResultFragment: PayResultFragment? = null
var foodOrderId: String = "" var foodOrderId: String = ""
var eatNum: Int = 1
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
override fun initialize() { override fun initialize() {
super.initialize() super.initialize()
foodInfo = intent.getParcelableExtra(FOOD_INFO) foodInfo = intent.getParcelableExtra(FOOD_INFO)
foodOrderId = intent.getStringExtra(FOOD_ORDER_ID) ?: "" foodOrderId = intent.getStringExtra(FOOD_ORDER_ID) ?: ""
eatNum = intent.getIntExtra(FOOD_EAT_NUM, 1)
// totalAmount = intent.getDoubleExtra(TOTAL_AMOUNT,0.0) // totalAmount = intent.getDoubleExtra(TOTAL_AMOUNT,0.0)
// memberInfo = intent.getParcelableExtra(MEMBER_INFO) // memberInfo = intent.getParcelableExtra(MEMBER_INFO)
binding.tvFoodName.text = foodInfo?.foodName binding.tvFoodName.text = foodInfo?.foodName
@@ -129,34 +133,6 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
} }
} }
// private fun showFragment(currentFragment: Fragment, tag: String) {
// runCatching {
// supportFragmentManager.beginTransaction().apply {
// val existFragment = supportFragmentManager.findFragmentByTag(tag)
// if (existFragment == null) {
// add(R.id.fragmentContainerView, currentFragment, tag)
// }
// val fragments = supportFragmentManager.fragments
// fragments.forEach {
// it?.let { fragment ->
// if (fragment != currentFragment) {
// hide(fragment)
// }
// }
// }
// show(currentFragment)
// commitAllowingStateLoss()
// }
// }.onFailure {
// it.printStackTrace()
// }
// }
// fun showPayResult() {
// payResultFragment = PayResultFragment.instance(1, memberInfo)
// showFragment(payResultFragment!!, TAG_PAY_RESULT)
// }
override fun onDestroy() { override fun onDestroy() {
qrCodePayFragment?.presentation?.dismiss() qrCodePayFragment?.presentation?.dismiss()
cashPayFragment?.presentation?.dismiss() cashPayFragment?.presentation?.dismiss()
@@ -182,23 +158,36 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
}.also { }.also {
it.foodName = foodInfo?.foodName it.foodName = foodInfo?.foodName
//确认使用vipPrice 还是 specPrice //确认使用vipPrice 还是 specPrice
val totalPrice = if (isVip) foodInfo?.vipPrice else foodInfo?.specPrice val onePrice = if (isVip) foodInfo?.vipPrice else foodInfo?.specPrice
it.totalPrice = totalPrice ?: 0.0 it.totalPrice = (onePrice ?: 0.0) * eatNum
} }
scanQrCodePayPresentation?.show() scanQrCodePayPresentation?.show()
} }
} }
fun updateQrCodeImage(qrCodeUrl: String?) {
scanQrCodePayPresentation?.loadQrCodeImage(qrCodeUrl)
}
fun showPaySuccess(isVip: Boolean) { fun showPaySuccess(isVip: Boolean) {
showPayInfo(type = 2, isVip = isVip, memberInfo = memberInfo) showPayInfo(type = 2, isVip = isVip, memberInfo = memberInfo)
hidePayTab() hidePayTab()
} }
fun getQrCodeImg(orderId: String, userId: String? = null, totalFee: String?=null, block: (String?) -> Unit) { fun getQrCodeImg(
userViewModel.getQrCodeImg(orderId = orderId, userId = userId, totalFee = totalFee) { qrCodeImg -> orderId: String,
userId: String? = null,
totalFee: String? = null,
block: (String?) -> Unit
) {
userViewModel.getQrCodeImg(
orderId = orderId,
userId = userId,
totalFee = totalFee
) { qrCodeImg ->
runOnUiThread { runOnUiThread {
if (qrCodeImg.isNullOrBlank()) { if (qrCodeImg.isNullOrBlank()) {
ToastUtils.showToast("获取二维码失败") //ToastUtils.showToast("获取二维码失败")
return@runOnUiThread return@runOnUiThread
} }
block(qrCodeImg) block(qrCodeImg)
@@ -218,7 +207,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
userViewModel.memberPay(param) { userViewModel.memberPay(param) {
runOnUiThread { runOnUiThread {
if (it.not()) { if (it.not()) {
ToastUtils.showToast("支付失败,请稍后重试") //ToastUtils.showToast("支付失败,请稍后重试")
return@runOnUiThread return@runOnUiThread
} }
block() block()
@@ -242,14 +231,72 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
binding.llPayTab.gone() binding.llPayTab.gone()
} }
fun getMemberInfoByPhone(phone: String, key: String, block: (MemberInfo?) -> Unit) {
userViewModel.getMemberInfoByPhone(phone, key) { memberInfo ->
runOnUiThread {
block(memberInfo)
}
}
}
fun getMemberInfoById(userId: String, block: (MemberInfo?) -> Unit) {
userViewModel.getMemberInfoById(memberId = userId) { memberInfo ->
runOnUiThread {
block(memberInfo)
}
}
}
// private val intervalExecutor by lazy { IntervalExecutor() } fun bindOrder(userId: String, block: (Boolean) -> Unit) {
// private var payTaskJob: Job? = null val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
// fun paySuccessCallback() { val mode = if (pickupMode == 1) 1 else 2
// payTaskJob = intervalExecutor.startIntervalTaskWithInitialDelay(5000, 10000) { userViewModel.bindOrder(userId, foodOrderId, mode = mode) { bindResult ->
// runOnUiThread {
block(bindResult)
}
}
}
// fun bindOrder(userId: String, block: () -> Unit) {
// val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
// val mode = if (pickupMode == 1) 1 else 2
// userViewModel.bindOrder(userId, foodOrderId, mode = mode) { bindResult ->
// runOnUiThread {
// if (bindResult.not()) {
// hideWaitingDialog()
// //ToastUtils.showToast("订单绑定失败")
// return@runOnUiThread
// }
// binding.root.postDelayed({
// hideWaitingDialog()
// showPayInfo(type = 1, isVip = true, memberInfo = memberInfo)
// hidePayTab()
// block()
// }, 1000)
// }
// }
// }
// fun getMemberInfoByPhone(phone: String, key: String, block: (MemberInfo) -> Unit) {
// userViewModel.getMemberInfoByPhone(phone, key) { memberInfo ->
// runOnUiThread {
// if (memberInfo == null) {
// hideWaitingDialog()
// //ToastUtils.showToast("查询会员信息失败,请稍后重试")
// return@runOnUiThread
// }
// block(memberInfo)
// }
// }
// }
// fun getMemberInfo(userId: String, block: (MemberInfo) -> Unit) {
// userViewModel.getMemberInfoById(memberId = userId) { memberInfo ->
// runOnUiThread {
// if (memberInfo == null) {
// hideWaitingDialog()
// //ToastUtils.showToast("查询会员信息失败,请稍后重试")
// return@runOnUiThread
// }
// block(memberInfo)
// }
// } // }
// } // }
} }
@@ -10,7 +10,6 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.camera.view.PreviewView import androidx.camera.view.PreviewView
import androidx.core.net.toUri
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@@ -40,14 +39,13 @@ import kotlinx.coroutines.launch
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber import timber.log.Timber
import java.io.File
import kotlin.getValue import kotlin.getValue
class CollectFragment : BaseFragment<FragmentCollectBinding>() { class CollectFragment : BaseFragment<FragmentCollectBinding>() {
companion object { companion object {
private const val TAG = "CollectFragment" private const val TAG = "CollectFragment"
const val MAX_COUNT = 100 const val MAX_COUNT = 102
} }
private var selectedFoodId: String? = "" private var selectedFoodId: String? = ""
private var selectedFoodName: String? = "" private var selectedFoodName: String? = ""
@@ -339,8 +337,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
private fun clearData() { private fun clearData() {
foodCollectionList.forEach { foodCollectionList.forEach {
it.bitmap = null it.bitmap = null
it.imageVector = null
it.imageFile = null
it.isShowCamera = true it.isShowCamera = true
it.isFinish = false it.isFinish = false
it.uploadSuccess = false
} }
collectionAdapter.notifyDataSetChanged() collectionAdapter.notifyDataSetChanged()
@@ -13,9 +13,9 @@ import com.sw.plate.utils.ToastUtils
class CashPayFragment : BaseFragment<FragmentCashPayBinding>() { class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
private var payActivity: PayActivity? = null private lateinit var payActivity: PayActivity
private var foodName: String? = null private var foodName: String? = null
private var payAmount: String? = null private var payAmount: Double? = null
var presentation: CashPayPresentation? = null var presentation: CashPayPresentation? = null
@@ -24,20 +24,21 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
} }
override fun initialize() { override fun initialize() {
payActivity = requireActivity() as? PayActivity payActivity = requireActivity() as PayActivity
payActivity.foodInfo?.let {
foodName = payActivity?.foodInfo?.foodName foodName = it.foodName
payAmount = payActivity?.foodInfo?.specPrice.format2String(2) payAmount = (it.specPrice?:0.0) * payActivity.eatNum
binding.tvRealAmount.text = getAmountText(payAmount?:"") }
binding.tvRealAmount.text = getAmountText(payAmount.format2String(2))
binding.btnConfirmPayFinish.setOnClickListener { binding.btnConfirmPayFinish.setOnClickListener {
payActivity?.cashPay(hashMapOf( payActivity.cashPay(hashMapOf(
//标价金额(单位为元) //标价金额(单位为元)
"totalFee" to (payAmount?:""), "totalFee" to payAmount.format2String(2),
//订单类型(0付款1会员充值) //订单类型(0付款1会员充值)
"orderType" to "0", "orderType" to "0",
//商户订单号 //商户订单号
"orderNo" to (payActivity?.foodOrderId?:""), "orderNo" to payActivity.foodOrderId,
//支付来源:0线下收款 、3:线上纯会员支付 101:支付宝主动、102:支付宝被动、201:微信主动、202:微信被动 //支付来源:0线下收款 、3:线上纯会员支付 101:支付宝主动、102:支付宝被动、201:微信主动、202:微信被动
"paySource" to "0" "paySource" to "0"
)) { paySuccess -> )) { paySuccess ->
@@ -45,7 +46,7 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
ToastUtils.showToast("接口调用失败") ToastUtils.showToast("接口调用失败")
return@cashPay return@cashPay
} }
payActivity?.showPaySuccess( false) payActivity.showPaySuccess( false)
} }
} }
showSubScreen() showSubScreen()
@@ -74,11 +75,11 @@ 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
it.payAmount = payAmount it.payAmount = payAmount.format2String(2)
} }
presentation?.show() presentation?.show()
} }
@@ -9,9 +9,9 @@ import com.sw.dualscreen.presentation.pay.FacePayPresentation
class FacePayFragment : BaseFragment<FragmentFacePayBinding>() { class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
private var payActivity: PayActivity? = null private lateinit var payActivity: PayActivity
private var foodName: String? = null private var foodName: String? = null
private var payAmount: String? = null private var payAmount: Double? = null
var presentation: FacePayPresentation? = null var presentation: FacePayPresentation? = null
override fun inflateViewBinding(): FragmentFacePayBinding { override fun inflateViewBinding(): FragmentFacePayBinding {
return FragmentFacePayBinding.inflate(layoutInflater) return FragmentFacePayBinding.inflate(layoutInflater)
@@ -22,8 +22,10 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
// binding.tvFaceState.setOnClickListener { // binding.tvFaceState.setOnClickListener {
// payActivity?.showPayResult() // payActivity?.showPayResult()
// } // }
foodName = payActivity?.foodInfo?.foodName payActivity.foodInfo?.let {
payAmount = payActivity?.foodInfo?.specPrice.format2String(2) foodName = it.foodName
payAmount = (it.vipPrice?:0.0) * payActivity.eatNum
}
showSubScreen() showSubScreen()
} }
@@ -56,16 +58,16 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
// 查找副屏(通常索引为1 // 查找副屏(通常索引为1
if (displays.size > 1) { if (displays.size > 1) {
presentation = FacePayPresentation( presentation = FacePayPresentation(
activity = payActivity!!, activity = payActivity,
display = displays[1], display = displays[1],
userViewModel = payActivity!!.userViewModel, userViewModel = payActivity.userViewModel,
recognizeViewModel = payActivity!!.recognizeViewModel, recognizeViewModel = payActivity.recognizeViewModel,
// parentTextureView = binding.parentTextureView, // parentTextureView = binding.parentTextureView,
) { ) {
presentation?.dismiss() presentation?.dismiss()
}.also { }.also {
it.foodName = foodName it.foodName = foodName
it.payAmount = payAmount it.payAmount = payAmount.format2String(2)
} }
presentation?.show() presentation?.show()
} }
@@ -1,28 +1,82 @@
package com.sw.dualscreen.activity.fragment.pay package com.sw.dualscreen.activity.fragment.pay
import com.sw.dualscreen.GlobalKey
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.FragmentNumberPayBinding import com.sw.dualscreen.databinding.FragmentNumberPayBinding
import com.sw.dualscreen.ext.format2String
import com.sw.dualscreen.ext.hideKeyboard import com.sw.dualscreen.ext.hideKeyboard
import com.sw.dualscreen.model.response.MemberInfo
import com.sw.dualscreen.presentation.pay.CashPayPresentation import com.sw.dualscreen.presentation.pay.CashPayPresentation
import com.sw.dualscreen.utils.SPUtil
import com.sw.plate.utils.ToastUtils
class NumberPayFragment: BaseFragment<FragmentNumberPayBinding>() { class NumberPayFragment : BaseFragment<FragmentNumberPayBinding>() {
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: Double? = null
var presentation: CashPayPresentation? = null var presentation: CashPayPresentation? = null
override fun inflateViewBinding(): FragmentNumberPayBinding { override fun inflateViewBinding(): FragmentNumberPayBinding {
return FragmentNumberPayBinding.inflate(layoutInflater) return FragmentNumberPayBinding.inflate(layoutInflater)
} }
override fun initialize() { override fun initialize() {
binding.root.hideKeyboard() binding.root.setOnClickListener { v ->
v.hideKeyboard()
}
payActivity = requireActivity() as PayActivity payActivity = requireActivity() as PayActivity
foodName = payActivity.foodInfo?.foodName payActivity.foodInfo?.let {
payAmount = "36.80" foodName = it.foodName
payAmount = (it.specPrice ?: 0.0) * payActivity.eatNum
}
binding.btnConfirm.setOnClickListener { v ->
val phone = binding.etInputPhone.text.toString().trim()
val key = binding.etInputNumber.text.toString().trim()
if (phone.isBlank() || key.isBlank()) {
ToastUtils.showToast("请输入会员验证信息")
return@setOnClickListener
}
payActivity.showWaitingDialog("加载中,请稍后……")
v.hideKeyboard()
// payActivity.getMemberInfoByPhone(phone, key) { memberInfo ->
// payActivity.bindOrder(memberInfo.id?:"") {
// ToastUtils.showToast("会员验证成功")
// }
// }
payActivity.getMemberInfoByPhone(phone, key) { memberInfo ->
if (memberInfo == null) {
payActivity.hideWaitingDialog()
//ToastUtils.showToast("查询会员信息失败,请稍后重试")
return@getMemberInfoByPhone
}
//绑定订单使用faceUserId
payActivity.bindOrder(memberInfo.faceUserId ?: "") { bindResult ->
if (bindResult.not()) {
payActivity.hideWaitingDialog()
//ToastUtils.showToast("订单绑定失败")
return@bindOrder
}
binding.root.postDelayed({
payActivity.hideWaitingDialog()
payActivity.showPayInfo(type = 1, isVip = true, memberInfo = memberInfo)
payActivity.hidePayTab()
}, 1000)
}
}
// getMemberInfo(phone, key) { memberInfo ->
// bindOrder(memberInfo.id ?: "") {
// binding.root.postDelayed({
// payActivity.hideWaitingDialog()
// payActivity.showPayInfo(type = 1, isVip = true, memberInfo = memberInfo)
// payActivity.hidePayTab()
// }, 1000)
// }
// }
}
showSubScreen() showSubScreen()
} }
@@ -54,9 +108,31 @@ class NumberPayFragment: BaseFragment<FragmentNumberPayBinding>() {
presentation?.dismiss() presentation?.dismiss()
}.also { }.also {
it.foodName = foodName it.foodName = foodName
it.payAmount = payAmount it.payAmount = payAmount.format2String(2)
} }
presentation?.show() presentation?.show()
} }
} }
// private fun bindOrder(userId: String, block: () -> Unit) {
// payActivity.bindOrder(userId) { bindResult ->
// if (bindResult.not()) {
// payActivity.hideWaitingDialog()
// //ToastUtils.showToast("订单绑定失败")
// return@bindOrder
// }
// block()
// }
// }
// private fun getMemberInfo(phone: String, key: String, block: (MemberInfo) -> Unit) {
// payActivity.getMemberInfoByPhone(phone, key) { memberInfo ->
// if (memberInfo == null) {
// payActivity.hideWaitingDialog()
// //ToastUtils.showToast("查询会员信息失败,请稍后重试")
// return@getMemberInfoByPhone
// }
// block(memberInfo)
// }
// }
} }
@@ -42,7 +42,7 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
return FragmentPayResultBinding.inflate(layoutInflater) return FragmentPayResultBinding.inflate(layoutInflater)
} }
private var payActivity: PayActivity? = null private lateinit var payActivity: PayActivity
override fun initialize() { override fun initialize() {
payActivity = activity as PayActivity payActivity = activity as PayActivity
binding.btnBack.setOnClickListener { binding.btnBack.setOnClickListener {
@@ -54,7 +54,7 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
} }
if (memberInfo != null) { if (memberInfo != null) {
totalPrice = payActivity?.foodInfo?.vipPrice ?: 0.0 totalPrice = (payActivity.foodInfo?.vipPrice ?: 0.0) * payActivity.eatNum
binding.layoutVip.visible() binding.layoutVip.visible()
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
@@ -62,7 +62,7 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
loadUserInfo(memberInfo!!) loadUserInfo(memberInfo!!)
} else { } else {
binding.layoutVip.gone() binding.layoutVip.gone()
totalPrice = payActivity?.foodInfo?.specPrice ?: 0.0 totalPrice = (payActivity.foodInfo?.specPrice ?: 0.0) * payActivity.eatNum
} }
when (pageType) { when (pageType) {
@@ -77,7 +77,7 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
binding.tvRealAmount.text = SpannedUtils.getAmountText( binding.tvRealAmount.text = SpannedUtils.getAmountText(
listOf( listOf(
TextBean(text = "¥", textSize = 36), TextBean(text = "¥", textSize = 36),
TextBean(text = realPayPrice.format2String(2), textSize = 60), TextBean(text = totalPrice.format2String(2), textSize = 60),
) )
) )
@@ -100,12 +100,12 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
isEnabled = true isEnabled = true
//点击支付,接口成功打开成功页面 //点击支付,接口成功打开成功页面
setOnClickListener { setOnClickListener {
payActivity?.showWaitingDialog("支付中,请稍后……") payActivity.showWaitingDialog("支付中,请稍后……")
memberPay(totalPrice.format2String(2)) { memberPay(totalPrice.format2String(2)) {
binding.root.postDelayed({ binding.root.postDelayed({
payActivity?.hideWaitingDialog() payActivity.hideWaitingDialog()
payActivity?.showPaySuccess(true) payActivity.showPaySuccess(true)
},1000) }, 1000)
} }
} }
} }
@@ -113,16 +113,18 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
binding.ivPayQrCode.visible() binding.ivPayQrCode.visible()
binding.btnConfirmPay.isEnabled = false binding.btnConfirmPay.isEnabled = false
val payAmount = totalPrice - balance val payAmount = totalPrice - balance
payActivity?.getQrCodeImg( payActivity.getQrCodeImg(
orderId = payActivity!!.foodOrderId, orderId = payActivity.foodOrderId,
userId = memberInfo!!.id, userId = memberInfo!!.id,
totalFee = payAmount.format2String(2) totalFee = payAmount.format2String(2)
) { qrCodeImg -> ) { qrCodeImg ->
binding.ivPayQrCode.load(qrCodeImg) binding.ivPayQrCode.load(qrCodeImg)
//更新副屏二维码
payActivity.updateQrCodeImage(qrCodeImg)
} }
paySuccessCallback { paySuccessCallback {
//扫码成功回调打开成功页面,后端处理余额扣除 //扫码成功回调打开成功页面,后端处理余额扣除
payActivity?.showPaySuccess(true) payActivity.showPaySuccess(true)
// if (balance > 0.0) { // if (balance > 0.0) {
// memberPay(balance.format2String(2)) { // memberPay(balance.format2String(2)) {
// //扫码成功+会员支付完成后打开成功页面 // //扫码成功+会员支付完成后打开成功页面
@@ -146,13 +148,15 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
TextBean(text = remainBalance.format2String(2), textSize = 36), TextBean(text = remainBalance.format2String(2), textSize = 36),
) )
) )
binding.tvPayAmount.text = "收款金额 ${realPayPrice.format2String(2)}"
binding.tvPayInfo.text = val showTotalPrice = totalPrice.format2String(2)
"应收 ${totalPrice.format2String(2)} 元,余额扣除 ${expensesBalance.format2String(2)}" binding.tvPayAmount.text = "收款金额 $showTotalPrice"
val showExpensesBalance = expensesBalance.format2String(2)
binding.tvPayInfo.text = "应收 $showTotalPrice 元,余额扣除 $showExpensesBalance"
} else { } else {
binding.tvPayAmount.text = "收款金额 ${totalPrice.format2String(2)}" binding.tvPayAmount.text = "收款金额 ${totalPrice.format2String(2)}"
binding.tvPayInfo.text = binding.tvPayInfo.text = "应收 ${totalPrice.format2String(2)}"
"应收 ${totalPrice.format2String(2)}"
} }
} }
@@ -165,8 +169,10 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
//余额 //余额
private var balance = 0.0 private var balance = 0.0
//实际支付金额 //实际支付金额
private var realPayPrice = 0.0 private var realPayPrice = 0.0
//扣除余额 //扣除余额
private var expensesBalance = 0.0 private var expensesBalance = 0.0
@@ -174,20 +180,41 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
val list: MutableList<TextBean> = mutableListOf() val list: MutableList<TextBean> = mutableListOf()
list.add(TextBean(text = "余额扣除 ", textSize = 30, textColor = "#FF889AC2")) list.add(TextBean(text = "余额扣除 ", textSize = 30, textColor = "#FF889AC2"))
list.add(TextBean(text = "-${expensesBalance.format2String(2)}", textSize = 30, textColor = "#FF0A1428")) list.add(
TextBean(
text = "-${expensesBalance.format2String(2)}",
textSize = 30,
textColor = "#FF0A1428",
isBold = true
)
)
if (balance >= totalPrice) { if (balance >= totalPrice) {
//余额大于等于总价格,使用余额支付 //余额大于等于总价格,使用余额支付
TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF889AC2") list.add(TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF889AC2"))
val remainingBalance = balance - totalPrice val remainingBalance = balance - totalPrice
TextBean(text = remainingBalance.format2String(2), textSize = 30, textColor = "#FF0A1428") list.add(
TextBean(
text = remainingBalance.format2String(2),
textSize = 30,
textColor = "#FF0A1428",
isBold = true
)
)
} else { } else {
//余额小于总价格,使用余额+扫码支付 //余额小于总价格,使用余额+扫码支付
//实际支付金额 //实际支付金额
TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF889AC2") list.add(TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF889AC2"))
TextBean(text = realPayPrice.format2String(2), textSize = 30, textColor = "#FF0A1428") list.add(
TextBean(text = "", textSize = 30, textColor = "#FF889AC2") TextBean(
text = realPayPrice.format2String(2),
textSize = 30,
textColor = "#FF0A1428",
isBold = true
)
)
} }
list.add(TextBean(text = "", textSize = 30, textColor = "#FF889AC2"))
return list return list
} }
@@ -204,14 +231,14 @@ class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
phone phone
} }
private fun memberPay(total: String, callback:()-> Unit) { private fun memberPay(total: String, callback: () -> Unit) {
payActivity?.run { payActivity.run {
memberPay( memberPay(
param = hashMapOf( param = hashMapOf(
//支付金额 //支付金额
"totalFee" to total, "totalFee" to total,
//订单号 //订单号
"orderNo" to payActivity!!.foodOrderId, "orderNo" to payActivity.foodOrderId,
//用户id //用户id
"memberId" to memberInfo!!.id!! "memberId" to memberInfo!!.id!!
), ),
@@ -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: Double? = null
private var payQrCodePic: String? = null private var payQrCodePic: String? = null
var presentation: ScanQrCodePayPresentation? = null var presentation: ScanQrCodePayPresentation? = null
private var countDownJob: Job? = null private var countDownJob: Job? = null
@@ -36,11 +36,16 @@ class ScanQrCodePayFragment : BaseFragment<FragmentScanQrcodePayBinding>() {
override fun initialize() { override fun initialize() {
payActivity = requireActivity() as PayActivity payActivity = requireActivity() as PayActivity
foodName = payActivity.foodInfo?.foodName payActivity.foodInfo?.let {
payAmount = payActivity.foodInfo?.specPrice.format2String(2) foodName = it.foodName
binding.tvRealAmount.text = getAmountText(payAmount ?: "") payAmount = (it.specPrice?:0.0)*payActivity.eatNum
}
payActivity.getQrCodeImg(orderId = payActivity.foodOrderId, totalFee = payAmount) { binding.tvRealAmount.text = getAmountText(payAmount.format2String(2))
//不需要绑定会员id
payActivity.getQrCodeImg(
orderId = payActivity.foodOrderId,
totalFee = payAmount.format2String(2)
) {
payQrCodePic = it payQrCodePic = it
binding.ivPayQrCode.load(payQrCodePic) binding.ivPayQrCode.load(payQrCodePic)
binding.tvPayResult.text = "待支付(60s)..." binding.tvPayResult.text = "待支付(60s)..."
@@ -84,7 +89,7 @@ class ScanQrCodePayFragment : BaseFragment<FragmentScanQrcodePayBinding>() {
presentation?.dismiss() presentation?.dismiss()
}.also { }.also {
it.foodName = foodName it.foodName = foodName
it.totalPrice = payActivity.foodInfo?.specPrice ?: 0.0 it.totalPrice = payAmount ?: 0.0
it.payQrCodePic = payQrCodePic it.payQrCodePic = payQrCodePic
} }
presentation?.show() presentation?.show()
@@ -30,12 +30,17 @@ data class FoodOrder(
var notPay: Boolean, var notPay: Boolean,
//备注 //备注
var remark: String? = "", var remark: String? = "",
//即放即取-1,称重-2
var mode: Int
) )
@Parcelize @Parcelize
data class MemberInfo( data class MemberInfo(
//会员id //会员id
val id: String?, val id: String?,
//刷脸识别用户ID
val faceUserId: String?,
//手机号 //手机号
val phone: String?, val phone: String?,
//姓名 //姓名
@@ -53,7 +58,8 @@ data class MemberInfo(
data class TextBean( data class TextBean(
var text: String, var text: String,
var textSize: Int = 0, var textSize: Int = 0,
var textColor: String? = null var textColor: String? = null,
var isBold: Boolean = false
) )
data class UserNutrition( data class UserNutrition(
@@ -105,3 +111,8 @@ data class UserEnergy(
var fruitsVegetables:Double, var fruitsVegetables:Double,
var meatEggs:Double, var meatEggs:Double,
) )
data class RespCodeMsg(
val code: String?,
val msg: String?
)
@@ -213,11 +213,20 @@ interface ApiService {
* APP根据id获取会员或员工信息及余额 * APP根据id获取会员或员工信息及余额
*/ */
@GET @GET
suspend fun getMemberInfo( suspend fun getMemberInfoById(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getUserInfoBalanceById", @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getUserInfoBalanceById",
@Query("id") memberId: String, @Query("id") memberId: String,
): ApiResponse<MemberInfo?> ): ApiResponse<MemberInfo?>
/**
* 根据手机尾号和密钥查询员工信息及余额
*/
@POST
suspend fun getMemberInfoByPhone(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/queryUserInfoBalanceByPhone",
@Body param: HashMap<String, String>
): ApiResponse<MemberInfo?>
/** /**
* 绑定用户与订单号 * 绑定用户与订单号
*/ */
@@ -225,7 +234,8 @@ interface ApiService {
suspend fun bindOrder( suspend fun bindOrder(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/bingOrder", @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/bingOrder",
@Query("userId") userId: String, @Query("userId") userId: String,
@Query("orderNo") orderId: String @Query("orderNo") orderId: String,
@Query("mode") mode: Int
): ApiResponse<Any?> ): ApiResponse<Any?>
@@ -121,18 +121,18 @@ class MainScreenPresentation(
.d("updateWeight lastWeight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1") .d("updateWeight lastWeight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1")
mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0 mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0) val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
if (mealPickupMode == 1 && chargeMode == 0) { // if (mealPickupMode == 1 && chargeMode == 0) {
//余量计量+计费模式 // //余量计量+计费模式
if (isFirstGetWeight && lastWeight > 5) { // if (isFirstGetWeight && lastWeight > 5) {
recognitionWeight = lastWeight // recognitionWeight = lastWeight
isFirstGetWeight = false // isFirstGetWeight = false
} // }
if (lastWeight > 5) { // if (lastWeight > 5) {
//余量计量,有重量的情况下不回到重新识别状态 // //余量计量,有重量的情况下不回到重新识别状态
return // return
} // }
isFirstGetWeight = true // isFirstGetWeight = true
} // }
if (currentStep == 2 && lastWeight <= 5 && isGoStep1) { if (currentStep == 2 && lastWeight <= 5 && isGoStep1) {
//人脸识别过程中,秤上物品拿走 //人脸识别过程中,秤上物品拿走
isGoStep1 = false isGoStep1 = false
@@ -1109,7 +1109,8 @@ class MainScreenPresentation(
activity.createOrder( activity.createOrder(
foodInfo = currentFood!!, foodInfo = currentFood!!,
foodWeight = lastWeight.roundToInt(), foodWeight = lastWeight.roundToInt(),
eatWeight = eatWeight.roundToInt() eatWeight = eatWeight.roundToInt(),
eatNum = activity.getEatNum(eatWeight, currentFood!!.specWeight)
) { ) {
if (MyApp.DEBUG) { if (MyApp.DEBUG) {
ToastUtils.showToast("订单已生成") ToastUtils.showToast("订单已生成")
@@ -4,36 +4,28 @@ import android.Manifest
import android.app.Dialog import android.app.Dialog
import android.app.Presentation import android.app.Presentation
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Point import android.graphics.Point
import android.hardware.Camera import android.hardware.Camera
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.Spanned
import android.text.SpannedString
import android.text.TextUtils import android.text.TextUtils
import android.text.style.AbsoluteSizeSpan
import android.view.Display import android.view.Display
import android.view.TextureView
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.text.buildSpannedString
import androidx.lifecycle.Observer 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.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.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.GsonUtils import com.sw.dualscreen.utils.SPUtil
import com.sw.dualscreen.utils.SpannedUtils 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
@@ -248,7 +240,7 @@ class FacePayPresentation(
// recognitionWeight = lastWeight // recognitionWeight = lastWeight
lastFaceTrackId = compareResult.trackId lastFaceTrackId = compareResult.trackId
val faceEntity = compareResult.faceEntity val faceEntity = compareResult.faceEntity
var userId = faceEntity.userName val userId = faceEntity.userName
if (userId == null) return@Observer if (userId == null) return@Observer
// TODO: 测试支付用户id // TODO: 测试支付用户id
// userId = "1987710988425662466" // userId = "1987710988425662466"
@@ -566,77 +558,66 @@ class FacePayPresentation(
} }
private var lastFaceTrackId: Int = -1 // 上一次的人脸信息 private var lastFaceTrackId: Int = -1 // 上一次的人脸信息
private var mDialogWaiting: CustomDialog? = null
/**
* 显示等待提示框
*/
fun showWaitingDialog(tip: String?): Dialog? {
hideWaitingDialog()
val view = View.inflate(activity, R.layout.dialog_waiting, null)
if (!TextUtils.isEmpty(tip)) (view.findViewById<View?>(R.id.tvTip) as TextView).text = tip
mDialogWaiting = CustomDialog(activity, view, R.style.MyDialog)
mDialogWaiting!!.show()
mDialogWaiting!!.setCancelable(true)
return mDialogWaiting
}
/**
* 隐藏等待提示框
*/
fun hideWaitingDialog() {
mDialogWaiting?.dismiss()
mDialogWaiting = null
}
override fun onDisplayRemoved() { override fun onDisplayRemoved() {
super.onDisplayRemoved() super.onDisplayRemoved()
onDismissListener() onDismissListener()
} }
private fun faceRecSuccess(userId: String) { private fun faceRecSuccess(userId: String) {
activity.runOnUiThread { activity.runOnUiThread {
showWaitingDialog("加载中,请稍后……") activity.showWaitingDialog("加载中,请稍后……")
} }
getMemberInfo(userId) { memberInfo -> activity.getMemberInfoById(userId) { memberInfo ->
bindOrder(userId) { if (memberInfo == null) {
activity.hideWaitingDialog()
//ToastUtils.showToast("查询会员信息失败,请稍后重试")
return@getMemberInfoById
}
activity.bindOrder(memberInfo.faceUserId?:"") { bindResult ->
if (bindResult.not()) {
activity.hideWaitingDialog()
//ToastUtils.showToast("订单绑定失败")
return@bindOrder
}
binding.root.postDelayed({ binding.root.postDelayed({
hideWaitingDialog() activity.hideWaitingDialog()
activity.showPayInfo(type = 1, isVip = true, memberInfo = memberInfo) activity.showPayInfo(type = 1, isVip = true, memberInfo = memberInfo)
activity.hidePayTab() activity.hidePayTab()
binding.root.postDelayed({ binding.root.postDelayed({
dismiss() dismiss()
}, 500) }, 500)
}, 1500) }, 1000)
}
}
}
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)
} }
} }
} }
// private fun bindOrder(userId: String, block: () -> Unit) {
// val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
// val mode = if (pickupMode == 1) 1 else 2
// userViewModel.bindOrder(userId, activity.foodOrderId, mode = mode) { bindResult ->
// activity.runOnUiThread {
// if (bindResult.not()) {
// activity.hideWaitingDialog()
// //ToastUtils.showToast("订单绑定失败")
// return@runOnUiThread
// }
// block()
// }
// }
// }
// private fun getMemberInfo(userId: String, block:(MemberInfo)-> Unit) {
// userViewModel.getMemberInfoById(memberId = userId) { memberInfo ->
// activity.runOnUiThread {
// if (memberInfo == null) {
// activity.hideWaitingDialog()
// //ToastUtils.showToast("查询会员信息失败,请稍后重试")
// return@runOnUiThread
// }
// block(memberInfo)
// }
// }
// }
} }
@@ -74,12 +74,11 @@ class ScanQrCodePayPresentation(
1 -> { 1 -> {
val memberInfo = activity.memberInfo val memberInfo = activity.memberInfo
binding.layoutVip.run { binding.layoutVip.run {
if (memberInfo!=null) visible() else gone() if (memberInfo != null) visible() else gone()
} }
binding.layoutPaySuccess.gone() binding.layoutPaySuccess.gone()
binding.layoutScanQrCode.visible() binding.layoutScanQrCode.visible()
//totalPrice = if (memberInfo != null) activity.foodInfo?.vipPrice else activity.foodInfo?.specPrice
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
@@ -110,13 +109,13 @@ class ScanQrCodePayPresentation(
2 -> { 2 -> {
val memberInfo = activity.memberInfo val memberInfo = activity.memberInfo
binding.layoutVip.run { binding.layoutVip.run {
if (memberInfo!=null) visible() else gone() if (memberInfo != null) visible() else gone()
} }
binding.layoutPaySuccess.visible() binding.layoutPaySuccess.visible()
binding.layoutScanQrCode.gone() binding.layoutScanQrCode.gone()
//totalPrice = activity.foodInfo?.vipPrice ?: 0.0 balance = if (memberInfo != null) (memberInfo.topUpBalance
balance = if (memberInfo != null) (memberInfo.topUpBalance ?: 0.0)+(memberInfo.rewardBalance ?: 0.0) else 0.0 ?: 0.0) + (memberInfo.rewardBalance ?: 0.0) else 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
@@ -136,6 +135,10 @@ class ScanQrCodePayPresentation(
} }
} }
fun loadQrCodeImage(qrCodeUrl: String?) {
binding.ivPayQrCode.load(qrCodeUrl)
}
private fun loadUserInfo(item: MemberInfo) { private fun loadUserInfo(item: MemberInfo) {
binding.ivHeadPic.load(item.faceUrl?.ifBlank { R.drawable.ic_avatar_default }) binding.ivHeadPic.load(item.faceUrl?.ifBlank { R.drawable.ic_avatar_default })
binding.tvUserName.text = item.name binding.tvUserName.text = item.name
@@ -154,24 +157,37 @@ class ScanQrCodePayPresentation(
TextBean( TextBean(
text = "-${expensesBalance.format2String(2)}", text = "-${expensesBalance.format2String(2)}",
textSize = 30, textSize = 30,
textColor = "#FF0A1428" textColor = "#FF0A1428",
isBold = true
) )
) )
if (balance >= totalPrice) { if (balance >= totalPrice) {
//余额大于等于总价格,使用余额支付 //余额大于等于总价格,使用余额支付
TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF5E7585") list.add(TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF5E7585"))
val remainingBalance = balance - totalPrice val remainingBalance = balance - totalPrice
TextBean( list.add(
text = remainingBalance.format2String(2), textSize = 30, textColor = "#FF0A1428" TextBean(
text = remainingBalance.format2String(2),
textSize = 30,
textColor = "#FF0A1428",
isBold = true
)
) )
} else { } else {
//余额小于总价格,使用余额+扫码支付 //余额小于总价格,使用余额+扫码支付
//实际支付金额 //实际支付金额
TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF5E7585") list.add(TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF5E7585"))
TextBean(text = realPayPrice.format2String(2), textSize = 30, textColor = "#FF0A1428") list.add(
TextBean(text = "", textSize = 30, textColor = "#FF5E7585") TextBean(
text = realPayPrice.format2String(2),
textSize = 30,
textColor = "#FF0A1428",
isBold = true
)
)
} }
list.add(TextBean(text = "", textSize = 30, textColor = "#FF5E7585"))
return list return list
} }
@@ -2,6 +2,8 @@ package com.sw.dualscreen.repository
import com.google.gson.JsonParseException import com.google.gson.JsonParseException
import com.sw.dualscreen.model.response.ApiResponse import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.RespCodeMsg
import com.sw.dualscreen.utils.GsonUtils
import retrofit2.HttpException import retrofit2.HttpException
import timber.log.Timber import timber.log.Timber
import java.io.IOException import java.io.IOException
@@ -18,7 +20,13 @@ abstract class BaseRepository {
when (e) { when (e) {
is HttpException -> { is HttpException -> {
ApiResponse(code = "${e.code()}", msg = e.message()) val respData = e.response()?.errorBody()?.string()
val respCodeMsg = GsonUtils.fromJson(respData, RespCodeMsg::class.java)
if (respCodeMsg?.msg.isNullOrBlank()) {
ApiResponse(code = "${e.code()}", msg = e.message())
} else {
ApiResponse(code = respCodeMsg.code ?:"-10", msg = respCodeMsg.msg)
}
} }
is SocketTimeoutException -> { is SocketTimeoutException -> {
@@ -222,15 +222,33 @@ class RemoteRepository constructor(
} }
} }
suspend fun bindOrder(userId: String, orderId: String): ApiResponse<Any?> { /**
* 绑定订单
*/
suspend fun bindOrder(userId: String, orderId: String, mode: Int): ApiResponse<Any?> {
return safeApiCall { return safeApiCall {
apiService.bindOrder(userId = userId, orderId = orderId) apiService.bindOrder(userId = userId, orderId = orderId, mode = mode)
} }
} }
suspend fun getMemberInfo(memberId: String): ApiResponse<MemberInfo?> { /**
* 根据id查询会员信息
*/
suspend fun getMemberInfoById(memberId: String): ApiResponse<MemberInfo?> {
return safeApiCall { return safeApiCall {
apiService.getMemberInfo(memberId = memberId) apiService.getMemberInfoById(memberId = memberId)
}
}
/**
* 根据id查询会员信息
*/
suspend fun getMemberInfoByPhone(phone: String, key: String): ApiResponse<MemberInfo?> {
return safeApiCall {
apiService.getMemberInfoByPhone(param = hashMapOf(
"phone" to phone,
"password" to key
))
} }
} }
@@ -1,9 +1,11 @@
package com.sw.dualscreen.utils package com.sw.dualscreen.utils
import android.graphics.Typeface
import android.text.Spanned import android.text.Spanned
import android.text.SpannedString import android.text.SpannedString
import android.text.style.AbsoluteSizeSpan import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import com.sw.dualscreen.model.response.TextBean import com.sw.dualscreen.model.response.TextBean
@@ -24,6 +26,9 @@ object SpannedUtils {
if (it.textColor.isNullOrBlank().not()) { if (it.textColor.isNullOrBlank().not()) {
setSpan(ForegroundColorSpan(it.textColor!!.toColorInt()), start, end, SPAN_FLAGS) setSpan(ForegroundColorSpan(it.textColor!!.toColorInt()), start, end, SPAN_FLAGS)
} }
if (it.isBold) {
setSpan(StyleSpan(Typeface.BOLD), start, end, SPAN_FLAGS)
}
} }
} }
} }
@@ -9,12 +9,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.UserFaceModel2
import com.sw.dualscreen.model.response.UserNutrition import com.sw.dualscreen.model.response.UserNutrition
import com.sw.dualscreen.objbox.CollectedFoodInfo import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.utils.GsonUtils
import com.sw.dualscreen.utils.SPUtil import com.sw.dualscreen.utils.SPUtil
import com.sw.plate.App import com.sw.plate.App
import com.sw.plate.utils.Base64 import com.sw.plate.utils.Base64
@@ -277,10 +275,16 @@ class UserViewModel : BaseViewModel() {
/** /**
* 获取支付二维码 * 获取支付二维码
*/ */
fun getQrCodeImg(orderId: String, userId: String? = null, totalFee: String?=null, block: (String?) -> Unit) { fun getQrCodeImg(
orderId: String,
userId: String? = null,
totalFee: String? = null,
block: (String?) -> Unit
) {
Timber.tag(TAG).d("getQrCodeImg orderId = $orderId, userId = $userId") Timber.tag(TAG).d("getQrCodeImg orderId = $orderId, userId = $userId")
launch { launch {
val response = repository.getQrCodeImg(orderNo = orderId, memberId = userId, totalFee = totalFee) val response =
repository.getQrCodeImg(orderNo = orderId, memberId = userId, totalFee = totalFee)
if (parseResponse(response)) { if (parseResponse(response)) {
block(response.data) block(response.data)
} else { } else {
@@ -419,10 +423,10 @@ class UserViewModel : BaseViewModel() {
/** /**
* 绑定订单 * 绑定订单
*/ */
fun bindOrder(userId: String, orderId: String, block: (Boolean) -> Unit) { fun bindOrder(userId: String, orderId: String, mode: Int, block: (Boolean) -> Unit) {
Timber.tag(TAG).d("bindOrder") Timber.tag(TAG).d("bindOrder")
launchWithLoading { launchWithLoading {
val response = repository.bindOrder(userId = userId, orderId = orderId) val response = repository.bindOrder(userId = userId, orderId = orderId, mode =mode)
if (parseResponse(response)) { if (parseResponse(response)) {
block(true) block(true)
} else { } else {
@@ -431,10 +435,22 @@ class UserViewModel : BaseViewModel() {
} }
} }
fun getMemberInfo(memberId: String, block: (MemberInfo?) -> Unit) { fun getMemberInfoById(memberId: String, block: (MemberInfo?) -> Unit) {
Timber.tag(TAG).d("getMemberInfo") Timber.tag(TAG).d("getMemberInfo")
launchWithLoading { launchWithLoading {
val response = repository.getMemberInfo(memberId) val response = repository.getMemberInfoById(memberId)
if (parseResponse(response)) {
block(response.data)
} else {
block(null)
}
}
}
fun getMemberInfoByPhone(phone: String, key: String, block: (MemberInfo?) -> Unit) {
Timber.tag(TAG).d("getMemberInfo")
launchWithLoading {
val response = repository.getMemberInfoByPhone(phone, key)
if (parseResponse(response)) { if (parseResponse(response)) {
block(response.data) block(response.data)
} else { } else {
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<shape android:shape="rectangle">
<solid android:color="#FFFF3232"/>
<size android:width="120dp" android:height="5dp"/>
<corners android:radius="5dp"/>
</shape>
</item>
<item android:state_checked="false">
<shape android:shape="rectangle">
<solid android:color="@color/transparent"/>
<size android:width="120dp" android:height="5dp"/>
<corners android:radius="5dp"/>
</shape>
</item>
</selector>
@@ -31,6 +31,7 @@
android:text="经营设置" android:text="经营设置"
android:textColor="@color/setting_radio" android:textColor="@color/setting_radio"
android:textSize="30sp" android:textSize="30sp"
android:drawableBottom="@drawable/line_shape_horizontal"
android:textStyle="bold" /> android:textStyle="bold" />
<RadioButton <RadioButton
@@ -46,6 +47,7 @@
android:text="餐品采集" android:text="餐品采集"
android:textColor="@color/setting_radio" android:textColor="@color/setting_radio"
android:textSize="30sp" android:textSize="30sp"
android:drawableBottom="@drawable/line_shape_horizontal"
android:textStyle="bold" /> android:textStyle="bold" />
</RadioGroup> </RadioGroup>
@@ -53,6 +53,7 @@
tools:ignore="Autofill,HardcodedText,LabelFor,TextFields" /> tools:ignore="Autofill,HardcodedText,LabelFor,TextFields" />
<androidx.appcompat.widget.AppCompatButton <androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_marginTop="64dp" android:layout_marginTop="64dp"
android:layout_marginHorizontal="64dp" android:layout_marginHorizontal="64dp"
@@ -128,7 +128,7 @@
android:layout_width="300dp" android:layout_width="300dp"
android:layout_height="300dp" android:layout_height="300dp"
android:layout_marginVertical="50dp" android:layout_marginVertical="50dp"
android:src="@drawable/ic_qrcode" tools:src="@drawable/ic_qrcode"
android:visibility="visible" /> android:visibility="visible" />
<TextView <TextView
@@ -62,8 +62,8 @@
android:text="请扫码支付或出示付款码" android:text="请扫码支付或出示付款码"
android:textColor="#FF5E7585" android:textColor="#FF5E7585"
android:textSize="24sp" android:textSize="24sp"
android:textStyle="bold"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<!-- android:textStyle="bold"-->
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
+14 -13
View File
@@ -1,25 +1,26 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:cardCornerRadius="5dp" app:cardCornerRadius="8dp"
app:cardBackgroundColor="#000000"
app:cardPreventCornerOverlap="true"> app:cardPreventCornerOverlap="true">
<TextView <TextView
android:id="@+id/toast_tv" android:id="@+id/toast_tv"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:paddingTop="10dp"
android:maxLines="1" android:paddingBottom="10dp"
android:paddingStart="15dp" android:gravity="center_vertical"
android:paddingTop="5dp" android:paddingStart="20dp"
android:paddingEnd="15dp" android:paddingEnd="20dp"
android:paddingBottom="5dp" android:textColor="#ffffff"
android:textColor="@color/black" android:textSize="36sp"
android:textSize="28sp" /> tools:text="TextView" />
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>