接口联调

This commit is contained in:
2025-11-28 18:46:41 +08:00
parent 9bcd7c9983
commit 29188c5944
39 changed files with 1882 additions and 1662 deletions
+2 -1
View File
@@ -22,8 +22,9 @@ class MyApp : App() {
Timber.plant(Timber.DebugTree())
var deviceId = AppUtil.getUDID(this)
Timber.d("UDID = ${AppUtil.getUDID(this)}")
deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
// deviceId = "3ea47dc0-3cf0-3c2f-909c-265a9a65572e"
GlobalData.deviceId = deviceId
GlobalData.appBaseUrl = "http://192.168.1.201:14801"
ObjectBox.init(this)
// 初始化崩溃处理器
CrashHandler.init(this)
@@ -11,7 +11,7 @@
//import com.sw.dualscreen.dialog.WarnDialog
//import com.sw.dualscreen.ext.addOnActionSearchListener
//import com.sw.dualscreen.ext.hideKeyboard
//import com.sw.dualscreen.objbox.CollectedFoodBean
//import com.sw.dualscreen.objbox.CollectedFoodInfo
//import com.sw.dualscreen.objbox.Food
//import com.sw.dualscreen.objbox.ObjectBox
//import com.sw.dualscreen.viewmodel.BaseViewModel
@@ -31,7 +31,7 @@
// return ActivityCollectedDataBinding.inflate(layoutInflater)
// }
//
// private val list: MutableList<CollectedFoodBean> = mutableListOf()
// private val list: MutableList<CollectedFoodInfo> = mutableListOf()
// private val adapter by lazy {
// CollectedFoodAdapter(list).apply {
// isStateViewEnable = true
@@ -88,7 +88,7 @@
// queryList = queryList?.filter { it.name?.contains(searchName) == true }
// }
// queryList?.forEach {
// list.add(CollectedFoodBean(foodName = it.name))
// list.add(CollectedFoodInfo(foodName = it.name))
// }
// adapter.notifyDataSetChanged()
// if (list.isEmpty()) {
@@ -11,7 +11,7 @@ import com.sw.dualscreen.databinding.LayoutEmptySearchBinding
import com.sw.dualscreen.dialog.WarnDialog
import com.sw.dualscreen.ext.addOnActionSearchListener
import com.sw.dualscreen.ext.hideKeyboard
import com.sw.dualscreen.objbox.CollectedFoodBean
import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.objbox.Food
import com.sw.dualscreen.objbox.ObjectBox
import com.sw.dualscreen.viewmodel.BaseViewModel
@@ -30,7 +30,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
return ActivityCollectedFoodBinding.inflate(layoutInflater)
}
private val list: MutableList<CollectedFoodBean> = mutableListOf()
private val list: MutableList<CollectedFoodInfo> = mutableListOf()
private val adapter by lazy {
CollectedFoodNewAdapter(list).apply {
isStateViewEnable = true
@@ -88,7 +88,7 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
val totalList = box?.all
?.filter { it.name!=null }
?.groupBy { it.name!! }
?.map { CollectedFoodBean(foodName = it.key, count = it.value.size) }
?.map { CollectedFoodInfo(foodName = it.key, foodCount = it.value.size) }
//var queryMap:Map<String, List<Food>> ?= null
if (searchName.isNullOrBlank().not()) {
//queryMap = totalMap?.filter { it.key.contains(searchName) }
@@ -106,8 +106,19 @@ class CollectedFoodActivity : BaseActivity<ActivityCollectedFoodBinding>() {
loadEmptyView()
}
binding.root.hideKeyboard()
viewModel.getCollectedFoodList(pageNo = pageNo) {
if (it.isNotEmpty()) {
list.addAll(it)
runOnUiThread {
adapter.notifyDataSetChanged()
}
}
}
}
private var pageNo = 1
private var emptyBinding: LayoutEmptySearchBinding? = null
private fun loadEmptyView() {
if (emptyBinding == null) {
@@ -29,20 +29,23 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
override fun initialize() {
super.initialize()
val isSuccess = viewModel.checkEquipmentInfo()
if (isSuccess) {
binding.root.postDelayed({
goMainActivity()
return
}
binding.imgQr.setImageBitmap(
QRCodeUtil.generateQRCode(
content = GlobalData.deviceId,
size = 200
)
)
binding.initButton.setOnClickListener {
viewModel.getDeviceToken()
}
}, 1000)
// val isSuccess = viewModel.checkEquipmentInfo()
// if (isSuccess) {
// goMainActivity()
// return
// }
// binding.imgQr.setImageBitmap(
// QRCodeUtil.generateQRCode(
// content = GlobalData.deviceId,
// size = 200
// )
// )
// binding.initButton.setOnClickListener {
// viewModel.getDeviceToken()
// }
}
override fun registerDataChange() {
@@ -114,7 +114,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
private fun initData() {
viewModel.getEquipmentToken()
// viewModel.getEquipmentToken()
viewModel.getUserFaceCache(pageNo = 1)
// presentation?.step1()
presentation?.step1FoodRecognizing()
}
@@ -200,10 +201,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.tvFoodName.setOnClickListener {
SensorScaleUtils.zero()
}
binding.tvRescan.setOnClickListener {
debouncer.debounce { recognizeFood() }
}
// binding.tvRescan.setOnClickListener {
// debouncer.debounce { recognizeFood() }
// }
binding.btnPay.setOnClickListener {
if (checkedItem == null) {
ToastUtils.showToast("暂无识别数据,请搜索选择")
return@setOnClickListener
}
presentation?.dismiss()
startActivity(Intent(this, PayActivity::class.java).apply {
putExtra(PayActivity.FOOD_INFO, checkedItem)
@@ -317,9 +322,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (TextUtils.isEmpty(foodName)) {
LightManager.closeGreenLight()
LightManager.closeRedLight()
binding.layoutRescan.visibility = View.VISIBLE
//binding.layoutRescan.visibility = View.VISIBLE
binding.flPay.visible()
binding.tvToSearch.let {
it.text = "未识别到,去手动搜索"
it.visible()
}
} else {
binding.layoutRescan.visibility = View.GONE
//binding.layoutRescan.visibility = View.GONE
viewModel.getFoodInfo(foodName) { list ->
runOnUiThread {
updateFoodInfo(list.toMutableList(), scoreList)
@@ -367,7 +377,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
LightManager.closeRedLight()
binding.flPay.visible()
binding.tvToSearch.visible()
binding.tvToSearch.let {
it.text = "以上都不是,手动搜索"
it.visible()
}
} else {
binding.flPay.gone()
binding.tvToSearch.gone()
@@ -65,9 +65,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
if (binding.btnPayCash.isChecked) {
return@setOnClickListener
}
if (cashPayFragment == null) {
cashPayFragment = CashPayFragment()
}
cashPayFragment = CashPayFragment()
showFragment(cashPayFragment!!, TAG_PAY_CASH)
switchButton(false, true, false, false)
}
@@ -75,9 +73,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
if (binding.btnPayNumber.isChecked) {
return@setOnClickListener
}
if (numberPayFragment == null) {
numberPayFragment = NumberPayFragment()
}
numberPayFragment = NumberPayFragment()
showFragment(numberPayFragment!!, TAG_PAY_NUMBER)
switchButton(false, false, true, false)
}
@@ -92,9 +88,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
}
private fun showScanQrCodePay() {
if (qrCodePayFragment == null) {
qrCodePayFragment = ScanQrCodePayFragment()
}
qrCodePayFragment = ScanQrCodePayFragment()
showFragment(qrCodePayFragment!!, TAG_PAY_QR_CODE)
switchButton(true, false, false, false)
}
@@ -107,9 +101,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
}
fun showFacePay() {
if (facePayFragment == null) {
facePayFragment = FacePayFragment()
}
facePayFragment = FacePayFragment()
showFragment(facePayFragment!!, TAG_PAY_FACE)
switchButton(false, false, false, true)
}
@@ -149,9 +141,7 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
// }
fun showPayResult() {
if (payResultFragment == null) {
payResultFragment = PayResultFragment()
}
payResultFragment = PayResultFragment()
showFragment(payResultFragment!!, TAG_PAY_RESULT)
}
@@ -162,9 +152,10 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
facePayFragment?.presentation?.dismiss()
super.onDestroy()
}
private var scanQrCodePayPresentation: ScanQrCodePayPresentation?=null
private var scanQrCodePayPresentation: ScanQrCodePayPresentation? = null
fun paySuccess() {
showFragment(PayResultFragment(),"")
showFragment(PayResultFragment(), "")
if (displays.size > 1) {
scanQrCodePayPresentation = ScanQrCodePayPresentation(
activity = this,
@@ -15,7 +15,7 @@ import kotlin.text.replace
class SettingActivity : BaseActivity<ActivitySettingBinding>() {
private val viewModel by viewModels<UserViewModel>()
val viewModel by viewModels<UserViewModel>()
override fun getViewModel(): BaseViewModel {
return viewModel
}
@@ -34,12 +34,16 @@ import com.sw.dualscreen.utils.ImageUtil
import com.sw.plate.utils.ToastUtils
import io.objectbox.Box
import io.objectbox.kotlin.boxFor
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.File
import kotlin.getValue
class CollectFragment : BaseFragment<FragmentCollectBinding>() {
companion object {
private const val TAG = "CollectFragment"
const val MAX_COUNT = 5
}
private var selectedFoodId: String? = ""
@@ -59,7 +63,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
SearchFoodAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position ->
checkedItem = searchFoodList[position]
selectedFoodId = checkedItem!!.id
selectedFoodId = checkedItem!!.foodId
selectedFoodName = checkedItem!!.foodName
val isChecked = checkedItem!!.isChecked
searchFoodList[position].isChecked = isChecked.not()
@@ -78,8 +82,11 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
foodCollectionList[position].let {
it.bitmap = null
it.imageVector = null
it.imageFile = null
it.isShowCamera = true
it.isFinish = false
it.uploadSuccess = false
}
notifyItemChanged(position)
}
@@ -91,28 +98,45 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
private val cameraCallback: (Uri) -> Unit = { uri ->
val index = foodCollectionList.indexOfFirst { it.bitmap == null }
if (index == -1) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
rerurn@cameraCallback
}
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
// val cropBitmap = BitmapCropper.cropCenter(
// original = bitmap,
// targetWidth = 1300, targetHeight = 900,
// //offsetX = 30, offsetY = 100
// )
val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
foodCollectionList[index].let {
it.bitmap = bitmap
it.isShowCamera = false
it.imageUri = file?.toUri()
try {
val index = foodCollectionList.indexOfFirst { it.imageFile == null }
if (index == -1) {
ToastUtils.showToast("每次只允许保存${MAX_COUNT}条数据")
rerurn@cameraCallback
}
collectionAdapter.notifyItemChanged(index)
ImageUtil.uriToBitmap(requireActivity(), uri)?.let { bitmap ->
// val cropBitmap = BitmapCropper.cropCenter(
// original = bitmap,
// targetWidth = 1300, targetHeight = 900,
// //offsetX = 30, offsetY = 100
// )
initBox()
val imageVector = try {
FoodModule.bitmap2FloatArray(bitmap)
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("操作失败")
return@let
}
val file = BitmapSaver.saveToAppFilesDir(
bitmap, requireActivity(), "IMG_CROP_${System.currentTimeMillis()}.jpg"
)
Timber.d("${this.javaClass.simpleName}-cameraCallback-裁剪bitmap保存文件路径:${file?.absolutePath}")
foodCollectionList[index].let {
it.imageVector = imageVector
it.bitmap = null
it.isShowCamera = false
it.imageFile = file
}
collectionAdapter.notifyItemChanged(index)
if (bitmap.isRecycled.not()) {
bitmap.recycle()
}
}
} catch (e: Exception) {
e.printStackTrace()
ToastUtils.showToast("程序异常")
}
}
@@ -157,7 +181,9 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
Toast.makeText(requireActivity(), "请拍摄菜品照片", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
vectorThread()
vectorThread(){
upload()
}
}
binding.editFoodName.setOnEditorActionListener { v, actionId, event ->
@@ -190,13 +216,43 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}
}
private fun vectorThread() {
private fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
(requireActivity() as SettingActivity).viewModel.uploadCollectFoodPics(files,params, callback)
}
private fun upload() {
val params = HashMap<String, RequestBody>()
//params["placeId"] = restId.toRequestBody()
params["foodId"] = checkedItem!!.foodId.toRequestBody()
params["foodName"] = checkedItem!!.foodName!!.toRequestBody()
//params["foodVector"] = foodVector.toRequestBody()
for (index in foodCollectionList.indices step 5) {
val end = if(index + 5 < foodCollectionList.size - 1) index + 5 else foodCollectionList.size - 1
val subList = foodCollectionList.subList(index, end)
val subFiles = subList.map { it.imageFile }
uploadCollectFoodPics(subFiles, params) { isSuccess->
Timber.tag(TAG).d("uploadMultipleImages: ${isSuccess}")
subList.filter { it.imageFile!=null }.forEach { it.uploadSuccess = isSuccess }
// val count = collectList.count { it.imageFile!=null && it.uploadSuccess.not() }
// runOnUiThread {
// binding.btnUploadImage.text = "待上传图片${count}张"
// if (count == 0) {
// Loading.dismiss()
// }
// }
}
}
}
private fun vectorThread(block:()-> Unit) {
settingActivity?.showWaitingDialog("加载中……")
Thread {
foodCollectionList
.filter { it.bitmap != null }
// .filter { it.bitmap != null }
.filter { it.imageVector != null }
.forEachIndexed { index, it ->
image2VectorTask(it, index)
image2VectorTask(imageVector = it.imageVector!!, index)
}
activity?.runOnUiThread {
binding.root.postDelayed({
@@ -212,25 +268,24 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
}
}
private fun image2VectorTask(item: FoodCollectionBean, position: Int) {
private fun image2VectorTask(imageVector: FloatArray, position: Int) {
initBox()
val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
// Timber.tag("mzf1").e(base64Str)
//// viewModel.postImageData(
//// context,
//// foodId = selectedFoodId.toString(),
//// foodName = selectedFoodName.toString(),
//// foodVector = base64Str,
//// uri = item.imageUri!!
//// )
// val imageVector = FoodModule.bitmap2FloatArray(item.bitmap!!)
//
//// val base64Str = FloatBase64Utils.floatArrayToBase64(imageVector)
//// Timber.tag("mzf1").e(base64Str)
////// viewModel.postImageData(
////// context,
////// foodId = selectedFoodId.toString(),
////// foodName = selectedFoodName.toString(),
////// foodVector = base64Str,
////// uri = item.imageUri!!
////// )
box?.put(Food(name = checkedItem!!.foodName, foodIdx = 0, foodVector = imageVector))
foodCollectionList[position].let {
it.imageVector = imageVector
// it.imageVector = imageVector
it.isFinish = true
}
activity?.runOnUiThread {
collectionAdapter.notifyItemChanged(position)
}
@@ -33,14 +33,24 @@ class CashPayFragment : BaseFragment<FragmentCashPayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -29,14 +29,24 @@ class FacePayFragment : BaseFragment<FragmentFacePayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
fun loadBitmap(frame: Bitmap) {
binding.ivFaceImage.setImageBitmap(frame)
}
@@ -29,14 +29,24 @@ class NumberPayFragment: BaseFragment<FragmentNumberPayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -25,6 +25,8 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
private var payAmount: String? = null
private var payQrCodePic: Any? = null
var presentation: ScanQrCodePayPresentation?=null
private var countDownJob: Job? = null
override fun inflateViewBinding(): FragmentScanQrcodePayBinding {
return FragmentScanQrcodePayBinding.inflate(layoutInflater)
}
@@ -47,14 +49,25 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (hidden) {
binding.root.postDelayed({
presentation?.dismiss()
}, 500)
delayDismiss()
return
}
showSubScreen()
}
override fun onDestroy() {
delayDismiss()
countDownJob?.cancel() // 自动取消订阅,防止内存泄漏
super.onDestroy()
}
private fun delayDismiss() {
presentation?.dismiss()
//binding.root.postDelayed({
// presentation?.dismiss()
//}, 100)
}
private fun showSubScreen() {
// 查找副屏(通常索引为1
if (displays.size > 1) {
@@ -90,9 +103,4 @@ class ScanQrCodePayFragment: BaseFragment<FragmentScanQrcodePayBinding>() {
}
)
}
private var countDownJob: Job? = null
override fun onDestroy() {
super.onDestroy()
countDownJob?.cancel() // 自动取消订阅,防止内存泄漏
}
}
@@ -10,11 +10,11 @@
//import com.sw.dualscreen.R
//import com.sw.dualscreen.databinding.ListItemCollectedDataBinding
//import com.sw.dualscreen.databinding.ListItemFoodCollectionBinding
//import com.sw.dualscreen.objbox.CollectedFoodBean
//import com.sw.dualscreen.objbox.CollectedFoodInfo
//import com.sw.dualscreen.objbox.FoodCollectionBean
//
//class CollectedFoodAdapter (var list: MutableList<CollectedFoodBean>) :
// BaseQuickAdapter<CollectedFoodBean, CollectedFoodAdapter.VH>(list) {
//class CollectedFoodAdapter (var list: MutableList<CollectedFoodInfo>) :
// BaseQuickAdapter<CollectedFoodInfo, CollectedFoodAdapter.VH>(list) {
//
// inner class VH(var binding: ListItemCollectedDataBinding) : QuickViewHolder(binding.root)
//
@@ -24,7 +24,7 @@
// return VH(binding)
// }
//
// override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodBean?) {
// override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodInfo?) {
// holder.binding.tvFoodName.text = item?.foodName
// holder.binding.divider.run {
// visibility = if (position == list.size - 1) View.GONE else View.VISIBLE
@@ -6,10 +6,10 @@ import android.view.ViewGroup
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.sw.dualscreen.databinding.ListItemCollectedFoodBinding
import com.sw.dualscreen.objbox.CollectedFoodBean
import com.sw.dualscreen.objbox.CollectedFoodInfo
class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodBean>) :
BaseQuickAdapter<CollectedFoodBean, CollectedFoodNewAdapter.VH>(list) {
class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodInfo>) :
BaseQuickAdapter<CollectedFoodInfo, CollectedFoodNewAdapter.VH>(list) {
inner class VH(var binding: ListItemCollectedFoodBinding) : QuickViewHolder(binding.root)
@@ -19,9 +19,9 @@ class CollectedFoodNewAdapter(var list: MutableList<CollectedFoodBean>) :
return VH(binding)
}
override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodBean?) {
override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodInfo?) {
holder.binding.tvFoodName.text = item?.foodName
holder.binding.tvCollectedNum.text = "已采集${item?.count}"
holder.binding.tvCollectedNum.text = "已采集${item?.foodCount}"
}
}
@@ -26,7 +26,7 @@ class SearchFoodAdapter(var list: MutableList<FoodInfo>) :
text = item.foodName
} else {
val score = (item.score / 100.0).format2String(2)
text = item.foodName + if (item.score != 0) "-${score}%" else ""
text = item.foodName + (if (item.score != 0) "-${score}%" else "")
}
isChecked = item.isChecked
}
@@ -1,17 +1,16 @@
package com.sw.dualscreen.model.response
data class ApiResponse<T>(
val code: Int? = 0,
val message: String? = "",
val result: T? = null,
val success: Boolean? = false,
val timestamp: Long? = 0
val code: String,
val msg: String? = "",
val data: T? = null
) {
fun isSuccess(): Boolean {
return success == true
}
fun isSuccess(): Boolean = ("00000" == code)
val result: T?
get() = data
val message: String?
get() = msg
}
@@ -0,0 +1,5 @@
package com.sw.dualscreen.model.response
data class FoodSearchReq(
var nameList:List<String>
)
@@ -1,42 +1,47 @@
package com.sw.dualscreen.model.response
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
data class DinnerTypeInfo(
@SerializedName("dinnerType")
val dinnerType: DinnerType? = DinnerType()
) : Parcelable {
@Parcelize
data class DinnerType(
@SerializedName("createBy")
val createBy: String? = "",
@SerializedName("createTime")
val createTime: String? = "",
@SerializedName("delFlag")
val delFlag: Int? = 0,
@SerializedName("dinnerType")
val dinnerType: String? = "",
@SerializedName("endTime")
val endTime: String? = "",
@SerializedName("id")
val id: Int? = 0,
@SerializedName("isSync")
val isSync: Int? = 0,
@SerializedName("isSyncCopy")
val isSyncCopy: Int? = 0,
@SerializedName("restId")
val restId: String? = "",
@SerializedName("startTime")
val startTime: String? = "",
@SerializedName("sysOrgCode")
val sysOrgCode: String? = "",
@SerializedName("updateBy")
val updateBy: String? = "",
@SerializedName("updateTime")
val updateTime: String? = ""
) : Parcelable
}
//{"id":"1992804086323437569","dinnerType":"晚餐","chargeType":1,"fixedAmount":3.0000}
data class DinnerType(
val id: String? = "",
//餐次
val dinnerType: String? = "",
//餐次收费模式(0称重,1固定,2不收费)
val chargeType: Int = 0,
//固定收费(元) 仅charge_type = 1 时
val fixedAmount: Double?=null
)
//@Parcelize
//data class DinnerTypeInfo(
// @SerializedName("dinnerType")
// val dinnerType: DinnerType? = DinnerType()
//) : Parcelable
//
//@Parcelize
//data class DinnerType(
// @SerializedName("createBy")
// val createBy: String? = "",
// @SerializedName("createTime")
// val createTime: String? = "",
// @SerializedName("delFlag")
// val delFlag: Int? = 0,
// @SerializedName("dinnerType")
// val dinnerType: String? = "",
// @SerializedName("endTime")
// val endTime: String? = "",
// @SerializedName("id")
// val id: Int? = 0,
// @SerializedName("isSync")
// val isSync: Int? = 0,
// @SerializedName("isSyncCopy")
// val isSyncCopy: Int? = 0,
// @SerializedName("restId")
// val restId: String? = "",
// @SerializedName("startTime")
// val startTime: String? = "",
// @SerializedName("sysOrgCode")
// val sysOrgCode: String? = "",
// @SerializedName("updateBy")
// val updateBy: String? = "",
// @SerializedName("updateTime")
// val updateTime: String? = ""
//) : Parcelable
@@ -12,11 +12,11 @@ data class EquipmentInfo(
@SerializedName("appPackageUrl")
val appPackageUrl: String? = "",
@SerializedName("arcsoftActiveKey")
val arcsoftActiveKey: String? = "",
var arcsoftActiveKey: String? = "",
@SerializedName("arcsoftAppId")
val arcsoftAppId: String? = "",
var arcsoftAppId: String? = "",
@SerializedName("arcsoftSdkKey")
val arcsoftSdkKey: String? = "",
var arcsoftSdkKey: String? = "",
@SerializedName("arrayCross")
val arrayCross: Int? = 0,
@SerializedName("arrayMode")
@@ -24,9 +24,9 @@ data class EquipmentInfo(
@SerializedName("arrayVertical")
val arrayVertical: Int? = 0,
@SerializedName("canteenId")
val canteenId: String? = "",
var canteenId: String? = "",
@SerializedName("canteenName")
val canteenName: String? = "",
var canteenName: String? = "",
@SerializedName("clientServerIp")
val clientServerIp: String? = "",
@SerializedName("createBy")
@@ -1,6 +1,5 @@
package com.sw.dualscreen.model.response
import android.net.Uri
import android.os.Parcelable
import android.text.TextUtils
@@ -12,292 +11,296 @@ import kotlinx.parcelize.Parcelize
*/
@Parcelize
data class FoodInfo(
@SerializedName("foodLabel")
val foodLabel: String? = "",
@SerializedName("foodName")
val foodName: String? = "",
@SerializedName("foodTypeAndRealIntakeVoList")
val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo?>? = listOf(),
/**
* 食物id
*/
@SerializedName("id")
val id: String? = "",
@SerializedName("imgUrl")
var imgUrl: String? = "",
/**
* 拍照结果
*/
//菜品id
val foodId:String,
//菜品名称
val foodName:String? = null,
//能量
val calorie:String? = null,
//蛋白质
val protein:String? = null,
//脂肪
val fat:String? = null,
//碳水化合物
val carbohydrate:String? = null,
//规格售卖价格(元)
val specPrice:String? = null,
//VIP售卖价(元)
val vipPrice:String? = null,
var score: Int = 0,
var isChecked: Boolean = false,
var photoUri: Uri? = null,
var imgUrl: String? = "",
// @SerializedName("foodTypeAndRealIntakeVoList")
// val foodTypeAndRealIntakeVoList: List<FoodTypeAndRealIntakeVo>? = listOf(),
@SerializedName("stFoodInfoMaterial")
val stFoodInfoMaterial: StFoodInfoMaterial? = StFoodInfoMaterial(),
@SerializedName("stFoodInfoPagoda")
val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(),
// @SerializedName("stFoodInfoPagoda")
// val stFoodInfoPagoda: StFoodInfoPagoda? = StFoodInfoPagoda(),
@SerializedName("stFoodInfoPagodaAPPVO")
val stFoodInfoPagodaAPPVO: StFoodInfoPagodaAPPVO? = StFoodInfoPagodaAPPVO(),
@SerializedName("stFoodInfoSetting")
val stFoodInfoSetting: StFoodInfoSetting? = StFoodInfoSetting(),
@SerializedName("stFoodInfoSpecificationList")
val stFoodInfoSpecificationList: List<StFoodInfoSpecification?>? = listOf(),
var score: Int = 0,
var isChecked: Boolean = false
// @SerializedName("stFoodInfoSetting")
// val stFoodInfoSetting: StFoodInfoSetting? = StFoodInfoSetting(),
// @SerializedName("stFoodInfoSpecificationList")
// val stFoodInfoSpecificationList: List<StFoodInfoSpecification>? = listOf(),
) : Parcelable
//@Parcelize
//data class FoodTypeAndRealIntakeVo(
// @SerializedName("childMaterClassName")
// val childMaterClassName: String? = "",
// @SerializedName("foodId")
// val foodId: String? = "",
// @SerializedName("goodsId")
// val goodsId: String? = "",
// @SerializedName("goodsName")
// val goodsName: String? = "",
// @SerializedName("materClassName")
// val materClassName: String? = "",
// @SerializedName("materId")
// val materId: String? = "",
// @SerializedName("materialType")
// val materialType: String? = "",
// @SerializedName("realityIntake")
// val realityIntake: String? = ""
//) : Parcelable
@Parcelize
data class StFoodInfoMaterial(
@SerializedName("ash")
val ash: Double? = 0.0,
@SerializedName("avitE")
val avitE: Double? = 0.0,
@SerializedName("ca")
val ca: Double? = 0.0,
@SerializedName("cho")
val cho: Double? = 0.0,
@SerializedName("cholesterol")
val cholesterol: Double? = 0.0,
@SerializedName("cu")
val cu: Double? = 0.0,
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("dietFiber")
val dietFiber: Double? = 0.0,
@SerializedName("elementI")
val elementI: Double? = 0.0,
@SerializedName("elementK")
val elementK: String? = "",
@SerializedName("elementP")
val elementP: String? = "",
@SerializedName("energyKcal")
val energyKcal: Double? = 0.0,
@SerializedName("energyKj")
val energyKj: Double? = 0.0,
@SerializedName("fat")
val fat: Double? = 0.0,
@SerializedName("fe")
val fe: Double? = 0.0,
@SerializedName("folate")
val folate: Double? = 0.0,
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("foodWeight")
val foodWeight: String? = "",
@SerializedName("historyStatus")
val historyStatus: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("mg")
val mg: Double? = 0.0,
@SerializedName("mn")
val mn: Double? = 0.0,
@SerializedName("na")
val na: Double? = 0.0,
@SerializedName("naicin")
val naicin: Double? = 0.0,
@SerializedName("protein")
val protein: Double? = 0.0,
@SerializedName("retionl")
val retionl: Double? = 0.0,
@SerializedName("riboflavin")
val riboflavin: Double? = 0.0,
@SerializedName("se")
val se: Double? = 0.0,
@SerializedName("thiamin")
val thiamin: Double? = 0.0,
@SerializedName("totCarotene")
val totCarotene: Double? = 0.0,
@SerializedName("vitA")
val vitA: Double? = 0.0,
@SerializedName("vitB12")
val vitB12: Double? = 0.0,
@SerializedName("vitB6")
val vitB6: Double? = 0.0,
@SerializedName("vitC")
val vitC: Double? = 0.0,
@SerializedName("vitE")
val vitE: Double? = 0.0,
@SerializedName("water")
val water: Double? = 0.0,
@SerializedName("zn")
val zn: Double? = 0.0
) : Parcelable
//@Parcelize
//data class StFoodInfoPagoda(
// @SerializedName("aquatic")
// val aquatic: String? = "",
// @SerializedName("birds")
// val birds: String? = "",
// @SerializedName("delFlag")
// val delFlag: String? = "",
// @SerializedName("egg")
// val egg: String? = "",
// @SerializedName("foodId")
// val foodId: String? = "",
// @SerializedName("fruits")
// val fruits: String? = "",
// @SerializedName("grain")
// val grain: String? = "",
// @SerializedName("id")
// val id: String? = "",
// @SerializedName("isSync")
// val isSync: String? = "",
// @SerializedName("isSyncCopy")
// val isSyncCopy: String? = "",
// @SerializedName("livestock")
// val livestock: String? = "",
// @SerializedName("milk")
// val milk: String? = "",
// @SerializedName("nuts")
// val nuts: String? = "",
// @SerializedName("oil")
// val oil: String? = "",
// @SerializedName("potato")
// val potato: String? = "",
// @SerializedName("salt")
// val salt: String? = "",
// @SerializedName("soya")
// val soya: String? = "",
// @SerializedName("sugar")
// val sugar: String? = "",
// @SerializedName("vegetable")
// val vegetable: String? = ""
//) : Parcelable
@Parcelize
data class StFoodInfoPagodaAPPVO(
@SerializedName("fruits")
val fruits: String? = "",
@SerializedName("fruitsRecommend")
val fruitsRecommend: String? = "",
@SerializedName("grain")
val grain: String? = "",
@SerializedName("grainRecommend")
val grainRecommend: String? = "",
@SerializedName("meat")
val meat: String? = "",
@SerializedName("meatRecommend")
val meatRecommend: String? = "",
@SerializedName("oil")
val oil: String? = "",
@SerializedName("salt")
val salt: String? = "",
@SerializedName("soya")
val soya: String? = "",
@SerializedName("soyaRecommend")
val soyaRecommend: String? = "",
@SerializedName("sugar")
val sugar: String? = "",
@SerializedName("vegetable")
val vegetable: String? = "",
@SerializedName("vegetableRecommend")
val vegetableRecommend: String? = ""
) : Parcelable {
@Parcelize
data class FoodTypeAndRealIntakeVo(
@SerializedName("childMaterClassName")
val childMaterClassName: String? = "",
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("goodsId")
val goodsId: String? = "",
@SerializedName("goodsName")
val goodsName: String? = "",
@SerializedName("materClassName")
val materClassName: String? = "",
@SerializedName("materId")
val materId: String? = "",
@SerializedName("materialType")
val materialType: String? = "",
@SerializedName("realityIntake")
val realityIntake: String? = ""
) : Parcelable
@Parcelize
data class StFoodInfoMaterial(
@SerializedName("ash")
val ash: Double? = 0.0,
@SerializedName("avitE")
val avitE: Double? = 0.0,
@SerializedName("ca")
val ca: Double? = 0.0,
@SerializedName("cho")
val cho: Double? = 0.0,
@SerializedName("cholesterol")
val cholesterol: Double? = 0.0,
@SerializedName("cu")
val cu: Double? = 0.0,
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("dietFiber")
val dietFiber: Double? = 0.0,
@SerializedName("elementI")
val elementI: Double? = 0.0,
@SerializedName("elementK")
val elementK: String? = "",
@SerializedName("elementP")
val elementP: String? = "",
@SerializedName("energyKcal")
val energyKcal: Double? = 0.0,
@SerializedName("energyKj")
val energyKj: Double? = 0.0,
@SerializedName("fat")
val fat: Double? = 0.0,
@SerializedName("fe")
val fe: Double? = 0.0,
@SerializedName("folate")
val folate: Double? = 0.0,
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("foodWeight")
val foodWeight: String? = "",
@SerializedName("historyStatus")
val historyStatus: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("mg")
val mg: Double? = 0.0,
@SerializedName("mn")
val mn: Double? = 0.0,
@SerializedName("na")
val na: Double? = 0.0,
@SerializedName("naicin")
val naicin: Double? = 0.0,
@SerializedName("protein")
val protein: Double? = 0.0,
@SerializedName("retionl")
val retionl: Double? = 0.0,
@SerializedName("riboflavin")
val riboflavin: Double? = 0.0,
@SerializedName("se")
val se: Double? = 0.0,
@SerializedName("thiamin")
val thiamin: Double? = 0.0,
@SerializedName("totCarotene")
val totCarotene: Double? = 0.0,
@SerializedName("vitA")
val vitA: Double? = 0.0,
@SerializedName("vitB12")
val vitB12: Double? = 0.0,
@SerializedName("vitB6")
val vitB6: Double? = 0.0,
@SerializedName("vitC")
val vitC: Double? = 0.0,
@SerializedName("vitE")
val vitE: Double? = 0.0,
@SerializedName("water")
val water: Double? = 0.0,
@SerializedName("zn")
val zn: Double? = 0.0
) : Parcelable
fun fruitsValue(): Double =
if (TextUtils.isEmpty(fruits))
0.0
else fruits!!.toDouble()
@Parcelize
data class StFoodInfoPagoda(
@SerializedName("aquatic")
val aquatic: String? = "",
@SerializedName("birds")
val birds: String? = "",
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("egg")
val egg: String? = "",
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("fruits")
val fruits: String? = "",
@SerializedName("grain")
val grain: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("livestock")
val livestock: String? = "",
@SerializedName("milk")
val milk: String? = "",
@SerializedName("nuts")
val nuts: String? = "",
@SerializedName("oil")
val oil: String? = "",
@SerializedName("potato")
val potato: String? = "",
@SerializedName("salt")
val salt: String? = "",
@SerializedName("soya")
val soya: String? = "",
@SerializedName("sugar")
val sugar: String? = "",
@SerializedName("vegetable")
val vegetable: String? = ""
) : Parcelable
fun grainValue(): Double =
if (TextUtils.isEmpty(grain))
0.0
else grain!!.toDouble()
@Parcelize
data class StFoodInfoPagodaAPPVO(
@SerializedName("fruits")
val fruits: String? = "",
@SerializedName("fruitsRecommend")
val fruitsRecommend: String? = "",
@SerializedName("grain")
val grain: String? = "",
@SerializedName("grainRecommend")
val grainRecommend: String? = "",
@SerializedName("meat")
val meat: String? = "",
@SerializedName("meatRecommend")
val meatRecommend: String? = "",
@SerializedName("oil")
val oil: String? = "",
@SerializedName("salt")
val salt: String? = "",
@SerializedName("soya")
val soya: String? = "",
@SerializedName("soyaRecommend")
val soyaRecommend: String? = "",
@SerializedName("sugar")
val sugar: String? = "",
@SerializedName("vegetable")
val vegetable: String? = "",
@SerializedName("vegetableRecommend")
val vegetableRecommend: String? = ""
) : Parcelable {
fun vegetableValue(): Double =
if (TextUtils.isEmpty(vegetable))
0.0
else vegetable!!.toDouble()
fun fruitsValue(): Double =
if (TextUtils.isEmpty(fruits))
0.0
else fruits!!.toDouble()
fun meatValue(): Double =
if (TextUtils.isEmpty(meat))
0.0
else meat!!.toDouble()
}
fun grainValue(): Double =
if (TextUtils.isEmpty(grain))
0.0
else grain!!.toDouble()
//@Parcelize
//data class StFoodInfoSetting(
// @SerializedName("addFoodWeight")
// val addFoodWeight: String? = "",
// @SerializedName("bowlPlateWeight")
// val bowlPlateWeight: String? = "",
// @SerializedName("delFlag")
// val delFlag: String? = "",
// @SerializedName("foodId")
// val foodId: String? = "",
// @SerializedName("foodStatus")
// val foodStatus: String? = "",
// @SerializedName("id")
// val id: String? = "",
// @SerializedName("inventoryStatus")
// val inventoryStatus: Boolean? = false,
// @SerializedName("isSync")
// val isSync: String? = "",
// @SerializedName("isSyncCopy")
// val isSyncCopy: String? = "",
// @SerializedName("replenishWeight")
// val replenishWeight: String? = "",
// @SerializedName("residueType")
// val residueType: String? = "",
// @SerializedName("tablewareStatus")
// val tablewareStatus: Boolean? = false,
// @SerializedName("tablewareWeight")
// val tablewareWeight: String? = "",
// @SerializedName("warningStatus")
// val warningStatus: String? = "",
// @SerializedName("weighStatus")
// val weighStatus: String? = "",
// @SerializedName("weighUnitId")
// val weighUnitId: String? = "",
// @SerializedName("weighUnitName")
// val weighUnitName: String? = ""
//) : Parcelable
fun vegetableValue(): Double =
if (TextUtils.isEmpty(vegetable))
0.0
else vegetable!!.toDouble()
fun meatValue(): Double =
if (TextUtils.isEmpty(meat))
0.0
else meat!!.toDouble()
}
@Parcelize
data class StFoodInfoSetting(
@SerializedName("addFoodWeight")
val addFoodWeight: String? = "",
@SerializedName("bowlPlateWeight")
val bowlPlateWeight: String? = "",
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("foodStatus")
val foodStatus: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("inventoryStatus")
val inventoryStatus: Boolean? = false,
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("replenishWeight")
val replenishWeight: String? = "",
@SerializedName("residueType")
val residueType: String? = "",
@SerializedName("tablewareStatus")
val tablewareStatus: Boolean? = false,
@SerializedName("tablewareWeight")
val tablewareWeight: String? = "",
@SerializedName("warningStatus")
val warningStatus: String? = "",
@SerializedName("weighStatus")
val weighStatus: String? = "",
@SerializedName("weighUnitId")
val weighUnitId: String? = "",
@SerializedName("weighUnitName")
val weighUnitName: String? = ""
) : Parcelable
@Parcelize
data class StFoodInfoSpecification(
@SerializedName("bowlPlateWeight")
val bowlPlateWeight: Double? = 0.0,
@SerializedName("defaultStatus")
val defaultStatus: String? = "",
@SerializedName("delFlag")
val delFlag: String? = "",
@SerializedName("foodId")
val foodId: String? = "",
@SerializedName("id")
val id: String? = "",
@SerializedName("isSync")
val isSync: String? = "",
@SerializedName("isSyncCopy")
val isSyncCopy: String? = "",
@SerializedName("specId")
val specId: String? = "",
@SerializedName("specName")
val specName: String? = "",
@SerializedName("specPrice")
val specPrice: String? = "",
@SerializedName("specWeight")
val specWeight: Double? = 0.0
) : Parcelable
}
//@Parcelize
//data class StFoodInfoSpecification(
// @SerializedName("bowlPlateWeight")
// val bowlPlateWeight: Double? = 0.0,
// @SerializedName("defaultStatus")
// val defaultStatus: String? = "",
// @SerializedName("delFlag")
// val delFlag: String? = "",
// @SerializedName("foodId")
// val foodId: String? = "",
// @SerializedName("id")
// val id: String? = "",
// @SerializedName("isSync")
// val isSync: String? = "",
// @SerializedName("isSyncCopy")
// val isSyncCopy: String? = "",
// @SerializedName("specId")
// val specId: String? = "",
// @SerializedName("specName")
// val specName: String? = "",
// @SerializedName("specPrice")
// val specPrice: String? = "",
// @SerializedName("specWeight")
// val specWeight: Double? = 0.0
//) : Parcelable
@@ -10,14 +10,15 @@ import kotlinx.parcelize.Parcelize
*/
@Parcelize
data class UserFaceModel(
@SerializedName("faceFeature")
val faceFeature: String? = "",
@SerializedName("faceFeatureString")
val faceFeatureString: String? = "",
@SerializedName("faceType")
val faceType: String? = "",
@SerializedName("userFaceId")
val userFaceId: String? = "",
@SerializedName("userId")
val userId: String? = ""
// @SerializedName("faceFeature")
// val faceFeature: String? = "",
// @SerializedName("faceFeatureString")
// val faceFeatureString: String? = "",
// @SerializedName("faceType")
// val faceType: String? = "",
// @SerializedName("userFaceId")
// val userFaceId: String? = "",
// @SerializedName("userId")
val userId: String? = "",
val faceFeatureStr: String? = ""
) : Parcelable
@@ -3,16 +3,16 @@ package com.sw.dualscreen.network.api
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.EquipmentInfo
import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserFaceInfo
import com.sw.dualscreen.model.response.FoodSearchReq
import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.objbox.CollectedFoodInfo
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
@@ -25,41 +25,54 @@ interface ApiService {
/**
* device获取token
*/
@GET("sys/getEquipmentToken")
suspend fun getDeviceToken(
@Query("qrcodeId") qrcodeId: String,
@Query("appVersion") appVersion: String = GlobalData.appVersion
): ApiResponse<String>
// @GET("sys/getEquipmentToken")
// suspend fun getDeviceToken(
// @Query("qrcodeId") qrcodeId: String,
// @Query("appVersion") appVersion: String = GlobalData.appVersion
// ): ApiResponse<String>
/**
*获取配置信息
*/
@GET("equipment/stEquipment/queryByEquipmentCode")
suspend fun getDeviceInfo(
@Query("equipmentCode") equipmentCode: String,
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Header("X-Access-Token") token: String
): ApiResponse<EquipmentInfo>
// @GET("equipment/stEquipment/queryByEquipmentCode")
// suspend fun getDeviceInfo(
// @Query("equipmentCode") equipmentCode: String,
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Header("X-Access-Token") token: String
// ): ApiResponse<EquipmentInfo>
/**
* 获取业务服务器token
*/
@GET
suspend fun getEquipmentToken(
@Url url: String = "${GlobalData.appBaseUrl}/sys/getEquipmentToken",
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Query("qrcodeId") qrcodeId: String
): ApiResponse<String>
// @GET
// suspend fun getEquipmentToken(
// @Url url: String = "${GlobalData.appBaseUrl}/sys/getEquipmentToken",
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Query("qrcodeId") qrcodeId: String
// ): ApiResponse<String>
/**
* 获取人脸数据
*/
@GET
@POST
suspend fun getUserFaceCache(
@Url url: String = "${GlobalData.appBaseUrl}/stapi/cquser/getUserFaceCache/v2",
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Query("pageIndex") pageIndex: Int
): ApiResponse<UserFaceInfo>
// @Url url: String = "${GlobalData.appBaseUrl}/stapi/cquser/getUserFaceCache/v2",
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/faceFeature/list",
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Query("pageIndex") pageIndex: Int
@Body param: Map<String, Int>
// @Query("pageNum") pageNum: Int,
// @Query("pageSize") pageSize: Int
): ApiResponse<List<UserFaceModel>>
/**
* 获取已采集数据列表
*/
@POST
suspend fun getCollectedFoodList(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/dishPage",
@Body param: Map<String, Int>
): ApiResponse<List<CollectedFoodInfo>>
/**
@@ -67,11 +80,14 @@ interface ApiService {
*/
@GET
suspend fun getRestInfoFoodsByType(
@Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getRestInfoFoodsByType/stall",
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Query("restId") restId: String,
@Query("type") type: Int,
@Query("foodName") foodName: String,
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getRestInfoFoodsByType/stall",
// @Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/getFoodsByFoodNamePage",
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/getFoodsByFoodNameList",
@Query("name") foodName: String,
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Query("restId") restId: String,
// @Query("type") type: Int,
// @Query("foodName") foodName: String,
): ApiResponse<List<FoodInfo>>
/**
@@ -91,10 +107,11 @@ interface ApiService {
*/
@GET
suspend fun getDinnerType(
@Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getCanteenDinnerType",
@Query("appVersion") appVersion: String = GlobalData.appVersion,
@Query("canteenId") restId: String,
): ApiResponse<DinnerTypeInfo>
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getCanteenDinnerType",
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/getRegionRule",
// @Query("appVersion") appVersion: String = GlobalData.appVersion,
// @Query("canteenId") restId: String,
): ApiResponse<DinnerType>
/**
* 提交就餐数据
@@ -108,11 +125,13 @@ interface ApiService {
/**
* 获取菜品信息
*/
@GET
@POST
suspend fun getFoodInfo(
@Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getRestInfoFoodsByType/stall/v2",
@Query("restId") restId: String,
@Query("foodNames") foodName: String,
// @Url url: String = "${GlobalData.appBaseUrl}/zhstapi/zhst/getRestInfoFoodsByType/stall/v2",
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/boothMachine/app/goodsList",
// @Query("restId") restId: String,
// @Query("foodNames") foodName: String
@Body req: FoodSearchReq
): ApiResponse<List<FoodInfo>>
@@ -121,10 +140,11 @@ interface ApiService {
*/
@Multipart
@POST
suspend fun postImageData(
@Url url: String = "http://192.168.1.201:14801/terminal/neglect/dishCollectionVectorData/add",
@PartMap params: Map<String, @JvmSuppressWildcards RequestBody>,
@Part image: MultipartBody.Part?
suspend fun uploadCollectFoodPics(
// @Url url: String = "http://192.168.1.201:14801/terminal/neglect/dishCollectionVectorData/add",
@Url url: String = "http://192.168.1.201:14801/terminal/neglect/boothMachine/app/dishCollectionVectorData/add",
@PartMap params: HashMap<String, RequestBody>,
@Part foodPics: List<MultipartBody.Part>
): ApiResponse<String>
}
@@ -1,6 +1,7 @@
package com.sw.dualscreen.network.interceptor
import android.text.TextUtils
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.utils.SPUtil
import com.sw.plate.App
@@ -18,7 +19,10 @@ class RequestInterceptor : Interceptor {
.header("Content-Type", "application/json")
.header("Accept", "application/json")
// .header("Authorization", "Bearer ${getToken()}")
.header("X-Access-Token", getToken(originalRequest))
// .header("X-Access-Token", getToken(originalRequest))
// .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41")
.header("X-DEVICE-CODE", GlobalData.deviceId)
.header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d")
val newRequest = requestBuilder.build()
@@ -2,6 +2,7 @@ package com.sw.dualscreen.objbox
import android.graphics.Bitmap
import android.net.Uri
import java.io.File
data class FoodClassInfo(
var class_names: List<String>,
@@ -17,14 +18,20 @@ data class FoodClassInfo(
//)
data class FoodCollectionBean(
var imageUri: Uri? = null,
var imageFile: File? = null,
var bitmap: Bitmap? = null,
var imageVector: FloatArray? = null,
var isShowCamera: Boolean = false,
var isFinish:Boolean = false
var isFinish:Boolean = false,
var uploadSuccess:Boolean = false
)
data class CollectedFoodBean(
var foodName: String?,
var count: Int = 0
data class CollectedFoodInfo(
var id: String? = null,
var placeId: String? = null,
var foodId: String? = null,
var foodName: String? = null,
var foodPic: Any? = null,
var foodVector: Any? = null,
var foodCount: Int = 0
)
@@ -29,7 +29,7 @@ import com.sw.dualscreen.ext.gone
import com.sw.dualscreen.ext.maskName
import com.sw.dualscreen.ext.visible
import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.utils.Debouncer
@@ -89,7 +89,7 @@ class MainScreenPresentation(
private var detectWeight = 0.0 //识别菜品时的重量
private var lastWeight = 0.0 // 上一次的计算热量结果
private var userNutritionData: UserNutritionData? = null
private var dinnerTypeInfo: DinnerTypeInfo? = null
private var dinnerTypeInfo: DinnerType? = null
private val debouncer = Debouncer(500)
private var recognitionTime: Long = 0L // 人脸识别时的时间
private var recognitionWeight: Double = 0.0 // 人脸识别时的重量
@@ -228,27 +228,18 @@ class MainScreenPresentation(
return
}
updateFoodInfo(currentFood!!)
// binding.flPreview.visibility = View.VISIBLE
// binding.ivRecImage.visibility = View.VISIBLE
// binding.flFace.visibility = View.INVISIBLE
//// binding.ivFaceBg.visibility = View.GONE
// binding.tvFaceTip.visibility = View.GONE
//
//// binding.tvBottomTip.visibility = View.GONE
// binding.nutritionInclude.clNutritionData.visibility = View.VISIBLE
foodRecSuccess(currentFood!!)
}
private fun initView() {
binding.ivRecImage.let {
it.outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
}
}
it.clipToOutline = true
}
// //binding.ivRecImage.let {
// it.outlineProvider = object : ViewOutlineProvider() {
// override fun getOutline(view: View, outline: Outline) {
// outline.setRoundRect(0, 0, view.width, view.height, 12f.dp)
// }
// }
// it.clipToOutline = true
// }
}
override fun onDisplayRemoved() {
super.onDisplayRemoved()
@@ -270,7 +261,7 @@ class MainScreenPresentation(
/**
* 餐品识别成功,计费模式
*/
fun loadBilledMode(foodInfo: FoodInfo) {
fun loadBilledMode() {
binding.calorieInclude.root.visible()
binding.nutritionInclude.root.gone()
@@ -279,7 +270,7 @@ class MainScreenPresentation(
binding.tvFaceTip.gone()
binding.tvFoodRecPrompt.gone()
binding.llPriceInfo.visible()
binding.ivRecImage.gone()
//binding.ivRecImage.gone()
//updateFoodInfo(foodInfo)
@@ -291,7 +282,7 @@ class MainScreenPresentation(
/**
* 餐品识别成功,不计费模式
*/
fun loadUnbilledMode(foodInfo: FoodInfo) {
fun loadUnbilledMode() {
binding.calorieInclude.root.gone()
binding.nutritionInclude.root.visible()
@@ -300,7 +291,7 @@ class MainScreenPresentation(
binding.tvFaceTip.gone()
binding.tvFoodRecPrompt.gone()
binding.llPriceInfo.gone()
binding.ivRecImage.gone()
//binding.ivRecImage.gone()
//updateFoodInfo(foodInfo)
userNutritionData?.let {
@@ -342,10 +333,12 @@ class MainScreenPresentation(
binding.tvFoodRecPrompt.visible()
binding.flCameraView.visible()
binding.ivPreviewImage.visible()
binding.ivRecImage.gone()
//binding.ivRecImage.gone()
binding.ivFaceRecMask.gone()
binding.tvFaceTip.gone()
binding.llPriceInfo.gone()
binding.flFace.gone()
binding.flRecognizeIr.gone()
pauseCamera()
activity.clearFoodList()
@@ -356,10 +349,10 @@ class MainScreenPresentation(
val mode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
if (mode == 0) {
//计费
loadBilledMode(foodInfo)
loadBilledMode()
} else {
//不计费
loadUnbilledMode(foodInfo)
loadUnbilledMode()
}
}
@@ -377,13 +370,14 @@ class MainScreenPresentation(
binding.tvFoodName.text = foodInfo.foodName
binding.flFace.visible()
binding.flRecognizeIr.visible()
binding.flCameraView.visible()
binding.ivFaceRecMask.visible()
binding.tvFaceTip.visible()
binding.tvFoodRecPrompt.visible()
binding.llPriceInfo.gone()
binding.ivRecImage.gone()
//binding.ivRecImage.gone()
binding.ivPreviewImage.gone()
dinnerTypeInfo = null
@@ -413,22 +407,22 @@ class MainScreenPresentation(
private fun updateFoodInfo(foodInfo: FoodInfo) {
binding.tvFoodName.text = foodInfo.foodName
binding.ivPreviewImage.gone()
binding.ivRecImage.visible()
if (foodInfo.photoUri != null) {
GlideUtils.loadRoundCornerImage(
context,
url = foodInfo.photoUri,
imageView = binding.ivRecImage,
radius = 12
)
} else {
GlideUtils.loadRoundCornerImage(
context,
url = foodInfo.imgUrl,
imageView = binding.ivRecImage,
radius = 12
)
}
//binding.ivRecImage.visible()
// if (foodInfo.photoUri != null) {
// GlideUtils.loadRoundCornerImage(
// context,
// url = foodInfo.photoUri,
// imageView = //binding.ivRecImage,
// radius = 12
// )
// } else {
// GlideUtils.loadRoundCornerImage(
// context,
// url = foodInfo.imgUrl,
// imageView = //binding.ivRecImage,
// radius = 12
// )
// }
}
private fun calculateNutrition(weight1: Double) {
@@ -436,7 +430,7 @@ class MainScreenPresentation(
if (weight < 0) weight = 0.0
debouncer.debounce {
Timber.tag(TAG).d("calculateNutrition weight = $weight, recognitionWeight = $recognitionWeight")
val dinnerType = dinnerTypeInfo!!.dinnerType!!.dinnerType!!
val dinnerType = dinnerTypeInfo!!.dinnerType!!
Timber.tag(TAG).d("calculateNutrition foodName = ${currentFood!!.foodName}, dinnerType = $dinnerType, userId = ${userNutritionData!!.userId}")
val calcResultInfo = UserNutritionUtils.calculateNutrition(
currentFood!!,
@@ -638,7 +632,7 @@ class MainScreenPresentation(
}
userViewModel.getUserNutritionData(
userId = userId,
foodId = currentFood!!.id!!
foodId = currentFood!!.foodId!!
)
})
@@ -953,7 +947,7 @@ class MainScreenPresentation(
}
val userNutritionParam = UserNutritionParam(
userId = userNutritionData?.userId!!,
foodId = currentFood?.id!!,
foodId = currentFood?.foodId !!,
faceTime = recognitionTime,
faceEndTime = System.currentTimeMillis(),
eatWeight = eatWeight,//lastWeight
File diff suppressed because it is too large Load Diff
@@ -18,31 +18,31 @@ abstract class BaseRepository {
when (e) {
is HttpException -> {
ApiResponse(code = e.code(), message = e.message())
ApiResponse(code = "${e.code()}", msg = e.message())
}
is SocketTimeoutException -> {
ApiResponse(code = -2, message = "请求超时: ${e.message}")
ApiResponse(code = "-2", msg = "请求超时: ${e.message}")
}
is ConnectException -> {
ApiResponse(code = -3, message = "连接失败: ${e.message}")
ApiResponse(code = "-3", msg = "连接失败: ${e.message}")
}
is SSLHandshakeException -> {
ApiResponse(code = -4, message = "SSL握手失败: ${e.message}")
ApiResponse(code = "-4", msg = "SSL握手失败: ${e.message}")
}
is JsonParseException -> {
ApiResponse(code = -5, message = "JSON解析错误: ${e.message}")
ApiResponse(code = "-5", msg = "JSON解析错误: ${e.message}")
}
is IOException -> {
ApiResponse(code = -6, message = "网络IO错误: ${e.message}")
ApiResponse(code = "-6", msg = "网络IO错误: ${e.message}")
}
else -> {
ApiResponse(code = -1, message = "未知错误: ${e.message ?: "无错误信息"}")
ApiResponse(code = "-1", msg = "未知错误: ${e.message ?: "无错误信息"}")
}
}
}
@@ -5,15 +5,20 @@ import android.net.Uri
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.ApiResponse
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.EquipmentInfo
import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserFaceInfo
import com.sw.dualscreen.model.response.FoodSearchReq
import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.network.api.ApiService
import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.utils.ImageUtil
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
/**
* 远程数据处理
@@ -24,43 +29,65 @@ class RemoteRepository constructor(
/**
* 生成token
*/
suspend fun getDeviceToken(qrcodeId: String): ApiResponse<String> {
return safeApiCall {
apiService.getDeviceToken(
qrcodeId
)
}
}
// suspend fun getDeviceToken(qrcodeId: String): ApiResponse<String> {
// return safeApiCall {
// apiService.getDeviceToken(
// qrcodeId
// )
// }
// }
/**
* 获取设备信息
*/
suspend fun getDeviceInfo(equipmentCode: String, token: String): ApiResponse<EquipmentInfo> {
return safeApiCall {
apiService.getDeviceInfo(
equipmentCode,
token = token
)
}
}
// suspend fun getDeviceInfo(equipmentCode: String, token: String): ApiResponse<EquipmentInfo> {
// return safeApiCall {
// apiService.getDeviceInfo(
// equipmentCode,
// token = token
// )
// }
// }
/**
* 获取业务服务器token
*/
suspend fun getEquipmentToken(qrcodeId: String): ApiResponse<String> {
return safeApiCall {
apiService.getEquipmentToken(qrcodeId = qrcodeId)
}
}
// suspend fun getEquipmentToken(qrcodeId: String): ApiResponse<String> {
// return safeApiCall {
// apiService.getEquipmentToken(qrcodeId = qrcodeId)
// }
// }
/**
* 获取人脸数据
*/
suspend fun getUserFaceCache(
pageIndex: Int
): ApiResponse<UserFaceInfo> {
pageNum: Int,
pageSize: Int = 100,
): ApiResponse<List<UserFaceModel>> {
return safeApiCall {
apiService.getUserFaceCache(pageIndex = pageIndex)
apiService.getUserFaceCache(
param = mapOf(
"pageNum" to pageNum,
"pageSize" to pageSize
)
)
}
}
/**
* 获取人脸数据
*/
suspend fun getCollectedFoodList(
pageNum: Int,
pageSize: Int = 50,
): ApiResponse<List<CollectedFoodInfo>> {
return safeApiCall {
apiService.getCollectedFoodList(
param = mapOf(
"pageNum" to pageNum,
"pageSize" to pageSize
)
)
}
}
@@ -75,7 +102,7 @@ class RemoteRepository constructor(
foodName: String,
): ApiResponse<List<FoodInfo>> {
return safeApiCall {
apiService.getRestInfoFoodsByType(restId = restId, type = type, foodName = foodName)
apiService.getRestInfoFoodsByType(foodName = foodName)
}
}
@@ -93,10 +120,10 @@ class RemoteRepository constructor(
}
suspend fun getDinnerType(
restId: String = GlobalData.restId,
): ApiResponse<DinnerTypeInfo> {
// restId: String = GlobalData.restId,
): ApiResponse<DinnerType> {
return safeApiCall {
apiService.getDinnerType(restId = restId)
apiService.getDinnerType()
}
}
@@ -118,29 +145,31 @@ class RemoteRepository constructor(
restId: String = GlobalData.restId,
foodName: String,
): ApiResponse<List<FoodInfo>> {
return safeApiCall { apiService.getFoodInfo(restId = restId, foodName = foodName) }
return safeApiCall {
// val map = mutableMapOf<String, List<String>>()
// map["nameList"] = foodName.split(",")
apiService.getFoodInfo(req = FoodSearchReq(nameList = foodName.split(",")))
}
}
/**
* 获取菜品信息
* @param restId 从device服务获取的canteenId字段
* @param foodName 菜品名称,多个使用逗号拼接
* 上传采集菜品信息
*/
suspend fun postImageData(
context: Context,
restId: String = GlobalData.restId,
foodId: String,
foodName: String,
foodVector: String,
uri: Uri,
): ApiResponse<String> {
val params = HashMap<String, RequestBody>()
params["placeId"] = restId.toRequestBody()
params["foodId"] = foodId.toRequestBody()
params["foodName"] = foodName.toRequestBody()
params["foodVector"] = foodVector.toRequestBody()
val imagePart = ImageUtil.uriToMultipart(context, uri, "foodPic")
return safeApiCall { apiService.postImageData(params = params, image = imagePart) }
suspend fun uploadCollectFoodPics(fileList: List<File>, params: HashMap<String, RequestBody>): ApiResponse<String> {
// 准备文件参数
val fileParts = mutableListOf<MultipartBody.Part>()
fileList.forEachIndexed { index, file ->
val requestFile = file
.asRequestBody("multipart/form-data".toMediaTypeOrNull())
val filePart = MultipartBody.Part.createFormData(
"foodPics",
file.name,
requestFile
)
fileParts.add(filePart)
}
return safeApiCall {
apiService.uploadCollectFoodPics(params = params, foodPics = fileParts)
}
}
}
@@ -15,6 +15,15 @@ object ImageUtil {
fun uriToBitmap(context: Context, uri: Uri): Bitmap? {
return try {
val options = BitmapFactory.Options()
//options.inSampleSize = 2; // 这会将图片的尺寸缩小到原来的1/2
options.inJustDecodeBounds = false
// options.inPreferredConfig = Bitmap.Config.ARGB_8888
options.inPreferredConfig = Bitmap.Config.RGB_565
context.contentResolver.openInputStream(uri)?.use { stream ->
BitmapFactory.decodeStream(stream, null, options)
// BitmapFactory.decodeStream(stream)
}
context.contentResolver.openInputStream(uri)?.use { stream ->
BitmapFactory.decodeStream(stream)
}
@@ -52,25 +52,25 @@ abstract class BaseViewModel() : ViewModel() {
}
protected open fun parseResponse(response: ApiResponse<*>): Boolean {
if (response.isSuccess()
|| response.code == 200
|| response.code == 0
) {
val code = response.code
if (code == "00000" || code == "200" || code == "0") {
return true
}
Timber.d("msg = ${response.message}, code = ${response.code}")
ToastUtils.showToast("${response.message}(${response.code})")
val message = response.message?:response.msg
Timber.d("msg = ${message}, code = $code")
ToastUtils.showToast("${message}(${code})")
return false
}
fun parseEquipmentInfo(equipmentInfo: EquipmentInfo) {
GlobalData.appBaseUrl = equipmentInfo.appPackageUrl!!
//GlobalData.appBaseUrl="http://192.168.1.210/gateway/local"
GlobalData.sdkKey = equipmentInfo.arcsoftSdkKey!!
GlobalData.appId = equipmentInfo.arcsoftAppId!!
// GlobalData.activeKey = equipmentInfo.arcsoftActiveKey!!
GlobalData.restId = equipmentInfo.canteenId!!
}
// fun parseEquipmentInfo(equipmentInfo: EquipmentInfo) {
// //GlobalData.appBaseUrl = equipmentInfo.appPackageUrl!!
// GlobalData.appBaseUrl = "http://192.168.1.201:14801"
// //GlobalData.appBaseUrl="http://192.168.1.210/gateway/local"
// GlobalData.sdkKey = equipmentInfo.arcsoftSdkKey!!
// GlobalData.appId = equipmentInfo.arcsoftAppId!!
//// GlobalData.activeKey = equipmentInfo.arcsoftActiveKey!!
// GlobalData.restId = equipmentInfo.canteenId!!
// }
fun handleError(exception: Exception) {
Timber.d("handleError ${exception.message}")
@@ -19,49 +19,49 @@ class DeviceViewModel : BaseViewModel() {
/**
* 获取token
*/
fun getDeviceToken(deviceId: String = GlobalData.deviceId) {
launchWithLoading {
val response = repository.getDeviceToken(deviceId)
if (parseResponse(response)) {
val response1 = repository.getDeviceInfo(deviceId, response.result!!)
if (parseResponse(response1)) {
val equipmentInfo = response1.result
if (equipmentInfo == null) return@launchWithLoading
try {
parseEquipmentInfo(equipmentInfo)
SPUtil.getInstance()
.put(GlobalKey.KEY_EQUIPMENT_INFO, GsonUtils.toJson(equipmentInfo))
_deviceInfoResult.value = true
} catch (e: Exception) {
Timber.e(e)
}
}
}
}
}
// fun getDeviceToken(deviceId: String = GlobalData.deviceId) {
// launchWithLoading {
// val response = repository.getDeviceToken(deviceId)
// if (parseResponse(response)) {
// val response1 = repository.getDeviceInfo(deviceId, response.result!!)
//
// if (parseResponse(response1)) {
// val equipmentInfo = response1.result
// if (equipmentInfo == null) return@launchWithLoading
// try {
// parseEquipmentInfo(equipmentInfo)
// SPUtil.getInstance()
// .put(GlobalKey.KEY_EQUIPMENT_INFO, GsonUtils.toJson(equipmentInfo))
// _deviceInfoResult.value = true
// } catch (e: Exception) {
// Timber.e(e)
// }
// }
// }
// }
// }
/**
* 检查缓存数据
*/
fun checkEquipmentInfo(): Boolean {
val equipmentInfoStr = SPUtil.getInstance().get(GlobalKey.KEY_EQUIPMENT_INFO, "")
if (equipmentInfoStr == null) {
Timber.e("获取缓存设备信息失败")
return false
}
val equipmentInfo =
GsonUtils.fromJson<EquipmentInfo>(equipmentInfoStr, EquipmentInfo::class.java)
if (equipmentInfo == null) {
Timber.e("解析缓存设备信息失败")
return false
}
try {
parseEquipmentInfo(equipmentInfo)
return true
} catch (e: Exception) {
Timber.e(e)
return false
}
}
// fun checkEquipmentInfo(): Boolean {
// val equipmentInfoStr = SPUtil.getInstance().get(GlobalKey.KEY_EQUIPMENT_INFO, "")
// if (equipmentInfoStr == null) {
// Timber.e("获取缓存设备信息失败")
// return false
// }
// val equipmentInfo =
// GsonUtils.fromJson<EquipmentInfo>(equipmentInfoStr, EquipmentInfo::class.java)
// if (equipmentInfo == null) {
// Timber.e("解析缓存设备信息失败")
// return false
// }
// try {
// parseEquipmentInfo(equipmentInfo)
// return true
// } catch (e: Exception) {
// Timber.e(e)
// return false
// }
// }
}
@@ -1,16 +1,15 @@
package com.sw.dualscreen.viewmodel
import android.content.Context
import android.net.Uri
import androidx.lifecycle.viewModelScope
import com.arcsoft.face.ErrorInfo
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.model.request.UserNutritionParam
import com.sw.dualscreen.model.response.DinnerTypeInfo
import com.sw.dualscreen.model.response.DinnerType
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.model.response.UserFaceModel
import com.sw.dualscreen.model.response.UserNutritionData
import com.sw.dualscreen.objbox.CollectedFoodInfo
import com.sw.dualscreen.utils.SPUtil
import com.sw.plate.App
import com.sw.plate.utils.Base64
@@ -22,10 +21,15 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.RequestBody
import timber.log.Timber
import kotlin.math.atan
import java.io.File
class UserViewModel : BaseViewModel() {
companion object {
private const val TAG = "UserViewModel"
const val PAGE_SIZE = 100
}
private val faceApi: FaceApi = FaceApi()
@@ -44,8 +48,8 @@ class UserViewModel : BaseViewModel() {
/**
* 饭点类型 早餐/午餐/晚餐
*/
private val _dinnerTypeInfo = MutableStateFlow<DinnerTypeInfo?>(null)
val dinnerTypeInfo: StateFlow<DinnerTypeInfo?> = _dinnerTypeInfo
private val _dinnerTypeInfo = MutableStateFlow<DinnerType?>(null)
val dinnerTypeInfo: StateFlow<DinnerType?> = _dinnerTypeInfo
/**
* 人脸加载完成
@@ -59,45 +63,66 @@ class UserViewModel : BaseViewModel() {
* 获取token
*/
fun getEquipmentToken(qrcodeId: String = GlobalData.deviceId) {
Timber.d("getEquipmentToken")
launchWithLoading {
val response = repository.getEquipmentToken(qrcodeId)
if (parseResponse(response)) {
// 缓存token
SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, response.result)
// 首次运行获取人脸数据
if (SPUtil.getInstance().get(GlobalKey.KEY_FIRST_RUN, false) != true) {
getUserFaceCache(index = 0)
}
}
}
// Timber.tag(TAG).d("getEquipmentToken")
// launchWithLoading {
// val response = repository.getEquipmentToken(qrcodeId)
// if (parseResponse(response)) {
// // 缓存token
// SPUtil.getInstance().put(GlobalKey.KEY_TOKEN, response.result)
// // 首次运行获取人脸数据
// if (SPUtil.getInstance().get(GlobalKey.KEY_FIRST_RUN, false) != true) {
// getUserFaceCache(pageNo = 1)
// }
// }
// }
}
/**
* 获取人脸数据
*/
fun getUserFaceCache(index: Int = 0) {
Timber.d("getUserFaceCache index = $index")
fun getUserFaceCache(pageNo: Int = 1, pageSize: Int = PAGE_SIZE) {
var currentPageNo = pageNo
Timber.tag(TAG).d("getUserFaceCache index = $currentPageNo")
launch {
_loadFaceResult.value = false
val response = repository.getUserFaceCache(index)
val response = repository.getUserFaceCache(currentPageNo)
if (parseResponse(response)) {
// 获取成功一次后缓存状态
SPUtil.getInstance().put(GlobalKey.KEY_FIRST_RUN, true)
withContext(Dispatchers.Default) {
val list: List<UserFaceModel> = response.result?.data ?: emptyList()
val list: List<UserFaceModel> = response.result ?: emptyList()
val item = list.firstOrNull { it.userId == "1951105919342936066" }
Timber.d("getUserFaceCache userId = ${item?.userId}")
Timber.tag(TAG).d("getUserFaceCache userId = ${item?.userId}")
val faceEntity = list.map {
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureString))
FaceEntity(it.userId, null, Base64.decode(it.faceFeatureStr))
}
faceApi.updateFaceData(currentPageNo, faceEntity)
if (list.size >= pageSize) {
currentPageNo++
getUserFaceCache(currentPageNo)
} else {
_loadFaceResult.value = true
}
faceApi.updateFaceData(index, faceEntity)
}
val nextPageIndex = response.result?.nextPageIndex ?: -1
if (nextPageIndex > 0) {
getUserFaceCache(nextPageIndex)
} else {
_loadFaceResult.value = true
// val nextPageIndex = response.result?.nextPageIndex ?: -1
// if (nextPageIndex > 0) {
// getUserFaceCache(nextPageIndex)
// } else {
// _loadFaceResult.value = true
// }
}
}
}
fun getCollectedFoodList(pageNo: Int = 1, pageSize: Int = 100, block:(List<CollectedFoodInfo>)-> Unit) {
Timber.tag(TAG).d("getCollectedFoodList index = $pageNo")
launch {
val response = repository.getCollectedFoodList(pageNo)
if (parseResponse(response)) {
withContext(Dispatchers.Default) {
val list: List<CollectedFoodInfo> = response.result ?: emptyList()
block(list)
}
}
}
@@ -107,7 +132,7 @@ class UserViewModel : BaseViewModel() {
* 激活人脸识别引擎
*/
fun activeEngine() {
Timber.d("activeEngine")
Timber.tag(TAG).d("activeEngine")
faceApi.activeEngine(
App.getContext(),
@@ -116,7 +141,7 @@ class UserViewModel : BaseViewModel() {
GlobalData.activeKey,
object : FaceApi.ActiveCallback {
override fun onSuccess(activeCode: Int) {
Timber.d("activeEngine activeCode = $activeCode")
Timber.tag(TAG).d("activeEngine activeCode = $activeCode")
viewModelScope.launch(Dispatchers.Main) {
when (activeCode) {
ErrorInfo.MOK -> {
@@ -142,18 +167,18 @@ class UserViewModel : BaseViewModel() {
})
}
fun getIdentifiedFoodList() {
Timber.d("identifiedFoodList")
launchWithLoading {
val response = repository.getRestInfoFoodsByType(foodName = "")
if (parseResponse(response)) {
_identifiedFoodInfoList.value = response.result ?: emptyList()
}
}
}
// fun getIdentifiedFoodList() {
// Timber.tag(TAG).d("identifiedFoodList")
// launchWithLoading {
// val response = repository.getRestInfoFoodsByType(foodName = "")
// if (parseResponse(response)) {
// _identifiedFoodInfoList.value = response.result ?: emptyList()
// }
// }
// }
fun cleanIdentifiedFoodInfoList() {
Timber.d("cleanIdentifiedFoodInfoList")
Timber.tag(TAG).d("cleanIdentifiedFoodInfoList")
_identifiedFoodInfoList.value = emptyList<FoodInfo>()
}
@@ -161,19 +186,19 @@ class UserViewModel : BaseViewModel() {
* 搜索食物
*/
fun searchByFoodName(foodName: String, action: (List<FoodInfo>) -> Unit = {}) {
Timber.d("searchByFoodName foodName = $foodName")
Timber.tag(TAG).d("searchByFoodName foodName = $foodName")
launchWithLoading {
val response = repository.getRestInfoFoodsByType(foodName = foodName)
if (parseResponse(response)) {
val list = response.result ?: emptyList()
action(list)
_searchFoodInfoList.value = list
_identifiedFoodInfoList.value = response.result ?: emptyList()
}
}
}
fun cleanSearchFoodInfoList() {
Timber.d("cleanSearchFoodInfoList")
Timber.tag(TAG).d("cleanSearchFoodInfoList")
_searchFoodInfoList.value = emptyList<FoodInfo>()
}
@@ -181,7 +206,7 @@ class UserViewModel : BaseViewModel() {
* 获取用户就餐数据
*/
fun getUserNutritionData(userId: String, foodId: String) {
Timber.d("getUserNutritionData userId = ${userId}, foodId = $foodId")
Timber.tag(TAG).d("getUserNutritionData userId = ${userId}, foodId = $foodId")
_nutritionData.value = null
launch {
val response = repository.getUserNutritionData(userId = userId, foodId = foodId)
@@ -192,7 +217,7 @@ class UserViewModel : BaseViewModel() {
}
fun getDinnerType() {
Timber.d("getDinnerType")
Timber.tag(TAG).d("getDinnerType")
_dinnerTypeInfo.value = null
launch {
val response = repository.getDinnerType()
@@ -206,7 +231,7 @@ class UserViewModel : BaseViewModel() {
* 提交就餐数据
*/
fun postUserNutritionData(param: List<UserNutritionParam>) {
Timber.d("postUserNutritionData param = $param")
Timber.tag(TAG).d("postUserNutritionData param = $param")
launch {
val response = repository.postUserNutritionData(param)
if (parseResponse(response)) {
@@ -215,13 +240,13 @@ class UserViewModel : BaseViewModel() {
}
}
fun getFoodInfo(foodName: String, action:(List<FoodInfo>)-> Unit = {}) {
Timber.d("getFoodInfo")
fun getFoodInfo(foodName: String, action: (List<FoodInfo>) -> Unit = {}) {
Timber.tag(TAG).d("getFoodInfo")
launchWithLoading {
val response = repository.getFoodInfo(foodName = foodName)
if (parseResponse(response)) {
val list = response.result ?: emptyList()
_identifiedFoodInfoList2.value = list
_identifiedFoodInfoList.value = list
action(list)
} else {
action(emptyList())
@@ -229,22 +254,22 @@ class UserViewModel : BaseViewModel() {
}
}
fun postImageData(
context: Context,
foodId: String,
foodName: String,
foodVector: String,
uri: Uri
) {
Timber.d("postImageData")
fun uploadCollectFoodPics(files: List<File?>, params: HashMap<String, RequestBody>, callback: (Boolean) -> Unit) {
Timber.tag(TAG).d("uploadCollectFoodPics")
launchWithLoading {
val response = repository.postImageData(
context, foodId = foodId, foodName = foodName, foodVector = foodVector,
uri = uri
)
if (parseResponse(response)) {
Timber.tag("mzf").d("code=${response.code}")
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")
}
}
}
+1 -1
View File
@@ -3,5 +3,5 @@
android:shape="rectangle">
<solid android:color="#FFF5F6F8" />
<corners
android:radius="43dp" />
android:radius="50dp" />
</shape>
+4 -2
View File
@@ -63,7 +63,8 @@
android:text="设备初始化"
android:textColor="@color/white"
android:textSize="30sp"
android:textStyle="bold" />
android:textStyle="bold"
android:visibility="invisible"/>
<TextView
android:id="@+id/activeArcsoft"
@@ -86,6 +87,7 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
tools:src="@mipmap/ic_launcher"/>
tools:src="@mipmap/ic_launcher"
android:visibility="invisible"/>
</RelativeLayout>
</LinearLayout>
+31 -27
View File
@@ -104,37 +104,41 @@
android:layout_marginTop="42dp"
android:layout_weight="1" />
<LinearLayout
android:id="@+id/layout_rescan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="140dp"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<!-- <LinearLayout-->
<!-- android:id="@+id/layoutRescan"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginBottom="140dp"-->
<!-- android:gravity="center"-->
<!-- android:orientation="vertical"-->
<!-- android:visibility="gone">-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="未识别出菜品,请重试或手动搜索"
android:textColor="#FFFF3232"
android:textSize="24sp" />
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="未识别出菜品,请重试或手动搜索"-->
<!-- android:textColor="#FFFF3232"-->
<!-- android:textSize="24sp" />-->
<TextView
android:id="@+id/tv_rescan"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@drawable/bg_border_red"
android:gravity="center"
android:padding="10dp"
android:text="重试"
android:textColor="#FFFF3232"
android:textSize="32sp" />
</LinearLayout>
<!-- <CheckedTextView-->
<!-- android:id="@+id/tv_rescan"-->
<!-- android:layout_width="360dp"-->
<!-- android:layout_height="90dp"-->
<!-- android:layout_marginTop="20dp"-->
<!-- android:background="@drawable/bg_search_food"-->
<!-- android:gravity="center"-->
<!-- android:padding="10dp"-->
<!-- android:text="重试"-->
<!-- android:paddingHorizontal="15dp"-->
<!-- android:textAlignment="center"-->
<!-- android:textColor="@color/color_search_food"-->
<!-- android:textStyle="bold"-->
<!-- android:checked="true"-->
<!-- android:textSize="32sp" />-->
<!-- </LinearLayout>-->
<TextView
android:id="@+id/tv_to_search"
android:id="@+id/tvToSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
+12 -12
View File
@@ -4,31 +4,31 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottom_sheet_layout"
android:layout_width="match_parent"
android:layout_height="900dp"
android:layout_height="1000dp"
android:background="@drawable/bottom_sheet_background"
android:gravity="center_horizontal"
android:orientation="vertical">
<View
android:id="@+id/view_close"
android:layout_width="78dp"
android:layout_height="9dp"
android:layout_marginTop="28dp"
android:layout_width="90dp"
android:layout_height="10dp"
android:layout_marginTop="32dp"
android:background="@drawable/view_shape_point" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="41dp"
android:layout_marginTop="47dp"
android:text="菜品检索"
android:textStyle="bold"
android:textColor="#FF0A1428"
android:textSize="31sp" />
android:textSize="36sp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="87dp"
android:layout_marginTop="56dp"
android:layout_height="100dp"
android:layout_marginTop="64dp"
android:layout_marginHorizontal="28dp"
android:background="@drawable/bg_search"
android:gravity="center_vertical"
@@ -47,14 +47,14 @@
android:inputType="text"
android:textColor="#FF0A1428"
android:textColorHint="#FFB1B1C0"
android:textSize="31sp" />
android:textSize="36sp" />
<ImageView
android:id="@+id/iv_search"
android:layout_width="100dp"
android:layout_height="85dp"
android:layout_height="100dp"
android:paddingStart="25dp"
android:paddingEnd="40dp"
android:paddingEnd="35dp"
android:layout_gravity="end|center_vertical"
android:src="@drawable/ic_search2" />
</FrameLayout>
@@ -64,7 +64,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="500dp"
android:layout_marginTop="42dp"
android:layout_marginTop="48dp"
android:layout_marginBottom="20dp"
android:layout_marginHorizontal="14dp"
app:spanCount="2"
@@ -44,6 +44,7 @@
android:layout_marginEnd="75dp"
android:paddingHorizontal="10dp"
android:src="@drawable/ic_close2"
tools:ignore="ContentDescription" />
tools:ignore="ContentDescription"
android:visibility="gone"/>
</LinearLayout>
@@ -82,11 +82,11 @@
android:layout_height="456dp"
tools:background="@mipmap/ic_launcher"/>
<ImageView
android:id="@+id/ivRecImage"
android:layout_width="match_parent"
android:layout_height="456dp"
tools:background="@mipmap/ic_launcher"/>
<!-- <ImageView-->
<!-- android:id="@+id/ivRecImage"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="456dp"-->
<!-- tools:background="@mipmap/ic_launcher"/>-->
<ImageView
android:layout_width="match_parent"
@@ -228,11 +228,11 @@
</LinearLayout>
<FrameLayout
android:id="@+id/fl_recognize_ir"
android:id="@+id/flRecognizeIr"
android:layout_width="1.3333dp"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:visibility="visible">
android:visibility="gone">
<TextureView
android:id="@+id/dual_camera_texture_preview_ir"