接口调试、增加人脸识别后主副屏支付金额逻辑、其它优化
This commit is contained in:
@@ -108,6 +108,9 @@ dependencies {
|
|||||||
implementation(libs.pytorch.android)
|
implementation(libs.pytorch.android)
|
||||||
implementation(libs.pytorch.android.torchvision)
|
implementation(libs.pytorch.android.torchvision)
|
||||||
|
|
||||||
|
implementation("io.github.scwang90:refresh-layout-kernel:3.0.0-alpha")
|
||||||
|
implementation("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
|
||||||
|
|
||||||
val objectboxVersion = "5.0.1"
|
val objectboxVersion = "5.0.1"
|
||||||
debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion")
|
debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion")
|
||||||
// releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
|
// releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ package com.sw.dualscreen.activity
|
|||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.content.res.Resources
|
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.Display
|
import android.view.Display
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
@@ -93,6 +92,19 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
|||||||
mDialogWaiting = null
|
mDialogWaiting = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showWaitingDialog2(tip: String?) {
|
||||||
|
if (mDialogWaiting == null) {
|
||||||
|
hideWaitingDialog()
|
||||||
|
val view = View.inflate(this, R.layout.dialog_waiting, null)
|
||||||
|
mDialogWaiting = CustomDialog(this, view, R.style.MyDialog)
|
||||||
|
mDialogWaiting!!.show()
|
||||||
|
mDialogWaiting!!.setCancelable(true)
|
||||||
|
}
|
||||||
|
val contentView = mDialogWaiting?.findViewById<ViewGroup>(android.R.id.content)
|
||||||
|
val tvTip = contentView?.findViewById<TextView>(R.id.tvTip)
|
||||||
|
tvTip?.text = tip
|
||||||
|
}
|
||||||
|
|
||||||
private var launchPermissionCallback: IActivityResult.RequestPermissionCallback? = null
|
private var launchPermissionCallback: IActivityResult.RequestPermissionCallback? = null
|
||||||
|
|
||||||
fun requestSinglePermissionResult(
|
fun requestSinglePermissionResult(
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import com.sw.dualscreen.databinding.ActivityCollectedFoodBinding
|
|||||||
import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
|
import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
|
||||||
import com.sw.dualscreen.dialog.WarnDialog
|
import com.sw.dualscreen.dialog.WarnDialog
|
||||||
import com.sw.dualscreen.ext.addOnActionSearchListener
|
import com.sw.dualscreen.ext.addOnActionSearchListener
|
||||||
|
import com.sw.dualscreen.ext.gone
|
||||||
import com.sw.dualscreen.ext.hideKeyboard
|
import com.sw.dualscreen.ext.hideKeyboard
|
||||||
|
import com.sw.dualscreen.ext.visible
|
||||||
import com.sw.dualscreen.objbox.CollectedFoodInfo
|
import com.sw.dualscreen.objbox.CollectedFoodInfo
|
||||||
import com.sw.dualscreen.objbox.Food
|
import com.sw.dualscreen.objbox.Food
|
||||||
import com.sw.dualscreen.objbox.ObjectBox
|
import com.sw.dualscreen.objbox.ObjectBox
|
||||||
@@ -21,6 +23,11 @@ import io.objectbox.Box
|
|||||||
import io.objectbox.kotlin.boxFor
|
import io.objectbox.kotlin.boxFor
|
||||||
|
|
||||||
class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val PAGE_SIZE = 100
|
||||||
|
}
|
||||||
|
|
||||||
private val viewModel by viewModels<UserViewModel>()
|
private val viewModel by viewModels<UserViewModel>()
|
||||||
override fun getViewModel(): BaseViewModel {
|
override fun getViewModel(): BaseViewModel {
|
||||||
return viewModel
|
return viewModel
|
||||||
@@ -33,7 +40,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
|||||||
private val list: MutableList<CollectedFoodInfo> = mutableListOf()
|
private val list: MutableList<CollectedFoodInfo> = mutableListOf()
|
||||||
private val adapter by lazy {
|
private val adapter by lazy {
|
||||||
CollectedFoodNewAdapter(list).apply {
|
CollectedFoodNewAdapter(list).apply {
|
||||||
isStateViewEnable = true
|
// isStateViewEnable = true
|
||||||
addOnItemChildClickListener(R.id.ivDeleteFood) { _, _, position ->
|
addOnItemChildClickListener(R.id.ivDeleteFood) { _, _, position ->
|
||||||
deleteGoods(position)
|
deleteGoods(position)
|
||||||
}
|
}
|
||||||
@@ -42,6 +49,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
|||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
super.initialize()
|
super.initialize()
|
||||||
|
//binding.root.setOnClickListener { it.hideKeyboard() }
|
||||||
binding.rvFoodList.let {
|
binding.rvFoodList.let {
|
||||||
it.layoutManager = LinearLayoutManager(this)
|
it.layoutManager = LinearLayoutManager(this)
|
||||||
it.adapter = adapter
|
it.adapter = adapter
|
||||||
@@ -65,14 +73,30 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
|||||||
ToastUtils.showToast("请输入物品名称")
|
ToastUtils.showToast("请输入物品名称")
|
||||||
return@addOnActionSearchListener
|
return@addOnActionSearchListener
|
||||||
}
|
}
|
||||||
|
pageNo = 1
|
||||||
getCollectGoods(searchName)
|
getCollectGoods(searchName)
|
||||||
}
|
}
|
||||||
v.addTextChangedListener {
|
v.addTextChangedListener {
|
||||||
if (it.isNullOrBlank()) {
|
if (it.isNullOrBlank()) {
|
||||||
|
pageNo = 1
|
||||||
getCollectGoods()
|
getCollectGoods()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.refreshLayout.let {
|
||||||
|
it.setEnableRefresh(true)
|
||||||
|
it.setEnableLoadMore(false)
|
||||||
|
it.setOnRefreshListener {
|
||||||
|
pageNo = 1
|
||||||
|
getCollectGoods()
|
||||||
|
}
|
||||||
|
it.setOnLoadMoreListener {
|
||||||
|
getCollectGoods()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.emptyInclude.root.setOnClickListener {
|
||||||
|
it.hideKeyboard()
|
||||||
|
}
|
||||||
getCollectGoods()
|
getCollectGoods()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,54 +105,81 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
|||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun getCollectGoods(searchName: String? = null) {
|
private fun getCollectGoods(searchName: String? = null) {
|
||||||
if (box == null) {
|
// if (box == null) {
|
||||||
box = ObjectBox.boxStore.boxFor(Food::class)
|
// box = ObjectBox.boxStore.boxFor(Food::class)
|
||||||
}
|
// }
|
||||||
list.clear()
|
// list.clear()
|
||||||
val totalList = box?.all
|
// val totalList = box?.all
|
||||||
?.filter { it.name!=null }
|
// ?.filter { it.name!=null }
|
||||||
?.groupBy { it.name!! }
|
// ?.groupBy { it.name!! }
|
||||||
?.map { CollectedFoodInfo(foodName = it.key, foodCount = it.value.size) }
|
// ?.map { CollectedFoodInfo(foodName = it.key, foodCount = it.value.size) }
|
||||||
//var queryMap:Map<String, List<Food>> ?= null
|
// //var queryMap:Map<String, List<Food>> ?= null
|
||||||
if (searchName.isNullOrBlank().not()) {
|
// if (searchName.isNullOrBlank().not()) {
|
||||||
//queryMap = totalMap?.filter { it.key.contains(searchName) }
|
// //queryMap = totalMap?.filter { it.key.contains(searchName) }
|
||||||
val temp = totalList?.filter { it.foodName?.contains(searchName) == true}
|
// val temp = totalList?.filter { it.foodName?.contains(searchName) == true}
|
||||||
if (temp.isNullOrEmpty().not()) {
|
// if (temp.isNullOrEmpty().not()) {
|
||||||
list.addAll(temp)
|
// list.addAll(temp)
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
if (totalList.isNullOrEmpty().not()) {
|
// if (totalList.isNullOrEmpty().not()) {
|
||||||
list.addAll(totalList)
|
// list.addAll(totalList)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
adapter.notifyDataSetChanged()
|
// adapter.notifyDataSetChanged()
|
||||||
if (list.isEmpty()) {
|
// if (list.isEmpty()) {
|
||||||
loadEmptyView()
|
// loadEmptyView()
|
||||||
}
|
// }
|
||||||
binding.root.hideKeyboard()
|
|
||||||
|
|
||||||
viewModel.getCollectedFoodList(pageNo = pageNo) {
|
viewModel.getCollectedFoodList(
|
||||||
if (it.isNotEmpty()) {
|
pageNo = pageNo,
|
||||||
list.addAll(it)
|
pageSize = PAGE_SIZE,
|
||||||
|
foodName = searchName ?: ""
|
||||||
|
) { items ->
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
|
loadFoodList(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun loadFoodList(items: List<CollectedFoodInfo>) {
|
||||||
|
finishRefresh()
|
||||||
|
if (pageNo == 1 && items.isEmpty()) {
|
||||||
|
list.clear()
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
|
loadEmptyView()
|
||||||
|
binding.refreshLayout.setEnableLoadMore(false)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
binding.refreshLayout.visible()
|
||||||
|
binding.emptyInclude.root.gone()
|
||||||
|
if (pageNo == 1) {
|
||||||
|
list.clear()
|
||||||
}
|
}
|
||||||
|
list.addAll(items)
|
||||||
|
val isEnableLoadMore = items.size >= PAGE_SIZE
|
||||||
|
if (isEnableLoadMore) {
|
||||||
|
pageNo++
|
||||||
}
|
}
|
||||||
|
binding.refreshLayout.setEnableLoadMore(isEnableLoadMore)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
binding.root.hideKeyboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pageNo = 1
|
private var pageNo = 1
|
||||||
|
|
||||||
private var emptyBinding: LayoutEmptySearchBinding? = null
|
// private var emptyBinding: LayoutEmptySearchBinding? = null
|
||||||
private fun loadEmptyView() {
|
private fun loadEmptyView() {
|
||||||
if (emptyBinding == null) {
|
binding.refreshLayout.gone()
|
||||||
emptyBinding =
|
binding.emptyInclude.root.visible()
|
||||||
LayoutEmptySearchBinding.inflate(layoutInflater, binding.rvFoodList, false)
|
//if (emptyBinding == null) {
|
||||||
}
|
// emptyBinding =
|
||||||
emptyBinding?.root?.let { layout ->
|
// LayoutEmptySearchBinding.inflate(layoutInflater, binding.rvFoodList, false)
|
||||||
layout.setOnClickListener { layout.hideKeyboard() }
|
//}
|
||||||
adapter.stateView = layout
|
//emptyBinding?.root?.let { layout ->
|
||||||
}
|
// layout.setOnClickListener { layout.hideKeyboard() }
|
||||||
|
// adapter.stateView = layout
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteGoods(position: Int) {
|
private fun deleteGoods(position: Int) {
|
||||||
@@ -154,4 +205,16 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
|
|||||||
}.start()
|
}.start()
|
||||||
}).show()
|
}).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun finishRefresh() {
|
||||||
|
binding.refreshLayout.let {
|
||||||
|
if (pageNo == 1) {
|
||||||
|
it.finishRefresh(500)
|
||||||
|
} else {
|
||||||
|
it.finishLoadMore(500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ import android.os.Looper
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewOutlineProvider
|
import android.view.ViewOutlineProvider
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.core.CameraSelector
|
import androidx.camera.core.CameraSelector
|
||||||
import androidx.camera.core.ImageAnalysis
|
import androidx.camera.core.ImageAnalysis
|
||||||
@@ -21,20 +22,22 @@ import androidx.camera.lifecycle.ProcessCameraProvider
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
import com.sw.dualscreen.GlobalData
|
||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
import com.sw.dualscreen.adapter.SearchFoodAdapter
|
import com.sw.dualscreen.adapter.SearchFoodAdapter
|
||||||
import com.sw.dualscreen.databinding.ActivityMainBinding
|
import com.sw.dualscreen.databinding.ActivityMainBinding
|
||||||
import com.sw.dualscreen.ext.dp
|
import com.sw.dualscreen.ext.dp
|
||||||
import com.sw.dualscreen.ext.gone
|
import com.sw.dualscreen.ext.gone
|
||||||
|
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.FoodInfo
|
||||||
|
import com.sw.dualscreen.model.response.FoodOrder
|
||||||
import com.sw.dualscreen.objbox.FoodModule
|
import com.sw.dualscreen.objbox.FoodModule
|
||||||
import com.sw.dualscreen.objbox.FoodModule.IdNameScore
|
import com.sw.dualscreen.objbox.FoodModule.IdNameScore
|
||||||
import com.sw.dualscreen.presentation.MainScreenPresentation
|
import com.sw.dualscreen.presentation.MainScreenPresentation
|
||||||
import com.sw.dualscreen.sdk.SensorScaleUtils
|
import com.sw.dualscreen.sdk.SensorScaleUtils
|
||||||
import com.sw.dualscreen.utils.BitmapSaver
|
import com.sw.dualscreen.utils.BitmapSaver
|
||||||
import com.sw.dualscreen.utils.Debouncer
|
import com.sw.dualscreen.utils.Debouncer
|
||||||
import com.sw.dualscreen.utils.GlideUtils
|
|
||||||
import com.sw.dualscreen.utils.GsonUtils
|
import com.sw.dualscreen.utils.GsonUtils
|
||||||
import com.sw.dualscreen.utils.ImageUtil
|
import com.sw.dualscreen.utils.ImageUtil
|
||||||
import com.sw.dualscreen.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
@@ -65,7 +68,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private val viewModel by viewModels<UserViewModel>()
|
private val viewModel by viewModels<UserViewModel>()
|
||||||
private var imageCapture: ImageCapture? = null
|
private var imageCapture: ImageCapture? = null
|
||||||
private var isAnalyzing = true // 控制是否进行图像分析
|
var isAnalyzing = true // 控制是否进行图像分析
|
||||||
|
|
||||||
// private var presentation: SecondaryScreenPresentation? = null
|
// private var presentation: SecondaryScreenPresentation? = null
|
||||||
private var presentation: MainScreenPresentation? = null
|
private var presentation: MainScreenPresentation? = null
|
||||||
private val executor = Executors.newSingleThreadExecutor()
|
private val executor = Executors.newSingleThreadExecutor()
|
||||||
@@ -86,7 +90,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var checkedItem: FoodInfo? = null
|
var checkedItem: FoodInfo? = null
|
||||||
private var imageAnalysis: ImageAnalysis? = null
|
private var imageAnalysis: ImageAnalysis? = null
|
||||||
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
|
private var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>? = null
|
||||||
private var canIdentify: Boolean = false
|
private var canIdentify: Boolean = false
|
||||||
@@ -106,6 +110,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
super.initialize()
|
super.initialize()
|
||||||
|
addBackEventListener()
|
||||||
FoodModule.init(this)
|
FoodModule.init(this)
|
||||||
initView()
|
initView()
|
||||||
setupSecondaryDisplay()
|
setupSecondaryDisplay()
|
||||||
@@ -204,45 +209,44 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
// binding.tvRescan.setOnClickListener {
|
// binding.tvRescan.setOnClickListener {
|
||||||
// debouncer.debounce { recognizeFood() }
|
// debouncer.debounce { recognizeFood() }
|
||||||
// }
|
// }
|
||||||
binding.btnPay.setOnClickListener {
|
binding.btnPay.let {
|
||||||
|
it.run {
|
||||||
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
if (mode == 0) visible() else gone()
|
||||||
|
}
|
||||||
|
it.setOnClickListener { v ->
|
||||||
if (checkedItem == null) {
|
if (checkedItem == null) {
|
||||||
ToastUtils.showToast("暂无识别数据,请搜索选择")
|
ToastUtils.showToast("暂无识别数据,请搜索选择")
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
presentation?.dismiss()
|
createOrder(checkedItem!!)
|
||||||
startActivity(Intent(this, PayActivity::class.java).apply {
|
}
|
||||||
putExtra(PayActivity.FOOD_INFO, checkedItem)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCurrentFood(foodInfo: FoodInfo?) {
|
fun updateCurrentFood(foodInfo: FoodInfo?) {
|
||||||
if (foodInfo != null) {
|
if (foodInfo == null) {
|
||||||
presentation?.updateFood(foodInfo)
|
|
||||||
binding.tvFoodName.text = foodInfo.foodName
|
|
||||||
binding.previewView.visibility = View.GONE
|
|
||||||
binding.ivImg.visibility = View.VISIBLE
|
|
||||||
val imgUrl = foodInfo.imgUrl
|
|
||||||
if (TextUtils.isEmpty(imgUrl)) {
|
|
||||||
takePhoto { imgUri ->
|
|
||||||
GlideUtils.loadRoundCornerImage(this, imgUri, binding.ivImg, 12)
|
|
||||||
presentation?.updateFood(foodInfo.copy(imgUrl = imgUri.toString()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (foodInfo.photoUri != null) {
|
|
||||||
GlideUtils.loadRoundCornerImage(this, foodInfo.photoUri, binding.ivImg, 12)
|
|
||||||
} else {
|
|
||||||
GlideUtils.loadRoundCornerImage(this, foodInfo.imgUrl, binding.ivImg, 12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pauseAnalysis()
|
|
||||||
} else {
|
|
||||||
binding.tvFoodName.text = "-"
|
binding.tvFoodName.text = "-"
|
||||||
binding.previewView.visibility = View.VISIBLE
|
binding.previewView.visibility = View.VISIBLE
|
||||||
binding.ivImg.visibility = View.GONE
|
binding.ivImg.visibility = View.GONE
|
||||||
resumeAnalysis()
|
resumeAnalysis()
|
||||||
viewModel.cleanIdentifiedFoodInfoList()
|
viewModel.cleanIdentifiedFoodInfoList()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
pauseAnalysis()
|
||||||
|
presentation?.updateFood(foodInfo)
|
||||||
|
binding.tvFoodName.text = foodInfo.foodName
|
||||||
|
binding.previewView.visibility = View.GONE
|
||||||
|
binding.ivImg.visibility = View.VISIBLE
|
||||||
|
if (foodInfo.foodImg.isNullOrBlank()) {
|
||||||
|
takePhoto { imgUri ->
|
||||||
|
binding.ivImg.load(imgUri)
|
||||||
|
presentation?.updateFood(foodInfo.copy(foodImg = imgUri.toString()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.ivImg.load(foodInfo.photoUri ?: foodInfo.foodImg)
|
||||||
|
}
|
||||||
|
//pauseAnalysis()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerDataChange() {
|
override fun registerDataChange() {
|
||||||
@@ -343,21 +347,13 @@ 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("registerDataChange识别后查询接口数据:${GsonUtils.toJson(list)},识别数据:${GsonUtils.toJson(scoreList)}")
|
Timber.d(
|
||||||
// TODO: 临时测试数据,后续删除-------------------
|
"registerDataChange识别后查询接口数据:${GsonUtils.toJson(list)},识别数据:${
|
||||||
//if (list.isEmpty()) {
|
GsonUtils.toJson(
|
||||||
// //binding.flPay.visible()
|
scoreList
|
||||||
// //binding.recyclerview.visible()
|
)
|
||||||
// //list.add(FoodInfo(foodName = "豆角茄子"))
|
}"
|
||||||
// //list.add(FoodInfo(foodName = "豆芽炒粉条"))
|
)
|
||||||
// //list.add(FoodInfo(foodName = "岐山臊子面"))
|
|
||||||
// //list.add(FoodInfo(foodName = "肉末干拌面"))
|
|
||||||
// //list.add(FoodInfo(foodName = "雪菜肉丝面"))
|
|
||||||
// //list.add(FoodInfo(foodName = "康帅博方便面"))
|
|
||||||
// //list.add(FoodInfo(foodName = "担担面"))
|
|
||||||
// //list.add(FoodInfo(foodName = "四合一干拌面"))
|
|
||||||
//}
|
|
||||||
// TODO: 临时测试数据,后续删除-------------------
|
|
||||||
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
|
||||||
@@ -476,7 +472,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
fun resumeAnalysis() {
|
fun resumeAnalysis() {
|
||||||
Timber.d("resumeAnalysis isAnalyzing = $isAnalyzing")
|
Timber.d("resumeAnalysis isAnalyzing = $isAnalyzing")
|
||||||
if (isAnalyzing) return
|
if (isAnalyzing) return
|
||||||
isAnalyzing = true
|
// isAnalyzing = true
|
||||||
imageAnalysis?.setAnalyzer(executor) { imageProxy ->
|
imageAnalysis?.setAnalyzer(executor) { imageProxy ->
|
||||||
if (presentation?.currentStep == 1) {
|
if (presentation?.currentStep == 1) {
|
||||||
val bitmap = imageProxy.toBitmap()
|
val bitmap = imageProxy.toBitmap()
|
||||||
@@ -629,6 +625,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
||||||
presentation?.updateMealPickupMode(mode ?: 0)
|
presentation?.updateMealPickupMode(mode ?: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
// 取消定时器
|
// 取消定时器
|
||||||
@@ -658,4 +655,61 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
handler.postDelayed(timeoutRunnable, TIME_OUT)
|
handler.postDelayed(timeoutRunnable, TIME_OUT)
|
||||||
lastTouchTime = System.currentTimeMillis()
|
lastTouchTime = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createOrder(foodInfo: FoodInfo) {
|
||||||
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
val realWeight = (lastWeight * 1000).roundToInt()
|
||||||
|
val order = FoodOrder(
|
||||||
|
deviceId = GlobalData.deviceId,
|
||||||
|
foodId = foodInfo.foodId,
|
||||||
|
foodName = foodInfo.foodName ?: "",
|
||||||
|
foodMaterialId = foodInfo.foodMaterialId ?: "",
|
||||||
|
specId = foodInfo.specId ?: "",
|
||||||
|
foodWeight = realWeight,
|
||||||
|
eatWeight = realWeight,
|
||||||
|
//根据specId对应规格重量计算
|
||||||
|
eatNum = getEatNum(realWeight, foodInfo.specWeight ?: 0.0),
|
||||||
|
userId = null,
|
||||||
|
notPay = mode != 0,
|
||||||
|
)
|
||||||
|
viewModel.createOrder(order) { orderId ->
|
||||||
|
runOnUiThread {
|
||||||
|
if (orderId.isBlank()) {
|
||||||
|
ToastUtils.showToast("订单id为空")
|
||||||
|
return@runOnUiThread
|
||||||
|
}
|
||||||
|
foodOrderId = orderId
|
||||||
|
presentation?.dismiss()
|
||||||
|
startActivity(Intent(this, PayActivity::class.java).apply {
|
||||||
|
putExtra(PayActivity.FOOD_INFO, foodInfo)
|
||||||
|
putExtra(PayActivity.FOOD_ORDER_ID, orderId)
|
||||||
|
})
|
||||||
|
// ToastUtils.showToast("订单已生成")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEatNum(realWeight: Int, specWeight: Double): Int {
|
||||||
|
if (realWeight == 0 || specWeight == 0.0) return 0
|
||||||
|
return (realWeight / specWeight).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var foodOrderId: String = ""
|
||||||
|
private var isExist = false
|
||||||
|
fun addBackEventListener() {
|
||||||
|
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
if (isExist.not()) {
|
||||||
|
ToastUtils.showToast("再按一次退出")
|
||||||
|
isExist = true
|
||||||
|
binding.root.postDelayed({
|
||||||
|
isExist = false
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.sw.dualscreen.activity
|
package com.sw.dualscreen.activity
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
@@ -11,7 +10,7 @@ import com.sw.dualscreen.activity.fragment.pay.PayResultFragment
|
|||||||
import com.sw.dualscreen.activity.fragment.pay.ScanQrCodePayFragment
|
import com.sw.dualscreen.activity.fragment.pay.ScanQrCodePayFragment
|
||||||
import com.sw.dualscreen.databinding.ActivityPayBinding
|
import com.sw.dualscreen.databinding.ActivityPayBinding
|
||||||
import com.sw.dualscreen.model.response.FoodInfo
|
import com.sw.dualscreen.model.response.FoodInfo
|
||||||
import com.sw.dualscreen.presentation.pay.FacePayPresentation
|
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
|
||||||
@@ -22,6 +21,10 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val FOOD_INFO = "foodInfo"
|
const val FOOD_INFO = "foodInfo"
|
||||||
|
const val TOTAL_AMOUNT = "totalAmount"
|
||||||
|
const val FOOD_ORDER_ID = "foodOrderId"
|
||||||
|
|
||||||
|
// const val MEMBER_INFO = "memberInfo"
|
||||||
const val TAG_PAY_QR_CODE = "tagPayQrCode"
|
const val TAG_PAY_QR_CODE = "tagPayQrCode"
|
||||||
const val TAG_PAY_CASH = "tagPayCash"
|
const val TAG_PAY_CASH = "tagPayCash"
|
||||||
const val TAG_PAY_NUMBER = "tagPayNumber"
|
const val TAG_PAY_NUMBER = "tagPayNumber"
|
||||||
@@ -42,16 +45,22 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
|
|
||||||
var foodInfo: FoodInfo? = null
|
var foodInfo: FoodInfo? = null
|
||||||
|
|
||||||
|
// var totalAmount:Double = 0.0
|
||||||
private var qrCodePayFragment: ScanQrCodePayFragment? = null
|
private var qrCodePayFragment: ScanQrCodePayFragment? = null
|
||||||
private var cashPayFragment: CashPayFragment? = null
|
private var cashPayFragment: CashPayFragment? = null
|
||||||
private var numberPayFragment: NumberPayFragment? = null
|
private var numberPayFragment: NumberPayFragment? = null
|
||||||
var facePayFragment: FacePayFragment? = null
|
var facePayFragment: FacePayFragment? = null
|
||||||
private var payResultFragment: PayResultFragment? = null
|
private var payResultFragment: PayResultFragment? = null
|
||||||
|
|
||||||
|
var foodOrderId:String = ""
|
||||||
|
|
||||||
@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)?:""
|
||||||
|
// totalAmount = intent.getDoubleExtra(TOTAL_AMOUNT,0.0)
|
||||||
|
// memberInfo = intent.getParcelableExtra(MEMBER_INFO)
|
||||||
binding.tvFoodName.text = foodInfo?.foodName
|
binding.tvFoodName.text = foodInfo?.foodName
|
||||||
binding.include.ivPageBack.setOnClickListener { finish() }
|
binding.include.ivPageBack.setOnClickListener { finish() }
|
||||||
binding.include.tvPageTitle.text = "下单结算"
|
binding.include.tvPageTitle.text = "下单结算"
|
||||||
@@ -140,10 +149,10 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fun showPayResult() {
|
// fun showPayResult() {
|
||||||
payResultFragment = PayResultFragment()
|
// payResultFragment = PayResultFragment.instance(1, memberInfo)
|
||||||
showFragment(payResultFragment!!, TAG_PAY_RESULT)
|
// showFragment(payResultFragment!!, TAG_PAY_RESULT)
|
||||||
}
|
// }
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
qrCodePayFragment?.presentation?.dismiss()
|
qrCodePayFragment?.presentation?.dismiss()
|
||||||
@@ -154,8 +163,29 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null
|
private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null
|
||||||
fun paySuccess() {
|
var memberInfo: MemberInfo? = null
|
||||||
showFragment(PayResultFragment(), "")
|
fun showPayInfo(memberInfo: MemberInfo) {
|
||||||
|
this.memberInfo = memberInfo
|
||||||
|
payResultFragment = PayResultFragment.instance(1, memberInfo)
|
||||||
|
showFragment(payResultFragment!!, TAG_PAY_RESULT)
|
||||||
|
if (displays.size > 1) {
|
||||||
|
scanQrCodePayPresentation = ScanQrCodePayPresentation(
|
||||||
|
activity = this,
|
||||||
|
display = displays[1],
|
||||||
|
type = 1
|
||||||
|
) {
|
||||||
|
scanQrCodePayPresentation?.dismiss()
|
||||||
|
}.also {
|
||||||
|
it.foodName = foodInfo?.foodName
|
||||||
|
it.totalPrice = foodInfo?.vipPrice?:0.0
|
||||||
|
}
|
||||||
|
scanQrCodePayPresentation?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showPaySuccess() {
|
||||||
|
payResultFragment = PayResultFragment.instance(2, memberInfo!!)
|
||||||
|
showFragment(payResultFragment!!, TAG_PAY_RESULT)
|
||||||
if (displays.size > 1) {
|
if (displays.size > 1) {
|
||||||
scanQrCodePayPresentation = ScanQrCodePayPresentation(
|
scanQrCodePayPresentation = ScanQrCodePayPresentation(
|
||||||
activity = this,
|
activity = this,
|
||||||
@@ -164,8 +194,8 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
|||||||
) {
|
) {
|
||||||
scanQrCodePayPresentation?.dismiss()
|
scanQrCodePayPresentation?.dismiss()
|
||||||
}.also {
|
}.also {
|
||||||
// it.foodName = foodName
|
it.foodName = foodInfo?.foodName
|
||||||
// it.payAmount = payAmount
|
it.totalPrice = foodInfo?.vipPrice?:0.0
|
||||||
}
|
}
|
||||||
scanQrCodePayPresentation?.show()
|
scanQrCodePayPresentation?.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
binding.rgCharge.let {
|
binding.rgCharge.let {
|
||||||
it.setOnCheckedChangeListener { group, checkedId ->
|
// it.setOnCheckedChangeListener { group, checkedId ->
|
||||||
val mode = if (checkedId == R.id.rbChargeYes) 0 else 1
|
// val mode = if (checkedId == R.id.rbChargeYes) 0 else 1
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_CHARGE_MODE, mode)
|
// SPUtil.getInstance().put(GlobalKey.KEY_CHARGE_MODE, mode)
|
||||||
}
|
// }
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
it.check(if (mode == 0) R.id.rbChargeYes else R.id.rbChargeNot)
|
it.check(if (mode == 0) R.id.rbChargeYes else R.id.rbChargeNot)
|
||||||
}
|
}
|
||||||
binding.rgTakeFood.let {
|
binding.rgTakeFood.let {
|
||||||
it.setOnCheckedChangeListener { group, checkedId ->
|
// it.setOnCheckedChangeListener { group, checkedId ->
|
||||||
val mode = if (checkedId == R.id.rbPickAndPlace) 0 else 1
|
// val mode = if (checkedId == R.id.rbPickAndPlace) 0 else 1
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode)
|
// SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode)
|
||||||
}
|
// }
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
||||||
it.check(if (mode == 0) R.id.rbPickAndPlace else R.id.rbSurplusCalculate)
|
it.check(if (mode == 0) R.id.rbPickAndPlace else R.id.rbSurplusCalculate)
|
||||||
}
|
}
|
||||||
@@ -49,6 +49,8 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
|
|||||||
|
|
||||||
mode = if (binding.rgTakeFood.checkedRadioButtonId == R.id.rbPickAndPlace) 0 else 1
|
mode = if (binding.rgTakeFood.checkedRadioButtonId == R.id.rbPickAndPlace) 0 else 1
|
||||||
SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode)
|
SPUtil.getInstance().put(GlobalKey.KEY_PICKUP_MODE, mode)
|
||||||
|
|
||||||
|
ToastUtils.showToast("设置已保存")
|
||||||
}
|
}
|
||||||
SensorScaleUtils.addWeightListener { value ->
|
SensorScaleUtils.addWeightListener { value ->
|
||||||
val realWeight = (value * 1000).roundToInt()
|
val realWeight = (value * 1000).roundToInt()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.widget.Toast
|
|||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
import com.sw.dualscreen.activity.CollectedFoodActivity
|
import com.sw.dualscreen.activity.CollectedFoodActivity
|
||||||
@@ -30,10 +31,12 @@ import com.sw.dualscreen.objbox.ObjectBox
|
|||||||
import com.sw.dualscreen.utils.BitmapSaver
|
import com.sw.dualscreen.utils.BitmapSaver
|
||||||
import com.sw.dualscreen.utils.CameraUtils
|
import com.sw.dualscreen.utils.CameraUtils
|
||||||
import com.sw.dualscreen.utils.Debouncer
|
import com.sw.dualscreen.utils.Debouncer
|
||||||
|
import com.sw.dualscreen.utils.ImageUploader
|
||||||
import com.sw.dualscreen.utils.ImageUtil
|
import com.sw.dualscreen.utils.ImageUtil
|
||||||
import com.sw.plate.utils.ToastUtils
|
import com.sw.plate.utils.ToastUtils
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.kotlin.boxFor
|
import io.objectbox.kotlin.boxFor
|
||||||
|
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
|
||||||
@@ -44,7 +47,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "CollectFragment"
|
private const val TAG = "CollectFragment"
|
||||||
const val MAX_COUNT = 5
|
const val MAX_COUNT = 100
|
||||||
}
|
}
|
||||||
private var selectedFoodId: String? = ""
|
private var selectedFoodId: String? = ""
|
||||||
private var selectedFoodName: String? = ""
|
private var selectedFoodName: String? = ""
|
||||||
@@ -181,10 +184,8 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
Toast.makeText(requireActivity(), "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
|
Toast.makeText(requireActivity(), "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
vectorThread(){
|
|
||||||
upload()
|
upload()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
|
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
|
||||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||||
@@ -216,42 +217,71 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
|
|
||||||
(requireActivity() as SettingActivity).viewModel.uploadCollectFoodPics(files,params, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun upload() {
|
private fun upload() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val totalFileCount = foodCollectionList.count { it.imageFile != null }
|
||||||
|
settingActivity?.showWaitingDialog("图片上传中0/$totalFileCount")
|
||||||
val params = HashMap<String, RequestBody>()
|
val params = HashMap<String, RequestBody>()
|
||||||
//params["placeId"] = restId.toRequestBody()
|
//params["placeId"] = restId.toRequestBody()
|
||||||
params["foodId"] = checkedItem!!.foodId.toRequestBody()
|
params["foodId"] = checkedItem!!.foodId.toRequestBody()
|
||||||
params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
|
params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
|
||||||
//params["foodVector"] = foodVector.toRequestBody()
|
//params["foodVector"] = foodVector.toRequestBody()
|
||||||
for (index in foodCollectionList.indices step 5) {
|
ImageUploader(
|
||||||
val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
|
totalList = foodCollectionList,
|
||||||
val subList = foodCollectionList.subList(index, end)
|
uploadImage = { batch->
|
||||||
val subFiles = subList.map { it.imageFile }
|
val files = batch.map { it.imageFile }
|
||||||
uploadCollectFoodPics(subFiles, params) { isSuccess->
|
(requireActivity() as SettingActivity).viewModel.uploadCollectFoodPics(files,params)
|
||||||
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
|
},
|
||||||
subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
|
onProgress = { count, batch ->
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
settingActivity?.showWaitingDialog2("图片上传中$count/$totalFileCount")
|
||||||
|
batch.forEach {
|
||||||
|
it.uploadSuccess = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
ToastUtils.showToast("上传失败,请稍后重试")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onComplete = {
|
||||||
|
vectorThread()
|
||||||
|
}
|
||||||
|
).processUploads()
|
||||||
|
}
|
||||||
|
|
||||||
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
|
||||||
// runOnUiThread {
|
// for (index in foodCollectionList.indices step 5) {
|
||||||
// binding.btnUploadImage.text = "待上传图片${count}张"
|
// val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
|
||||||
// if (count == 0) {
|
// val subList = foodCollectionList.subList(index, end)
|
||||||
// Loading.dismiss()
|
// val subFiles = subList.map { it.imageFile }
|
||||||
|
// uploadCollectFoodPics(subFiles, params) { isSuccess->
|
||||||
|
// Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
|
||||||
|
// subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
|
||||||
|
//
|
||||||
|
//// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
|
||||||
|
//// runOnUiThread {
|
||||||
|
//// binding.btnUploadImage.text = "待上传图片${count}张"
|
||||||
|
//// if (count == 0) {
|
||||||
|
//// Loading.dismiss()
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun vectorThread(block:()-> Unit) {
|
private fun vectorThread() {
|
||||||
settingActivity?.showWaitingDialog("加载中……")
|
settingActivity?.showWaitingDialog("加载中……")
|
||||||
Thread {
|
Thread {
|
||||||
foodCollectionList
|
foodCollectionList
|
||||||
// .filter { it.bitmap != null }
|
// .filter { it.bitmap != null }
|
||||||
.filter { it.imageVector != null }
|
// .filter { it.imageVector != null }
|
||||||
.forEachIndexed { index, it ->
|
.forEachIndexed { index, it ->
|
||||||
|
if (it.imageVector == null) {
|
||||||
|
return@forEachIndexed
|
||||||
|
}
|
||||||
image2VectorTask(imageVector = it.imageVector!!, index)
|
image2VectorTask(imageVector = it.imageVector!!, index)
|
||||||
}
|
}
|
||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
|
|||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
payActivity = activity as PayActivity
|
payActivity = activity as PayActivity
|
||||||
binding.tvFaceState.setOnClickListener {
|
// binding.tvFaceState.setOnClickListener {
|
||||||
payActivity?.showPayResult()
|
// payActivity?.showPayResult()
|
||||||
}
|
// }
|
||||||
foodName = payActivity?.foodInfo?.foodName
|
foodName = payActivity?.foodInfo?.foodName
|
||||||
payAmount = "36.80"
|
payAmount = "36.80"
|
||||||
showSubScreen()
|
showSubScreen()
|
||||||
|
|||||||
@@ -1,17 +1,48 @@
|
|||||||
package com.sw.dualscreen.activity.fragment.pay
|
package com.sw.dualscreen.activity.fragment.pay
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
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 androidx.core.graphics.toColorInt
|
||||||
import androidx.core.text.buildSpannedString
|
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
|
||||||
import com.sw.dualscreen.databinding.FragmentPayResultBinding
|
import com.sw.dualscreen.databinding.FragmentPayResultBinding
|
||||||
|
import com.sw.dualscreen.ext.format2String
|
||||||
|
import com.sw.dualscreen.ext.gone
|
||||||
|
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.model.response.FoodInfo
|
||||||
|
import com.sw.dualscreen.model.response.MemberInfo
|
||||||
|
import com.sw.dualscreen.model.response.TextBean
|
||||||
|
import com.sw.dualscreen.utils.SpannedUtils
|
||||||
|
|
||||||
class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
|
class PayResultFragment : BaseFragment<FragmentPayResultBinding>() {
|
||||||
|
|
||||||
|
//type = 0,扫码支付默认显示二维码
|
||||||
|
//type = 1,会员结算显示二维码,是会员则显示名字、头像、手机号、可用余额
|
||||||
|
//type = 2,支付成功,是会员则显示名字、头像、手机号、可用余额
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PAGE_TYPE = "pageType"
|
||||||
|
const val MEMBER_INFO = "memberInfo"
|
||||||
|
fun instance(pageType: Int, memberInfo: MemberInfo): PayResultFragment {
|
||||||
|
return PayResultFragment().apply {
|
||||||
|
arguments = Bundle().also {
|
||||||
|
it.putInt(PAGE_TYPE, pageType)
|
||||||
|
it.putParcelable(MEMBER_INFO, memberInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var pageType: Int = 1
|
||||||
|
private var memberInfo: MemberInfo? = null
|
||||||
|
|
||||||
override fun inflateViewBinding(): FragmentPayResultBinding {
|
override fun inflateViewBinding(): FragmentPayResultBinding {
|
||||||
return FragmentPayResultBinding.inflate(layoutInflater)
|
return FragmentPayResultBinding.inflate(layoutInflater)
|
||||||
}
|
}
|
||||||
@@ -22,19 +53,121 @@ class PayResultFragment: BaseFragment<FragmentPayResultBinding>() {
|
|||||||
binding.btnBack.setOnClickListener {
|
binding.btnBack.setOnClickListener {
|
||||||
//payActivity?.showFacePay()
|
//payActivity?.showFacePay()
|
||||||
}
|
}
|
||||||
|
arguments?.let {
|
||||||
|
pageType = it.getInt(PAGE_TYPE, 0)
|
||||||
|
memberInfo = it.getParcelable(MEMBER_INFO)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalPrice = payActivity?.foodInfo?.vipPrice ?: 0.0
|
||||||
|
balance = (memberInfo?.topUpBalance ?: 0.0) + (memberInfo?.rewardBalance ?: 0.0)
|
||||||
|
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
|
||||||
|
expensesBalance = if (balance >= totalPrice) totalPrice else balance
|
||||||
|
memberInfo?.let { loadUserInfo(it) }
|
||||||
|
|
||||||
|
when (pageType) {
|
||||||
|
0 -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
binding.layoutPayInfo.visible()
|
||||||
|
binding.layoutPaySuccess.gone()
|
||||||
|
|
||||||
|
binding.tvRealAmount.text = SpannedUtils.getAmountText(
|
||||||
|
listOf(
|
||||||
|
TextBean(text = "¥", textSize = 36),
|
||||||
|
TextBean(text = realPayPrice.format2String(2), textSize = 60),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
//余额扣除 -36.80 元,扣除后可用余额 10.00 元
|
||||||
|
//余额扣除 -16.80 元,还需支付 20.00 元
|
||||||
|
|
||||||
|
binding.tvUserBalance.text = SpannedUtils.getAmountText(
|
||||||
|
listOf(
|
||||||
|
TextBean(text = "¥", textSize = 24),
|
||||||
|
TextBean(text = balance.format2String(2), textSize = 36),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.tvAccountInfo.text = SpannedUtils.getAmountText(
|
||||||
|
getAmountList()
|
||||||
|
)
|
||||||
|
if (balance >= totalPrice) {
|
||||||
|
binding.ivPayQrCode.invisible()
|
||||||
|
binding.btnConfirmPay.isEnabled = true
|
||||||
|
} else {
|
||||||
|
binding.ivPayQrCode.visible()
|
||||||
|
// binding.ivPayQrCode.load(payQrCodePic)
|
||||||
|
binding.btnConfirmPay.isEnabled = false
|
||||||
|
}
|
||||||
|
//点击支付接口成功打开成功页面,或者扫码手动成功回调打开成功页面
|
||||||
|
binding.btnConfirmPay.setOnClickListener {
|
||||||
|
payActivity?.showWaitingDialog("支付中,请稍后……")
|
||||||
|
binding.root.postDelayed({
|
||||||
|
payActivity?.hideWaitingDialog()
|
||||||
|
payActivity?.showPaySuccess()
|
||||||
|
},1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
binding.layoutPayInfo.gone()
|
||||||
|
binding.layoutPaySuccess.visible()
|
||||||
|
|
||||||
|
binding.tvPayInfo.text =
|
||||||
|
"应收 ${totalPrice.format2String(2)} 元,余额扣除 ${expensesBalance.format2String(2)} 元"
|
||||||
|
binding.tvPayAmount.text = "收款金额 ${realPayPrice.format2String(2)} 元"
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//总价格
|
||||||
|
private var totalPrice = 0.0
|
||||||
|
|
||||||
|
//余额
|
||||||
|
private var balance = 0.0
|
||||||
|
//实际支付金额
|
||||||
|
private var realPayPrice = 0.0
|
||||||
|
//扣除余额
|
||||||
|
private var expensesBalance = 0.0
|
||||||
|
|
||||||
|
private fun getAmountList(): List<TextBean> {
|
||||||
|
val list: MutableList<TextBean> = mutableListOf()
|
||||||
|
|
||||||
|
list.add(TextBean(text = "余额扣除 ", textSize = 30, textColor = "#FF889AC2"))
|
||||||
|
list.add(TextBean(text = "-${expensesBalance.format2String(2)}", textSize = 30, textColor = "#FF0A1428"))
|
||||||
|
|
||||||
|
if (balance >= totalPrice) {
|
||||||
|
//余额大于等于总价格,使用余额支付
|
||||||
|
TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF889AC2")
|
||||||
|
val remainingBalance = balance - totalPrice
|
||||||
|
TextBean(text = remainingBalance.format2String(2), textSize = 30, textColor = "#FF0A1428")
|
||||||
|
} else {
|
||||||
|
//余额小于总价格,使用余额+扫码支付
|
||||||
|
//实际支付金额
|
||||||
|
TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF889AC2")
|
||||||
|
TextBean(text = realPayPrice.format2String(2), textSize = 30, textColor = "#FF0A1428")
|
||||||
|
TextBean(text = " 元", textSize = 30, textColor = "#FF889AC2")
|
||||||
|
}
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadUserInfo(item: MemberInfo) {
|
||||||
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
||||||
binding.tvUserName.text = "张三"
|
binding.tvUserName.text = item.name
|
||||||
binding.tvUserPhone.text = "132****5678"
|
|
||||||
binding.tvUserBalance.text = getBalanceText("0.00")
|
val phone = item.phone ?: ""
|
||||||
binding.tvPayAmount.text = "收款金额 20.00 元"
|
binding.tvUserPhone.text =
|
||||||
binding.tvPayInfo.text = "应收 38.00 元,余额扣除 16.80 元"
|
if (phone.length == 11)
|
||||||
|
phone.replace(phone.substring(3, 7), "****")
|
||||||
|
else
|
||||||
|
phone
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBalanceText(amount: String): SpannedString {
|
|
||||||
return buildSpannedString {
|
|
||||||
append("¥", AbsoluteSizeSpan(20, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
append(amount, AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.sw.dualscreen.presentation.pay.ScanQrCodePayPresentation
|
|||||||
import com.sw.dualscreen.utils.countDownByFlow
|
import com.sw.dualscreen.utils.countDownByFlow
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import com.sw.dualscreen.databinding.FragmentScanQrcodePayBinding
|
import com.sw.dualscreen.databinding.FragmentScanQrcodePayBinding
|
||||||
|
import com.sw.dualscreen.ext.format2String
|
||||||
|
|
||||||
class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
|
class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
|
|||||||
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)
|
||||||
payQrCodePic = R.drawable.ic_qrcode
|
payQrCodePic = R.drawable.ic_qrcode
|
||||||
binding.tvRealAmount.text = getAmountText(payAmount?:"")
|
binding.tvRealAmount.text = getAmountText(payAmount?:"")
|
||||||
binding.ivPayQrCode.load(payQrCodePic)
|
binding.ivPayQrCode.load(payQrCodePic)
|
||||||
@@ -75,7 +76,7 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
|
|||||||
presentation?.dismiss()
|
presentation?.dismiss()
|
||||||
}.also {
|
}.also {
|
||||||
it.foodName = foodName
|
it.foodName = foodName
|
||||||
it.payAmount = payAmount
|
it.totalPrice = payActivity.foodInfo?.specPrice?:0.0
|
||||||
it.payQrCodePic = payQrCodePic
|
it.payQrCodePic = payQrCodePic
|
||||||
}
|
}
|
||||||
presentation?.show()
|
presentation?.show()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.chad.library.adapter4.viewholder.QuickViewHolder
|
|||||||
import com.sw.dualscreen.R
|
import com.sw.dualscreen.R
|
||||||
import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding
|
import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding
|
||||||
import com.sw.dualscreen.ext.dp
|
import com.sw.dualscreen.ext.dp
|
||||||
|
import com.sw.dualscreen.ext.load
|
||||||
import com.sw.dualscreen.objbox.FoodCollectionBean
|
import com.sw.dualscreen.objbox.FoodCollectionBean
|
||||||
import com.sw.dualscreen.utils.GlideUtils
|
import com.sw.dualscreen.utils.GlideUtils
|
||||||
|
|
||||||
@@ -38,14 +39,15 @@ class FoodCollectionAdapter (var list: MutableList<FoodCollectionBean>) :
|
|||||||
scaleType = ImageView.ScaleType.CENTER_CROP
|
scaleType = ImageView.ScaleType.CENTER_CROP
|
||||||
//setImageURI(it.imageUri)
|
//setImageURI(it.imageUri)
|
||||||
//setImageBitmap(it.bitmap)
|
//setImageBitmap(it.bitmap)
|
||||||
it.bitmap?.let { bitmap ->
|
load(it.imageFile)
|
||||||
GlideUtils.loadRoundCornerWitBitmap(
|
// it.bitmap?.let { bitmap ->
|
||||||
context,
|
// GlideUtils.loadRoundCornerWitBitmap(
|
||||||
url = bitmap,
|
// context,
|
||||||
imageView = this,
|
// url = bitmap,
|
||||||
radius = 8.dp
|
// imageView = this,
|
||||||
)
|
// radius = 8.dp
|
||||||
}
|
// )
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ val Float.sp: Float
|
|||||||
Resources.getSystem().displayMetrics
|
Resources.getSystem().displayMetrics
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Double.format2String(): String = "%.1f".format(this)
|
fun Double?.format2String(): String = this.format2String(1)
|
||||||
fun Double.format2String(num:Int): String = "%.${num}f".format(this)
|
fun Double?.format2String(num:Int): String = "%.${num}f".format(this?:0.0)
|
||||||
|
|
||||||
// 添加扩展函数
|
// 添加扩展函数
|
||||||
fun ImageProxy.toSafeBitmap(): Bitmap {
|
fun ImageProxy.toSafeBitmap(): Bitmap {
|
||||||
|
|||||||
@@ -1,5 +1,55 @@
|
|||||||
package com.sw.dualscreen.model.response
|
package com.sw.dualscreen.model.response
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
data class FoodSearchReq(
|
data class FoodSearchReq(
|
||||||
var nameList: List<String>
|
var nameList: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class FoodOrder(
|
||||||
|
//设备id
|
||||||
|
var deviceId: String,
|
||||||
|
//菜品id
|
||||||
|
var foodId: String,
|
||||||
|
//菜品名称
|
||||||
|
var foodName: String,
|
||||||
|
//菜品营养表id
|
||||||
|
var foodMaterialId: String,
|
||||||
|
//餐品规格ID
|
||||||
|
var specId: String,
|
||||||
|
//用户id(档口机,内部员工直接取餐:获取的用户ID/memberId)
|
||||||
|
var userId: String? = null,
|
||||||
|
//食物重量
|
||||||
|
var foodWeight: Int,
|
||||||
|
//食用重量
|
||||||
|
var eatWeight: Int,
|
||||||
|
//份数
|
||||||
|
var eatNum: Int,
|
||||||
|
//是否需要付款
|
||||||
|
var notPay: Boolean,
|
||||||
|
//备注
|
||||||
|
var remark: String? = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data class MemberInfo(
|
||||||
|
//会员id
|
||||||
|
val id: String?,
|
||||||
|
//手机号
|
||||||
|
val phone: String?,
|
||||||
|
//姓名
|
||||||
|
val name: String?,
|
||||||
|
//充值余额
|
||||||
|
val topUpBalance: Double?,
|
||||||
|
//赠送余额
|
||||||
|
val rewardBalance: Double?,
|
||||||
|
//积分余额
|
||||||
|
val integralBalance: Int?
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
data class TextBean(
|
||||||
|
var text: String,
|
||||||
|
var textSize: Int,
|
||||||
|
var textColor: String? = null
|
||||||
|
)
|
||||||
@@ -24,13 +24,21 @@ data class FoodInfo(
|
|||||||
//碳水化合物
|
//碳水化合物
|
||||||
val carbohydrate:String? = null,
|
val carbohydrate:String? = null,
|
||||||
//规格售卖价格(元)
|
//规格售卖价格(元)
|
||||||
val specPrice:String? = null,
|
val specPrice: Double? = null,
|
||||||
//VIP售卖价(元)
|
//VIP售卖价(元)
|
||||||
val vipPrice:String? = null,
|
val vipPrice:Double? = null,
|
||||||
|
//餐品营养id
|
||||||
|
val foodMaterialId:String? = null,
|
||||||
|
//菜品规格id
|
||||||
|
val specId:String? = null,
|
||||||
|
//规格重量(g)
|
||||||
|
val specWeight:Double? = null,
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
var score: Int = 0,
|
var score: Int = 0,
|
||||||
var isChecked: Boolean = false,
|
var isChecked: Boolean = false,
|
||||||
var photoUri: Uri? = null,
|
var photoUri: Uri? = null,
|
||||||
var imgUrl: String? = "",
|
var foodImg: String? = "",
|
||||||
|
|
||||||
// @SerializedName("foodTypeAndRealIntakeVoList")
|
// @SerializedName("foodTypeAndRealIntakeVoList")
|
||||||
// val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo>? = listOf(),
|
// val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo>? = listOf(),
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ 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.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.MemberInfo
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
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
|
||||||
@@ -71,7 +73,7 @@ interface ApiService {
|
|||||||
@POST
|
@POST
|
||||||
suspend fun getCollectedFoodList(
|
suspend fun getCollectedFoodList(
|
||||||
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/dishPage",
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/dishPage",
|
||||||
@Body param: Map<String, Int>
|
@Body param: Map<String, String>
|
||||||
): ApiResponse<List<CollectedFoodInfo>>
|
): ApiResponse<List<CollectedFoodInfo>>
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ interface ApiService {
|
|||||||
@GET
|
@GET
|
||||||
suspend fun getDinnerType(
|
suspend fun getDinnerType(
|
||||||
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getCanteenDinnerType",
|
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getCanteenDinnerType",
|
||||||
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/getRegionRule",
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getRegionRule",
|
||||||
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
|
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
|
||||||
// @Query("canteenId") restId: String,
|
// @Query("canteenId") restId: String,
|
||||||
): ApiResponse<DinnerType>
|
): ApiResponse<DinnerType>
|
||||||
@@ -134,6 +136,34 @@ interface ApiService {
|
|||||||
@Body req: FoodSearchReq
|
@Body req: FoodSearchReq
|
||||||
): ApiResponse<List<FoodInfo>>
|
): ApiResponse<List<FoodInfo>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开餐-生成订单
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
suspend fun createOrder(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/userEatFood/doubleScale",
|
||||||
|
@Body order: FoodOrder
|
||||||
|
): ApiResponse<Any?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP根据id获取会员或员工信息及余额
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getMemberInfo(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getUserInfoBalanceById",
|
||||||
|
@Query("id") memberId: String,
|
||||||
|
): ApiResponse<MemberInfo?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定用户与订单号
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun bindOrder(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/bingOrder",
|
||||||
|
@Query("userId") userId: String,
|
||||||
|
@Query("orderId") orderId: String
|
||||||
|
): ApiResponse<Any?>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交采集图片数据
|
* 提交采集图片数据
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import android.view.ViewOutlineProvider
|
|||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
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
|
||||||
@@ -26,6 +27,7 @@ import com.sw.dualscreen.databinding.PresentationMainScreenBinding
|
|||||||
import com.sw.dualscreen.ext.dp
|
import com.sw.dualscreen.ext.dp
|
||||||
import com.sw.dualscreen.ext.format2String
|
import com.sw.dualscreen.ext.format2String
|
||||||
import com.sw.dualscreen.ext.gone
|
import com.sw.dualscreen.ext.gone
|
||||||
|
import com.sw.dualscreen.ext.load
|
||||||
import com.sw.dualscreen.ext.maskName
|
import com.sw.dualscreen.ext.maskName
|
||||||
import com.sw.dualscreen.ext.visible
|
import com.sw.dualscreen.ext.visible
|
||||||
import com.sw.dualscreen.model.request.UserNutritionParam
|
import com.sw.dualscreen.model.request.UserNutritionParam
|
||||||
@@ -33,8 +35,6 @@ 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.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.GlideUtils
|
|
||||||
import com.sw.dualscreen.utils.GsonUtils
|
|
||||||
import com.sw.dualscreen.utils.SPUtil
|
import com.sw.dualscreen.utils.SPUtil
|
||||||
import com.sw.dualscreen.viewmodel.UserViewModel
|
import com.sw.dualscreen.viewmodel.UserViewModel
|
||||||
import com.sw.plate.utils.LightManager
|
import com.sw.plate.utils.LightManager
|
||||||
@@ -55,6 +55,7 @@ import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel
|
|||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class MainScreenPresentation(
|
class MainScreenPresentation(
|
||||||
@@ -71,6 +72,7 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
private lateinit var binding: PresentationMainScreenBinding
|
private lateinit var binding: PresentationMainScreenBinding
|
||||||
private lateinit var stepChangeCallback: (Int) -> Unit
|
private lateinit var stepChangeCallback: (Int) -> Unit
|
||||||
|
|
||||||
// 当前步骤
|
// 当前步骤
|
||||||
var currentStep: Int = 0
|
var currentStep: Int = 0
|
||||||
|
|
||||||
@@ -110,11 +112,19 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
fun updateWeight(weight: Double) {
|
fun updateWeight(weight: Double) {
|
||||||
lastWeight = weight * 1000 // 将千克转成克
|
lastWeight = weight * 1000 // 将千克转成克
|
||||||
Timber.tag(TAG).d("updateWeight lastWeight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1")
|
Timber.tag(TAG)
|
||||||
if ((currentStep == 2) &&
|
.d("updateWeight lastWeight = $weight, currentStep = $currentStep, isGoStep1 = $isGoStep1")
|
||||||
lastWeight <= 5 &&
|
// if (lastWeight <= 5) {
|
||||||
isGoStep1
|
// activity.isAnalyzing = false
|
||||||
) {//人脸识别过程中,秤上物品拿走
|
// }
|
||||||
|
if (currentStep == 2 && lastWeight <= 5 && isGoStep1) {
|
||||||
|
//人脸识别过程中,秤上物品拿走
|
||||||
|
isGoStep1 = false
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Timber.tag(TAG).e("切回step1")
|
||||||
|
step1FoodRecognizing()
|
||||||
|
}
|
||||||
|
} else if (lastWeight <= 5) {
|
||||||
isGoStep1 = false
|
isGoStep1 = false
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
Timber.tag(TAG).e("切回step1")
|
Timber.tag(TAG).e("切回step1")
|
||||||
@@ -140,6 +150,7 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
calculateNutrition(recognitionWeight - lastWeight)
|
calculateNutrition(recognitionWeight - lastWeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStepChangeCallback(callback: (Int) -> Unit) {
|
fun setStepChangeCallback(callback: (Int) -> Unit) {
|
||||||
stepChangeCallback = callback
|
stepChangeCallback = callback
|
||||||
}
|
}
|
||||||
@@ -200,10 +211,10 @@ class MainScreenPresentation(
|
|||||||
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 {
|
||||||
@@ -227,20 +238,22 @@ class MainScreenPresentation(
|
|||||||
ToastUtils.showToast("选中物品为空")
|
ToastUtils.showToast("选中物品为空")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateFoodInfo(currentFood!!)
|
// updateFoodInfo(currentFood!!)
|
||||||
|
|
||||||
foodRecSuccess(currentFood!!)
|
//foodRecSuccess(currentFood!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
// //binding.ivRecImage.let {
|
binding.ivRecImage.let {
|
||||||
// it.outlineProvider = object : ViewOutlineProvider() {
|
it.outlineProvider = object : ViewOutlineProvider() {
|
||||||
// override fun getOutline(view: View, outline: Outline) {
|
override fun getOutline(view: View, outline: Outline) {
|
||||||
// outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
|
outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// it.clipToOutline = true
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
it.clipToOutline = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDisplayRemoved() {
|
override fun onDisplayRemoved() {
|
||||||
super.onDisplayRemoved()
|
super.onDisplayRemoved()
|
||||||
onDismissListener()
|
onDismissListener()
|
||||||
@@ -274,11 +287,46 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
//updateFoodInfo(foodInfo)
|
//updateFoodInfo(foodInfo)
|
||||||
|
|
||||||
userNutritionData?.let {
|
// userNutritionData?.let {
|
||||||
Timber.tag(TAG).d("loadBilledMode:${GsonUtils.toJson(it)}")
|
// Timber.tag(TAG).d("loadBilledMode:${GsonUtils.toJson(it)}")
|
||||||
|
// }
|
||||||
|
currentFood?.let {
|
||||||
|
val specPrice = it.specPrice?:0.0
|
||||||
|
val vipPrice = it.vipPrice?:0.0
|
||||||
|
binding.tvNormalPrice.text = "${specPrice.format2String(2)} 元/份"
|
||||||
|
binding.tvVipPrice.text = "${vipPrice.format2String(2)} 元/份"
|
||||||
|
|
||||||
|
var calorie = getIntNutritionValue(it.calorie)
|
||||||
|
calorie = max(calorie, 0)
|
||||||
|
val fat = getIntNutritionValue(it.fat)
|
||||||
|
val protein = getIntNutritionValue(it.protein)
|
||||||
|
val carbohydrate = getIntNutritionValue(it.carbohydrate)
|
||||||
|
|
||||||
|
val fatRate = getNutritionRate(fat, calorie)
|
||||||
|
val proteinRate = getNutritionRate(protein, calorie)
|
||||||
|
val carbohydrateRate = getNutritionRate(carbohydrate, calorie)
|
||||||
|
binding.calorieInclude.run {
|
||||||
|
tvCalorie.text = "$calorie"
|
||||||
|
tvFatRate.text = "$fatRate%"
|
||||||
|
tvProteinRate.text = "$proteinRate%"
|
||||||
|
tvCarbohydrateRate.text = "$carbohydrateRate%"
|
||||||
|
|
||||||
|
viewFatLine.updateLayoutParams { height = (fatRate/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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getNutritionRate(value: Int, total: Int): Int{
|
||||||
|
if (value == 0 || total == 0) return 0
|
||||||
|
return (100.0 * value / total).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIntNutritionValue(text: String?): Int {
|
||||||
|
return if (text.isNullOrBlank()) 0 else text.toFloat().roundToInt() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 餐品识别成功,不计费模式
|
* 餐品识别成功,不计费模式
|
||||||
*/
|
*/
|
||||||
@@ -296,7 +344,8 @@ class MainScreenPresentation(
|
|||||||
//updateFoodInfo(foodInfo)
|
//updateFoodInfo(foodInfo)
|
||||||
userNutritionData?.let {
|
userNutritionData?.let {
|
||||||
binding.nutritionInclude.tvUserName.text = it.userName.maskName()
|
binding.nutritionInclude.tvUserName.text = it.userName.maskName()
|
||||||
binding.nutritionInclude.tvRecommendHeat.text = "推荐热量:${it.recommendMin}-${it.recommendMax}kcal"
|
binding.nutritionInclude.tvRecommendHeat.text =
|
||||||
|
"推荐热量:${it.recommendMin}-${it.recommendMax}kcal"
|
||||||
updateWeight(lastWeight / 1000)
|
updateWeight(lastWeight / 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,7 +356,7 @@ class MainScreenPresentation(
|
|||||||
fun step1FoodRecognizing() {
|
fun step1FoodRecognizing() {
|
||||||
hideStandbyScreen()
|
hideStandbyScreen()
|
||||||
activity.resetTouchTime()
|
activity.resetTouchTime()
|
||||||
|
activity.resumeAnalysis()
|
||||||
Timber.tag(TAG).d("step1")
|
Timber.tag(TAG).d("step1")
|
||||||
//if (abs(lastWeight.toInt()) <= 5) {
|
//if (abs(lastWeight.toInt()) <= 5) {
|
||||||
// activity.runOnUiThread {
|
// activity.runOnUiThread {
|
||||||
@@ -332,8 +381,8 @@ class MainScreenPresentation(
|
|||||||
binding.tvFoodName.text = "餐品识别中..."
|
binding.tvFoodName.text = "餐品识别中..."
|
||||||
binding.tvFoodRecPrompt.visible()
|
binding.tvFoodRecPrompt.visible()
|
||||||
binding.flCameraView.visible()
|
binding.flCameraView.visible()
|
||||||
|
binding.ivRecImage.gone()
|
||||||
binding.ivPreviewImage.visible()
|
binding.ivPreviewImage.visible()
|
||||||
//binding.ivRecImage.gone()
|
|
||||||
binding.ivFaceRecMask.gone()
|
binding.ivFaceRecMask.gone()
|
||||||
binding.tvFaceTip.gone()
|
binding.tvFaceTip.gone()
|
||||||
binding.llPriceInfo.gone()
|
binding.llPriceInfo.gone()
|
||||||
@@ -344,17 +393,21 @@ class MainScreenPresentation(
|
|||||||
activity.clearFoodList()
|
activity.clearFoodList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foodRecSuccess(foodInfo: FoodInfo) {
|
// fun foodRecSuccess(foodInfo: FoodInfo) {
|
||||||
//识别逻辑完成根据是否计费显示不同页面
|
// //识别逻辑完成根据是否计费显示不同页面
|
||||||
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
// val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
if (mode == 0) {
|
// if (mode == 0) {
|
||||||
//计费
|
// //计费
|
||||||
loadBilledMode()
|
// loadBilledMode()
|
||||||
} else {
|
// } else {
|
||||||
//不计费
|
// //不计费
|
||||||
loadUnbilledMode()
|
// //userViewModel.getUserNutritionData(
|
||||||
}
|
// // userId = userId,
|
||||||
}
|
// // foodId = currentFood!!.foodId!!
|
||||||
|
// //)
|
||||||
|
// loadUnbilledMode()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户人脸识别中
|
* 用户人脸识别中
|
||||||
@@ -377,7 +430,7 @@ class MainScreenPresentation(
|
|||||||
binding.tvFoodRecPrompt.visible()
|
binding.tvFoodRecPrompt.visible()
|
||||||
binding.llPriceInfo.gone()
|
binding.llPriceInfo.gone()
|
||||||
|
|
||||||
//binding.ivRecImage.gone()
|
binding.ivRecImage.gone()
|
||||||
binding.ivPreviewImage.gone()
|
binding.ivPreviewImage.gone()
|
||||||
|
|
||||||
dinnerTypeInfo = null
|
dinnerTypeInfo = null
|
||||||
@@ -386,7 +439,9 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
stepChangeCallback(currentStep)
|
stepChangeCallback(currentStep)
|
||||||
currentFood = foodInfo
|
currentFood = foodInfo
|
||||||
|
|
||||||
userViewModel.getDinnerType()
|
userViewModel.getDinnerType()
|
||||||
|
|
||||||
resumeCamera()
|
resumeCamera()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,18 +450,37 @@ class MainScreenPresentation(
|
|||||||
fun updateFood(foodInfo: FoodInfo?) {
|
fun updateFood(foodInfo: FoodInfo?) {
|
||||||
Timber.tag(TAG).d("updateFood")
|
Timber.tag(TAG).d("updateFood")
|
||||||
currentFood = foodInfo
|
currentFood = foodInfo
|
||||||
if (foodInfo != null) {
|
if (foodInfo == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.tvFoodName.text = foodInfo.foodName
|
||||||
|
binding.ivPreviewImage.gone()
|
||||||
|
binding.ivRecImage.let {
|
||||||
|
it.visible()
|
||||||
|
val imageUrl = if (foodInfo.foodImg.isNullOrBlank()) foodInfo.photoUri else foodInfo.foodImg
|
||||||
|
it.load(imageUrl)
|
||||||
|
}
|
||||||
|
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||||
|
if (mode == 0) {
|
||||||
|
//计费,查询营养信息、价格信息------------------------
|
||||||
|
loadBilledMode()
|
||||||
|
} else {
|
||||||
|
//不计费
|
||||||
|
//开启人脸识别
|
||||||
if (currentStep == 1) {
|
if (currentStep == 1) {
|
||||||
step2FaceRecognizing(foodInfo)
|
step2FaceRecognizing(foodInfo)
|
||||||
} else {
|
|
||||||
updateFoodInfo(foodInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//if (currentStep == 1) {
|
||||||
|
// step2FaceRecognizing(foodInfo)
|
||||||
|
//} else {
|
||||||
|
// updateFoodInfo(foodInfo)
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateFoodInfo(foodInfo: FoodInfo) {
|
private fun updateFoodInfo(foodInfo: FoodInfo) {
|
||||||
binding.tvFoodName.text = foodInfo.foodName
|
// binding.tvFoodName.text = foodInfo.foodName
|
||||||
binding.ivPreviewImage.gone()
|
// binding.ivPreviewImage.gone()
|
||||||
//binding.ivRecImage.visible()
|
//binding.ivRecImage.visible()
|
||||||
// if (foodInfo.photoUri != null) {
|
// if (foodInfo.photoUri != null) {
|
||||||
// GlideUtils.loadRoundCornerImage(
|
// GlideUtils.loadRoundCornerImage(
|
||||||
@@ -429,9 +503,11 @@ class MainScreenPresentation(
|
|||||||
var weight = weight1
|
var weight = weight1
|
||||||
if (weight < 0) weight = 0.0
|
if (weight < 0) weight = 0.0
|
||||||
debouncer.debounce {
|
debouncer.debounce {
|
||||||
Timber.tag(TAG).d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
Timber.tag(TAG)
|
||||||
|
.d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
|
||||||
val dinnerType = dinnerTypeInfo!!.dinnerType!!
|
val dinnerType = dinnerTypeInfo!!.dinnerType!!
|
||||||
Timber.tag(TAG).d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
|
Timber.tag(TAG)
|
||||||
|
.d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
|
||||||
val calcResultInfo = UserNutritionUtils.calculateNutrition(
|
val calcResultInfo = UserNutritionUtils.calculateNutrition(
|
||||||
currentFood!!,
|
currentFood!!,
|
||||||
userNutritionData!!,
|
userNutritionData!!,
|
||||||
@@ -528,6 +604,7 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateImage(bitmap: Bitmap) {
|
fun updateImage(bitmap: Bitmap) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
binding.ivPreviewImage.setImageBitmap(bitmap)
|
binding.ivPreviewImage.setImageBitmap(bitmap)
|
||||||
@@ -542,6 +619,7 @@ class MainScreenPresentation(
|
|||||||
mealPickupMode = mode
|
mealPickupMode = mode
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
if (rgbCameraHelper != null) {
|
if (rgbCameraHelper != null) {
|
||||||
rgbCameraHelper!!.release()
|
rgbCameraHelper!!.release()
|
||||||
@@ -605,7 +683,8 @@ class MainScreenPresentation(
|
|||||||
|
|
||||||
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")
|
||||||
@@ -614,7 +693,8 @@ class MainScreenPresentation(
|
|||||||
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
|
||||||
@@ -622,18 +702,25 @@ class MainScreenPresentation(
|
|||||||
val userId = faceEntity.userName
|
val userId = faceEntity.userName
|
||||||
if (userId == null) return@Observer
|
if (userId == null) return@Observer
|
||||||
if (currentFood == null) {
|
if (currentFood == null) {
|
||||||
//重新识别
|
currentFood = activity.checkedItem
|
||||||
|
}
|
||||||
|
if (currentFood == null) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
ToastUtils.showToast("currentFood == null")
|
ToastUtils.showToast("请选择菜品")
|
||||||
|
return@runOnUiThread
|
||||||
}
|
}
|
||||||
//activity.recognizeFood()
|
|
||||||
//step1FoodRecognizing()
|
|
||||||
return@Observer
|
|
||||||
}
|
}
|
||||||
userViewModel.getUserNutritionData(
|
// TODO: ------------------人脸识别成功
|
||||||
userId = userId,
|
//-------------------------------------------------
|
||||||
foodId = currentFood!!.foodId!!
|
// TODO: ------------------人脸识别成功
|
||||||
)
|
|
||||||
|
step3ShowRecognizeResult()
|
||||||
|
//根据接口数据更新热量数据--------------------------
|
||||||
|
loadUnbilledMode()
|
||||||
|
// userViewModel.getUserNutritionData(
|
||||||
|
// userId = userId,
|
||||||
|
// foodId = currentFood!!.foodId!!
|
||||||
|
// )
|
||||||
})
|
})
|
||||||
|
|
||||||
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
recognizeViewModel.drawRectInfoText.observe(activity, Observer { info ->
|
||||||
@@ -724,7 +811,8 @@ class MainScreenPresentation(
|
|||||||
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(
|
||||||
@@ -733,8 +821,10 @@ class MainScreenPresentation(
|
|||||||
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(
|
||||||
@@ -790,16 +880,19 @@ class MainScreenPresentation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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=$measuredWidth,measuredHeight=$measuredHeight")
|
Timber.tag(TAG)
|
||||||
|
.i("initRgbCamera measuredWidth=$measuredWidth,measuredHeight=$measuredHeight")
|
||||||
|
|
||||||
val previewConfig: PreviewConfig = recognizeViewModel.previewConfig
|
val previewConfig: PreviewConfig = recognizeViewModel.previewConfig
|
||||||
rgbCameraHelper = DualCameraHelper.Builder()
|
rgbCameraHelper = DualCameraHelper.Builder()
|
||||||
@@ -831,7 +924,8 @@ class MainScreenPresentation(
|
|||||||
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,
|
||||||
@@ -872,7 +966,8 @@ class MainScreenPresentation(
|
|||||||
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,14 +1011,17 @@ class MainScreenPresentation(
|
|||||||
// 识别成功
|
// 识别成功
|
||||||
binding.dualCameraFaceRectView.drawRealtimeFaceInfo(rgbDrawInfoList)
|
binding.dualCameraFaceRectView.drawRealtimeFaceInfo(rgbDrawInfoList)
|
||||||
}
|
}
|
||||||
|
val listIsEmpty = facePreviewInfoList.isEmpty()
|
||||||
if (facePreviewInfoList.isEmpty() || (lastFaceTrackId != facePreviewInfoList[0]!!.trackId)) {
|
val listFirstTrackId = if (listIsEmpty.not()) facePreviewInfoList[0]!!.trackId else null
|
||||||
|
Timber.tag(TAG).d("listIsEmpty=$listIsEmpty,lastFaceTrackId=$lastFaceTrackId,listFirstTrackId=$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
|
||||||
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
Timber.tag(TAG).i("$lastFaceTrackId 用户离开")
|
||||||
lastFaceTrackId = -1
|
lastFaceTrackId = -1
|
||||||
postUserData()
|
postUserData()
|
||||||
if (mealPickupMode == 0) {
|
if (mealPickupMode == 0) {
|
||||||
|
activity.isAnalyzing = false
|
||||||
step1FoodRecognizing()
|
step1FoodRecognizing()
|
||||||
} else {
|
} else {
|
||||||
step2FaceRecognizing(currentFood!!)
|
step2FaceRecognizing(currentFood!!)
|
||||||
@@ -935,7 +1033,8 @@ class MainScreenPresentation(
|
|||||||
fun postUserData() {
|
fun postUserData() {
|
||||||
Timber.tag(TAG).d("postUserData")
|
Timber.tag(TAG).d("postUserData")
|
||||||
if (userNutritionData == null || currentFood == null) {
|
if (userNutritionData == null || currentFood == null) {
|
||||||
Timber.tag(TAG).d("postUserData userNutritionData = ${userNutritionData == null}, currentFood = ${currentFood == null}")
|
Timber.tag(TAG)
|
||||||
|
.d("postUserData userNutritionData = ${userNutritionData == null}, currentFood = ${currentFood == null}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var eatWeight = 0.0
|
var eatWeight = 0.0
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ 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.load
|
import com.sw.dualscreen.ext.load
|
||||||
|
import com.sw.dualscreen.utils.GsonUtils
|
||||||
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
|
||||||
@@ -267,14 +268,31 @@ class FacePayPresentation(
|
|||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
//ToastUtils.showToast("用户人脸识别成功,挑战支付页面")
|
//ToastUtils.showToast("用户人脸识别成功,挑战支付页面")
|
||||||
showWaitingDialog("刷脸支付中,请稍后……")
|
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({
|
binding.root.postDelayed({
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
activity.paySuccess()
|
activity.showPayInfo(memberInfo)
|
||||||
binding.root.postDelayed({
|
binding.root.postDelayed({
|
||||||
dismiss()
|
dismiss()
|
||||||
},500)
|
},500)
|
||||||
},1500)
|
},1500)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// userViewModel.getUserNutritionData(
|
// userViewModel.getUserNutritionData(
|
||||||
// userId = userId,
|
// userId = userId,
|
||||||
// foodId = currentFood!!.id!!
|
// foodId = currentFood!!.id!!
|
||||||
@@ -577,6 +595,8 @@ class FacePayPresentation(
|
|||||||
// } else {
|
// } else {
|
||||||
// step2FaceRecognizing(currentFood!!)
|
// step2FaceRecognizing(currentFood!!)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
resumeCamera()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+108
-44
@@ -2,19 +2,18 @@ package com.sw.dualscreen.presentation.pay
|
|||||||
|
|
||||||
import android.app.Presentation
|
import android.app.Presentation
|
||||||
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 android.view.Display
|
import android.view.Display
|
||||||
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.databinding.PresentationScanQrcodePayBinding
|
import com.sw.dualscreen.databinding.PresentationScanQrcodePayBinding
|
||||||
|
import com.sw.dualscreen.ext.format2String
|
||||||
import com.sw.dualscreen.ext.gone
|
import com.sw.dualscreen.ext.gone
|
||||||
|
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.MemberInfo
|
||||||
|
import com.sw.dualscreen.model.response.TextBean
|
||||||
|
import com.sw.dualscreen.utils.SpannedUtils
|
||||||
|
|
||||||
class ScanQrCodePayPresentation(
|
class ScanQrCodePayPresentation(
|
||||||
val activity: PayActivity,
|
val activity: PayActivity,
|
||||||
@@ -38,8 +37,19 @@ class ScanQrCodePayPresentation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var foodName: String? = null
|
var foodName: String? = null
|
||||||
var payAmount: String? = null
|
|
||||||
var payQrCodePic: Any? = null
|
var payQrCodePic: Any? = null
|
||||||
|
|
||||||
|
//总价格
|
||||||
|
var totalPrice = 0.0
|
||||||
|
|
||||||
|
//余额
|
||||||
|
private var balance = 0.0
|
||||||
|
|
||||||
|
//实际支付金额
|
||||||
|
private var realPayPrice = 0.0
|
||||||
|
//扣除余额
|
||||||
|
private var expensesBalance = 0.0
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
when (type) {
|
when (type) {
|
||||||
0 -> {
|
0 -> {
|
||||||
@@ -49,63 +59,117 @@ class ScanQrCodePayPresentation(
|
|||||||
|
|
||||||
binding.tvPayTip.text = "请扫码支付或出示付款码"
|
binding.tvPayTip.text = "请扫码支付或出示付款码"
|
||||||
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 = totalPrice.format2String(2), textSize = 48),
|
||||||
|
)
|
||||||
|
)
|
||||||
binding.ivPayQrCode.load(payQrCodePic)
|
binding.ivPayQrCode.load(payQrCodePic)
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
binding.layoutVip.visible()
|
binding.layoutVip.visible()
|
||||||
binding.layoutPaySuccess.gone()
|
binding.layoutPaySuccess.gone()
|
||||||
binding.layoutScanQrCode.visible()
|
binding.layoutScanQrCode.visible()
|
||||||
|
|
||||||
|
val memberInfo = activity.memberInfo
|
||||||
|
totalPrice = activity.foodInfo?.vipPrice ?: 0.0
|
||||||
|
balance = (memberInfo?.topUpBalance ?: 0.0) + (memberInfo?.rewardBalance ?: 0.0)
|
||||||
|
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
|
||||||
|
expensesBalance = if (balance >= totalPrice) totalPrice else balance
|
||||||
|
|
||||||
|
memberInfo?.let { loadUserInfo(it) }
|
||||||
|
binding.tvUserBalance.text = SpannedUtils.getAmountText(
|
||||||
|
listOf(
|
||||||
|
TextBean(text = "¥", textSize = 20),
|
||||||
|
TextBean(text = balance.format2String(2), textSize = 32),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
binding.tvFoodName.text = foodName
|
binding.tvFoodName.text = foodName
|
||||||
binding.tvRealAmount.text = getAmountText(payAmount ?: "")
|
binding.tvRealAmount.text = SpannedUtils.getAmountText(
|
||||||
binding.ivPayQrCode.load(payQrCodePic)
|
listOf(
|
||||||
|
TextBean(text = "¥", textSize = 32),
|
||||||
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
TextBean(text = totalPrice.format2String(2), textSize = 48),
|
||||||
binding.tvUserName.text = "张三"
|
)
|
||||||
binding.tvUserPhone.text = "132****5678"
|
)
|
||||||
binding.tvUserBalance.text = getBalanceText("0.00")
|
binding.ivPayQrCode.run {
|
||||||
|
// load(payQrCodePic)
|
||||||
binding.tvPayTip.text = getPayTip("-16.80", "22.00")
|
if (balance >= totalPrice) invisible() else visible()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.tvPayTip.text = SpannedUtils.getAmountText(getAmountList())
|
||||||
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
binding.layoutVip.visible()
|
binding.layoutVip.visible()
|
||||||
binding.layoutPaySuccess.visible()
|
binding.layoutPaySuccess.visible()
|
||||||
binding.layoutScanQrCode.gone()
|
binding.layoutScanQrCode.gone()
|
||||||
|
|
||||||
|
val memberInfo = activity.memberInfo
|
||||||
|
totalPrice = activity.foodInfo?.vipPrice ?: 0.0
|
||||||
|
balance = (memberInfo?.topUpBalance ?: 0.0) + (memberInfo?.rewardBalance ?: 0.0)
|
||||||
|
realPayPrice = if (balance >= totalPrice) 0.0 else totalPrice - balance
|
||||||
|
expensesBalance = if (balance >= totalPrice) totalPrice else balance
|
||||||
|
|
||||||
|
memberInfo?.let { loadUserInfo(it) }
|
||||||
|
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.tvPayInfo.text =
|
||||||
|
"余额扣除 ${expensesBalance.format2String(2)} 元,在线支付 ${totalPrice.format2String(2)} 元"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadUserInfo(item: MemberInfo) {
|
||||||
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
binding.ivHeadPic.load(R.mipmap.ic_launcher)
|
||||||
binding.tvUserName.text = "张三"
|
binding.tvUserName.text = item.name
|
||||||
binding.tvUserPhone.text = "132****5678"
|
|
||||||
binding.tvUserBalance.text = getBalanceText("0.00")
|
|
||||||
|
|
||||||
binding.tvPayInfo.text = "余额扣除 16.80 元,在线支付 20.00 元"
|
val phone = item.phone ?: ""
|
||||||
|
binding.tvUserPhone.text =
|
||||||
}
|
if (phone.length == 11)
|
||||||
}
|
phone.replace(phone.substring(3, 7), "****")
|
||||||
|
else
|
||||||
|
phone
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPayTip(startAmount:String, endAmount: String): SpannedString {
|
private fun getAmountList(): List<TextBean> {
|
||||||
return buildSpannedString {
|
val list: MutableList<TextBean> = mutableListOf()
|
||||||
append("余额扣除 ", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
append(startAmount, ForegroundColorSpan("#FF0A1428".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
list.add(TextBean(text = "余额扣除 ", textSize = 30, textColor = "#FF5E7585"))
|
||||||
append(" 元,还需支付 ", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
list.add(
|
||||||
append(endAmount, ForegroundColorSpan("#FF0A1428".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
TextBean(
|
||||||
append(" 元", ForegroundColorSpan("#FF5E7585".toColorInt()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
text = "-${expensesBalance.format2String(2)}",
|
||||||
}
|
textSize = 30,
|
||||||
|
textColor = "#FF0A1428"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (balance >= totalPrice) {
|
||||||
|
//余额大于等于总价格,使用余额支付
|
||||||
|
TextBean(text = " 元,扣除后可用余额 ", textSize = 30, textColor = "#FF5E7585")
|
||||||
|
val remainingBalance = balance - totalPrice
|
||||||
|
TextBean(
|
||||||
|
text = remainingBalance.format2String(2),
|
||||||
|
textSize = 30,
|
||||||
|
textColor = "#FF0A1428"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
//余额小于总价格,使用余额+扫码支付
|
||||||
|
//实际支付金额
|
||||||
|
TextBean(text = " 元,还需支付 ", textSize = 30, textColor = "#FF5E7585")
|
||||||
|
TextBean(text = realPayPrice.format2String(2), textSize = 30, textColor = "#FF0A1428")
|
||||||
|
TextBean(text = " 元", textSize = 30, textColor = "#FF5E7585")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBalanceText(amount: String): SpannedString {
|
return list
|
||||||
return buildSpannedString {
|
|
||||||
append("¥", AbsoluteSizeSpan(20, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
append(amount, AbsoluteSizeSpan(32, true), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 onDisplayRemoved() {
|
override fun onDisplayRemoved() {
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.sw.dualscreen.presentation.pay
|
||||||
|
|
||||||
|
import android.view.TextureView
|
||||||
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
|
import java.util.concurrent.ExecutorService
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TransmitScreen {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,23 +1,21 @@
|
|||||||
package com.sw.dualscreen.repository
|
package com.sw.dualscreen.repository
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.net.Uri
|
|
||||||
import com.sw.dualscreen.GlobalData
|
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.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.MemberInfo
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
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
|
||||||
import com.sw.dualscreen.utils.ImageUtil
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.asRequestBody
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,18 +72,21 @@ class RemoteRepository constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取人脸数据
|
* 获取人脸数据
|
||||||
*/
|
*/
|
||||||
suspend fun getCollectedFoodList(
|
suspend fun getCollectedFoodList(
|
||||||
pageNum: Int,
|
pageNum: Int,
|
||||||
pageSize: Int = 50,
|
pageSize: Int = 100,
|
||||||
|
foodName: String,
|
||||||
): ApiResponse<List<CollectedFoodInfo>> {
|
): ApiResponse<List<CollectedFoodInfo>> {
|
||||||
return safeApiCall {
|
return safeApiCall {
|
||||||
apiService.getCollectedFoodList(
|
apiService.getCollectedFoodList(
|
||||||
param = mapOf(
|
param = mapOf(
|
||||||
"pageNum" to pageNum,
|
"pageNum" to "$pageNum",
|
||||||
"pageSize" to pageSize
|
"pageSize" to "$pageSize",
|
||||||
|
"foodName" to foodName,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -141,10 +142,7 @@ class RemoteRepository constructor(
|
|||||||
* @param restId 从device服务获取的canteenId字段
|
* @param restId 从device服务获取的canteenId字段
|
||||||
* @param foodName 菜品名称,多个使用逗号拼接
|
* @param foodName 菜品名称,多个使用逗号拼接
|
||||||
*/
|
*/
|
||||||
suspend fun getFoodInfo(
|
suspend fun getFoodInfo(foodName: String): ApiResponse<List<FoodInfo>> {
|
||||||
restId: String = GlobalData.restId,
|
|
||||||
foodName: String,
|
|
||||||
): ApiResponse<List<FoodInfo>> {
|
|
||||||
return safeApiCall {
|
return safeApiCall {
|
||||||
// val map = mutableMapOf<String, List<String>>()
|
// val map = mutableMapOf<String, List<String>>()
|
||||||
// map["nameList"] = foodName.split(",")
|
// map["nameList"] = foodName.split(",")
|
||||||
@@ -152,10 +150,31 @@ class RemoteRepository constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun createOrder(order: FoodOrder): ApiResponse<Any?> {
|
||||||
|
return safeApiCall {
|
||||||
|
apiService.createOrder(order = order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun bindOrder(userId: String, orderId: String): ApiResponse<Any?> {
|
||||||
|
return safeApiCall {
|
||||||
|
apiService.bindOrder(userId = userId, orderId = orderId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getMemberInfo(memberId: String): ApiResponse<MemberInfo?> {
|
||||||
|
return safeApiCall {
|
||||||
|
apiService.getMemberInfo(memberId = memberId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传采集菜品信息
|
* 上传采集菜品信息
|
||||||
*/
|
*/
|
||||||
suspend fun uploadCollectFoodPics(fileList: List<File>, params: HashMap<String, RequestBody>): ApiResponse<String> {
|
suspend fun uploadCollectFoodPics(
|
||||||
|
fileList: List<File>,
|
||||||
|
params: HashMap<String, RequestBody>
|
||||||
|
): ApiResponse<String> {
|
||||||
// 准备文件参数
|
// 准备文件参数
|
||||||
val fileParts = mutableListOf<MultipartBody.Part>()
|
val fileParts = mutableListOf<MultipartBody.Part>()
|
||||||
fileList.forEachIndexed { index, file ->
|
fileList.forEachIndexed { index, file ->
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
import com.sw.dualscreen.objbox.FoodCollectionBean
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
class ImageUploader(
|
||||||
|
private val totalList: List<FoodCollectionBean>,
|
||||||
|
private val uploadImage: suspend (List<FoodCollectionBean>)-> Boolean,
|
||||||
|
private val onProgress: (Int, List<FoodCollectionBean>) -> Unit,
|
||||||
|
private val onError:(List<FoodCollectionBean>) -> Unit,
|
||||||
|
private val onComplete:() -> Unit
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private const val BATCH_SIZE = 5
|
||||||
|
}
|
||||||
|
private val uploadedCount = AtomicInteger(0)
|
||||||
|
|
||||||
|
suspend fun processUploads() {
|
||||||
|
val batches = totalList.chunked(BATCH_SIZE)
|
||||||
|
|
||||||
|
for (batch in batches) {
|
||||||
|
val success = uploadImage(batch)
|
||||||
|
if (!success) {
|
||||||
|
//println("上传失败,终止流程")
|
||||||
|
onError(batch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val fileCount = batch.count { it.imageFile!=null }
|
||||||
|
uploadedCount.addAndGet(fileCount)
|
||||||
|
onProgress(uploadedCount.get(), batch)
|
||||||
|
//println("已上传 ${uploadedCount.get()}/$totalImages")
|
||||||
|
}
|
||||||
|
|
||||||
|
onComplete()
|
||||||
|
//println("流程完成,总计上传 ${uploadedCount.get()} 张图片")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.sw.dualscreen.utils
|
||||||
|
|
||||||
|
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.model.response.TextBean
|
||||||
|
|
||||||
|
object SpannedUtils {
|
||||||
|
|
||||||
|
public fun getAmountText(list: List<TextBean>): SpannedString {
|
||||||
|
return buildSpannedString {
|
||||||
|
list.forEach {
|
||||||
|
append(
|
||||||
|
it.text,
|
||||||
|
AbsoluteSizeSpan(it.textSize, true),
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
if (it.textColor.isNullOrBlank().not()) {
|
||||||
|
append(
|
||||||
|
it.text,
|
||||||
|
ForegroundColorSpan(it.textColor!!.toColorInt()),
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -128,7 +128,11 @@ class CustomBottomSheetDialog(
|
|||||||
|
|
||||||
private fun searchInfo(){
|
private fun searchInfo(){
|
||||||
debouncer.debounce {
|
debouncer.debounce {
|
||||||
viewModel.searchByFoodName(binding.etSearch.text.toString())
|
viewModel.searchByFoodName(binding.etSearch.text.toString()) {
|
||||||
|
searchFoodList.clear()
|
||||||
|
searchFoodList.addAll(it)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import android.view.Gravity;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sw.dualscreen.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载进度条弹窗
|
* 加载进度条弹窗
|
||||||
@@ -88,4 +91,5 @@ public class CustomDialog extends Dialog {
|
|||||||
// fullScreenImmersive(getWindow().getDecorView());
|
// fullScreenImmersive(getWindow().getDecorView());
|
||||||
// this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
// this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,11 +5,15 @@ import com.arcsoft.face.ErrorInfo
|
|||||||
import com.sw.dualscreen.GlobalData
|
import com.sw.dualscreen.GlobalData
|
||||||
import com.sw.dualscreen.GlobalKey
|
import com.sw.dualscreen.GlobalKey
|
||||||
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.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.FoodOrder
|
||||||
|
import com.sw.dualscreen.model.response.MemberInfo
|
||||||
import com.sw.dualscreen.model.response.UserFaceModel
|
import com.sw.dualscreen.model.response.UserFaceModel
|
||||||
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.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
|
||||||
@@ -115,10 +119,15 @@ class UserViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCollectedFoodList(pageNo: Int = 1, pageSize: Int = 100, block:(List<CollectedFoodInfo>)-> Unit) {
|
fun getCollectedFoodList(
|
||||||
|
pageNo: Int = 1,
|
||||||
|
pageSize: Int = 100,
|
||||||
|
foodName: String,
|
||||||
|
block: (List<CollectedFoodInfo>) -> Unit
|
||||||
|
) {
|
||||||
Timber.tag(TAG).d("getCollectedFoodList index = $pageNo")
|
Timber.tag(TAG).d("getCollectedFoodList index = $pageNo")
|
||||||
launch {
|
launch {
|
||||||
val response = repository.getCollectedFoodList(pageNo)
|
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.result ?: emptyList()
|
||||||
@@ -254,22 +263,73 @@ class UserViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createOrder(order: FoodOrder, block:(String)-> Unit) {
|
||||||
|
Timber.tag(TAG).d("createOrder")
|
||||||
fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
|
|
||||||
Timber.tag(TAG).d("uploadCollectFoodPics")
|
|
||||||
launchWithLoading {
|
launchWithLoading {
|
||||||
|
val response = repository.createOrder(order)
|
||||||
|
if (parseResponse(response)) {
|
||||||
|
block(response.data.toString())
|
||||||
|
} else {
|
||||||
|
block("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bindOrder(userId: String, orderId: String, block:(Boolean)-> Unit){
|
||||||
|
Timber.tag(TAG).d("bindOrder")
|
||||||
|
launchWithLoading {
|
||||||
|
val response = repository.bindOrder(userId = userId, orderId = orderId)
|
||||||
|
if (parseResponse(response)) {
|
||||||
|
block(true)
|
||||||
|
} else {
|
||||||
|
block(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMemberInfo(memberId: String, block:(MemberInfo?)-> Unit) {
|
||||||
|
Timber.tag(TAG).d("getMemberInfo")
|
||||||
|
launchWithLoading {
|
||||||
|
val response = repository.getMemberInfo(memberId)
|
||||||
|
if (parseResponse(response)) {
|
||||||
|
block(response.data)
|
||||||
|
} else {
|
||||||
|
block(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
|
||||||
|
// Timber.tag(TAG).d("uploadCollectFoodPics")
|
||||||
|
// launchWithLoading {
|
||||||
|
// val fileList = files.filterNotNull()
|
||||||
|
// if (fileList.isEmpty()) {
|
||||||
|
// callback(false)
|
||||||
|
// return@launchWithLoading
|
||||||
|
// }
|
||||||
|
// val resp = repository.uploadCollectFoodPics(fileList, params)
|
||||||
|
// if (!parseResponse(resp)) {
|
||||||
|
// callback(false)
|
||||||
|
// return@launchWithLoading
|
||||||
|
// }
|
||||||
|
// callback(resp.code == "00000")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
suspend fun uploadCollectFoodPics(
|
||||||
|
files: List<File?>,
|
||||||
|
params: HashMap<String, RequestBody>
|
||||||
|
): Boolean {
|
||||||
|
Timber.tag(TAG).d("uploadCollectFoodPics")
|
||||||
val fileList = files.filterNotNull()
|
val fileList = files.filterNotNull()
|
||||||
if (fileList.isEmpty()) {
|
if (fileList.isEmpty()) {
|
||||||
callback(false)
|
return true
|
||||||
return@launchWithLoading
|
|
||||||
}
|
}
|
||||||
val resp = repository.uploadCollectFoodPics(fileList, params)
|
val resp = repository.uploadCollectFoodPics(fileList, params)
|
||||||
if (!parseResponse(resp)) {
|
// if (!parseResponse(resp)) {
|
||||||
callback(false)
|
// return false
|
||||||
return@launchWithLoading
|
// }
|
||||||
}
|
return resp.code == "00000"
|
||||||
callback(resp.code == "00000")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:shape="rectangle">
|
<item android:state_enabled="false">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="#80FF3232"/>
|
<solid android:color="#80FF3232"/>
|
||||||
<corners android:radius="6dp"/>
|
<corners android:radius="6dp"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:state_enabled="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="#FFFF3232"/>
|
||||||
|
<corners android:radius="6dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
||||||
@@ -44,33 +44,39 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<!-- <com.scwang.smart.refresh.layout.SmartRefreshLayout-->
|
<FrameLayout
|
||||||
<!-- android:id="@+id/refreshLayout"-->
|
android:layout_width="match_parent"
|
||||||
<!-- android:layout_width="match_parent"-->
|
android:layout_height="match_parent">
|
||||||
<!-- android:layout_height="0dp"-->
|
|
||||||
<!-- android:layout_marginHorizontal="130dp"-->
|
|
||||||
<!-- android:layout_marginTop="40dp"-->
|
|
||||||
<!-- android:layout_marginBottom="58dp"-->
|
|
||||||
<!-- app:layout_constraintBottom_toTopOf="@id/dividerLine"-->
|
|
||||||
<!-- app:layout_constraintTop_toBottomOf="@id/flSearchBlock">-->
|
|
||||||
|
|
||||||
<!-- <com.scwang.smart.refresh.header.ClassicsHeader-->
|
<com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||||
<!-- android:layout_width="match_parent"-->
|
android:id="@+id/refreshLayout"
|
||||||
<!-- android:layout_height="wrap_content" />-->
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="10dp">
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.header.ClassicsHeader
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvFoodList"
|
android:id="@+id/rvFoodList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
android:layout_margin="10dp"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
tools:itemCount="8"
|
tools:itemCount="8"
|
||||||
tools:listitem="@layout/list_item_collected_food" />
|
tools:listitem="@layout/list_item_collected_food" />
|
||||||
|
|
||||||
<!-- <com.scwang.smart.refresh.footer.ClassicsFooter-->
|
<com.scwang.smart.refresh.footer.ClassicsFooter
|
||||||
<!-- android:layout_width="match_parent"-->
|
android:layout_width="match_parent"
|
||||||
<!-- android:layout_height="wrap_content" />-->
|
android:layout_height="wrap_content" />
|
||||||
<!-- </com.scwang.smart.refresh.layout.SmartRefreshLayout>-->
|
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/emptyInclude"
|
||||||
|
layout="@layout/layout_empty_search"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -77,12 +77,13 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<ImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/iv_img"
|
android:id="@+id/iv_img"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:contentDescription="食物图预览"
|
android:contentDescription="食物图预览"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
app:shapeAppearance="@style/round10dpCornerStyle"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvFoodList"
|
android:id="@+id/rvFoodList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="400dp"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
@@ -119,7 +119,8 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/flPreview"
|
app:layout_constraintTop_toBottomOf="@id/flPreview"
|
||||||
app:spanCount="3"
|
app:spanCount="3"
|
||||||
tools:itemCount="5"
|
tools:itemCount="12"
|
||||||
|
android:overScrollMode="never"
|
||||||
tools:listitem="@layout/list_item_food_collection" />
|
tools:listitem="@layout/list_item_food_collection" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -126,15 +126,10 @@
|
|||||||
android:id="@+id/ivPayQrCode"
|
android:id="@+id/ivPayQrCode"
|
||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="300dp"
|
android:layout_height="300dp"
|
||||||
android:layout_marginTop="56dp"
|
android:layout_marginVertical="50dp"
|
||||||
android:src="@drawable/ic_qrcode"
|
android:src="@drawable/ic_qrcode"
|
||||||
android:visibility="visible" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvAccountInfo"
|
android:id="@+id/tvAccountInfo"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -143,20 +138,26 @@
|
|||||||
android:textColor="#ff889ac2"
|
android:textColor="#ff889ac2"
|
||||||
android:textSize="30sp" />
|
android:textSize="30sp" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
<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="120dp"
|
||||||
android:layout_marginHorizontal="32dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:layout_marginTop="50dp"
|
|
||||||
android:layout_marginBottom="32dp"
|
android:layout_marginBottom="32dp"
|
||||||
android:background="@drawable/bg_btn_save2"
|
android:background="@drawable/bg_btn_save2"
|
||||||
android:text="确认支付"
|
android:text="确认支付"
|
||||||
|
android:enabled="true"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="40sp" />
|
android:textSize="40sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutPaySuccess"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:ignore="HardcodedText">
|
tools:ignore="HardcodedText">
|
||||||
|
|
||||||
@@ -18,17 +19,17 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="30dp"
|
||||||
android:layout_marginBottom="39dp"
|
android:layout_marginBottom="39dp"
|
||||||
android:text="暂无该物品"
|
android:text="暂无采集记录"
|
||||||
android:textColor="#ff000000"
|
android:textColor="#ff000000"
|
||||||
android:textSize="30sp"
|
android:textSize="36sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvContent"
|
android:id="@+id/tvContent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="请检查物品名称,或稍后重新搜索"
|
android:text="请确认菜品名称,或稍后重试"
|
||||||
android:textColor="#ff999999"
|
android:textColor="#ff999999"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textSize="26sp" />
|
android:textSize="30sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -12,15 +12,16 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="热量"
|
android:text="热量"
|
||||||
android:layout_marginTop="65dp"
|
android:layout_marginTop="50dp"
|
||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="24sp"
|
android:textSize="24sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/tvCalorie"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginVertical="15dp"
|
android:layout_marginVertical="13dp"
|
||||||
android:textColor="#ff0a1428"
|
android:textColor="#ff0a1428"
|
||||||
android:textSize="40sp"
|
android:textSize="40sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
@@ -32,12 +33,12 @@
|
|||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="kcal/100g" />
|
android:text="kcal/100g" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:layout_marginVertical="28dp"
|
android:layout_marginVertical="22dp"
|
||||||
android:layout_marginHorizontal="28dp"
|
android:layout_marginHorizontal="28dp"
|
||||||
android:background="#FFDBE5FB" />
|
android:background="#FFDBE5FB" />
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/llProtein"
|
app:layout_constraintEnd_toStartOf="@+id/llProtein"
|
||||||
app:layout_constraintHorizontal_chainStyle="spread"
|
app:layout_constraintHorizontal_chainStyle="spread"
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
@@ -59,7 +61,7 @@
|
|||||||
android:id="@+id/tvFatRate"
|
android:id="@+id/tvFatRate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="13%"
|
tools:text="13%"
|
||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
@@ -91,6 +93,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/llCarbohydrate"
|
app:layout_constraintEnd_toStartOf="@+id/llCarbohydrate"
|
||||||
app:layout_constraintStart_toEndOf="@id/llFat">
|
app:layout_constraintStart_toEndOf="@id/llFat">
|
||||||
|
|
||||||
@@ -98,7 +101,7 @@
|
|||||||
android:id="@+id/tvProteinRate"
|
android:id="@+id/tvProteinRate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="47%"
|
tools:text="47%"
|
||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
@@ -130,6 +133,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/llProtein">
|
app:layout_constraintStart_toEndOf="@id/llProtein">
|
||||||
|
|
||||||
@@ -137,7 +141,7 @@
|
|||||||
android:id="@+id/tvCarbohydrateRate"
|
android:id="@+id/tvCarbohydrateRate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="40%"
|
tools:text="40%"
|
||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
@@ -168,11 +172,12 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="(所示营养数据为每百克含量)"
|
android:text="(所示营养数据为每百克含量)"
|
||||||
android:textColor="#ff889ac2"
|
android:textColor="#ff889ac2"
|
||||||
android:layout_marginTop="56dp"
|
android:paddingBottom="20dp"
|
||||||
android:layout_marginBottom="27dp"
|
android:gravity="bottom"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout 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"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@@ -18,14 +17,14 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/setting_border"
|
android:background="@drawable/setting_border"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="28dp">
|
android:paddingBottom="26dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvFoodName"
|
android:id="@+id/tvFoodName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginVertical="60dp"
|
android:layout_marginVertical="50dp"
|
||||||
android:text="餐品识别中..."
|
android:text="餐品识别中..."
|
||||||
android:textColor="#ff0a1428"
|
android:textColor="#ff0a1428"
|
||||||
android:textSize="40sp"
|
android:textSize="40sp"
|
||||||
@@ -76,17 +75,20 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<ImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
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"
|
||||||
|
app:shapeAppearance="@style/round10dpCornerStyle"
|
||||||
tools:background="@mipmap/ic_launcher"/>
|
tools:background="@mipmap/ic_launcher"/>
|
||||||
|
|
||||||
<!-- <ImageView-->
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
<!-- 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"
|
||||||
<!-- tools:background="@mipmap/ic_launcher"/>-->
|
tools:background="@mipmap/ic_launcher_round"
|
||||||
|
app:shapeAppearance="@style/round10dpCornerStyle"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -100,13 +102,13 @@
|
|||||||
android:id="@+id/llPriceInfo"
|
android:id="@+id/llPriceInfo"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="28dp"
|
android:layout_marginTop="26dp"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvOldPrice"
|
android:id="@+id/tvNormalPrice"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="#ff0a1428"
|
android:textColor="#ff0a1428"
|
||||||
|
|||||||
@@ -172,4 +172,8 @@
|
|||||||
<item name="cornerSize">50%</item>
|
<item name="cornerSize">50%</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="round10dpCornerStyle">
|
||||||
|
<item name="cornerFamily">rounded</item>
|
||||||
|
<item name="cornerSize">10dp</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user