feat(api): 更新API端点并集成人脸数据库导入功能
- 将所有API端点中的/booth路径替换为/serve - 新增searchFood API用于菜品搜索功能 - 新增getCollectVectorPage API用于向量数据分页获取 - 添加FaceDbImporter工具类实现从assets导入人脸数据 - 在初始化活动中集成人脸数据导入功能 - 更新订单创建逻辑适配新的API参数结构 - 重构菜品搜索和订单处理相关API调用 - 添加V2数据模型到V1模型的转换扩展函数 - 更新绑定订单接口以使用新的API端点 - 添加测试模式支持以跳过实际拍照操作
This commit is contained in:
@@ -14,6 +14,7 @@ import com.sw.dualscreen.ext.clickWithDebounce
|
||||
import com.sw.dualscreen.ext.invisible
|
||||
import com.sw.dualscreen.ext.visible
|
||||
import com.sw.dualscreen.objbox.FoodModule
|
||||
import com.sw.dualscreen.utils.FaceDbImporter
|
||||
import com.sw.dualscreen.utils.FoodVectorTool
|
||||
import com.sw.dualscreen.utils.L
|
||||
import com.sw.dualscreen.utils.NetworkUtils
|
||||
@@ -22,7 +23,10 @@ import com.sw.dualscreen.viewmodel.BaseViewModel
|
||||
import com.sw.dualscreen.viewmodel.NetViewModelV2
|
||||
import com.sw.plate.utils.AppUtil
|
||||
import com.sw.plate.utils.ToastUtils
|
||||
import com.sw.plate.utils.arcface.faceserver.FaceServer
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
companion object {
|
||||
@@ -80,6 +84,13 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
// binding.initButton.setOnClickListener {
|
||||
// viewModel.getDeviceToken()
|
||||
// }
|
||||
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
FaceServer.getInstance().clearAllFaces()
|
||||
loadTestDb()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerDataChange() {
|
||||
@@ -189,6 +200,10 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
var arcsoftAppId = "Hkz1rBk6PZXbS8KwKr67K2eZtsz8bRoMHLg64bUdgCZj"
|
||||
var arcsoftSdkKey = "AabXs3sHM8UhhE7oCGf4LVMLrdkGb1nJNksbjjTdVt7k"
|
||||
var arcsoftActiveKey = "085F-118G-Q4GH-B2YH"
|
||||
|
||||
private fun getDeviceConfig() {
|
||||
userViewModel.getDeviceConfig(
|
||||
onSuccess = { deviceConfig ->
|
||||
@@ -200,6 +215,12 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
val settlementMode = if (deviceConfig.payType == 2) 0 else 1
|
||||
SpTool.settlementMode = settlementMode
|
||||
|
||||
// TODO: 临时写死用于测试----------------------------------------
|
||||
deviceConfig.arcsoftAppId = arcsoftAppId
|
||||
deviceConfig.arcsoftSdkKey = arcsoftSdkKey
|
||||
deviceConfig.arcsoftActiveKey = arcsoftActiveKey
|
||||
// TODO: 临时写死用于测试----------------------------------------
|
||||
|
||||
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
|
||||
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
|
||||
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
|
||||
@@ -240,4 +261,27 @@ class InitActivity : BaseActivity<ActivityInitBinding>() {
|
||||
checkNetworkTimer?.cancel()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun loadTestDb() {
|
||||
// 从测试库导入人脸数据
|
||||
FaceDbImporter.importFromAssets(this, object : FaceDbImporter.ImportCallback {
|
||||
public override fun onProgress(current: Int, total: Int) {
|
||||
showWaitingDialog("导入人脸数据 " + current + "/" + total)
|
||||
}
|
||||
|
||||
public override fun onError(message: String?) {
|
||||
hideWaitingDialog()
|
||||
ToastUtils.showToast("离线数据导入失败:" + message)
|
||||
}
|
||||
|
||||
public override fun onComplete() {
|
||||
hideWaitingDialog()
|
||||
ToastUtils.showToast("离线数据导入成功")
|
||||
// 后续流程会自动跳转
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,11 +44,13 @@ import com.sw.dualscreen.ext.load
|
||||
import com.sw.dualscreen.ext.visible
|
||||
import com.sw.dualscreen.model.response.ChargeModeEvent
|
||||
import com.sw.dualscreen.model.response.FoodInfo
|
||||
import com.sw.dualscreen.model.response.FoodOrder
|
||||
import com.sw.dualscreen.model.request.v2.PlaceOrderRequest
|
||||
import com.sw.dualscreen.model.response.PaySuccessEvent
|
||||
import com.sw.dualscreen.model.response.ResetRecognizeEvent
|
||||
import com.sw.dualscreen.model.response.UpdateRefreshEvent
|
||||
import com.sw.dualscreen.model.response.v2.FaceVO
|
||||
import com.sw.dualscreen.model.response.v2.NewFoodInfo
|
||||
import com.sw.dualscreen.model.response.v2.toFoodInfo
|
||||
import com.sw.dualscreen.objbox.Food
|
||||
import com.sw.dualscreen.objbox.FoodModule
|
||||
import com.sw.dualscreen.objbox.FoodModule.IdNameScore
|
||||
@@ -134,6 +136,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
}
|
||||
var isSwitchFood = false
|
||||
|
||||
/**
|
||||
* 用于切换菜品时重置数据
|
||||
*/
|
||||
@@ -145,11 +148,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
//联合支付,切换菜品重新请求接口
|
||||
presentation?.let {
|
||||
val userId = presentation?.currentUserId
|
||||
if(userId.isNullOrBlank()) {
|
||||
if (userId.isNullOrBlank()) {
|
||||
//切换菜品时,用户已离开重新打开识别功能
|
||||
it.pauseCamera()
|
||||
it.step2FaceRecognizing(foodInfo, true)
|
||||
} else{
|
||||
} else {
|
||||
//切换菜品时,用户未离开,重新请求接口
|
||||
it.step3ShowRecognizeResult(userId)
|
||||
}
|
||||
@@ -374,7 +377,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
log("registerDataChange weight 联合支付-余量计量")
|
||||
if (weight <= WEIGHT_RESET_RECOGNIZE) {
|
||||
log("registerDataChange weight 联合支付-余量计量,重量小于${WEIGHT_RESET_RECOGNIZE}g,step1FoodRecognizing")
|
||||
if (presentation?.currentUserId.isNullOrBlank().not() && presentation!!.jointPaymentQueryFinish) {
|
||||
if (presentation?.currentUserId.isNullOrBlank()
|
||||
.not() && presentation!!.jointPaymentQueryFinish
|
||||
) {
|
||||
//联合支付+余量计量,已识别人脸的状态下,从秤上拿餐品后,不再读取数据,等待人脸离开提交订单
|
||||
if (lastWeight != weight) {
|
||||
presentation?.updateWeight(weight)
|
||||
@@ -430,7 +435,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
val mealPickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||
//0-计费,1-不计费
|
||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||
if(mealPickupMode == 0 && chargeMode == 1) {
|
||||
if (mealPickupMode == 0 && chargeMode == 1) {
|
||||
//即放即取+不计费模式,
|
||||
if (presentation?.currentUserId.isNullOrBlank().not()) {
|
||||
//已识别人脸的状态下,从秤上拿餐品后,不再读取数据,等待人脸离开提交订单
|
||||
@@ -571,7 +576,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
}
|
||||
foodRecognizeState = true
|
||||
//查询到菜品信息,同步设置lastWeight=currentWeight
|
||||
lastWeight=currentWeight
|
||||
lastWeight = currentWeight
|
||||
presentation?.updateWeight(currentWeight)
|
||||
|
||||
list.forEach { foodInfo ->
|
||||
@@ -892,63 +897,59 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
val chargeMode = SPUtil.getInstance().get(GlobalKey.KEY_CHARGE_MODE, 0)
|
||||
//0-即放即取,1-余量计量
|
||||
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0) ?: 0
|
||||
// if (pickupMode == 0) {
|
||||
// if (foodWeight <= 5) {
|
||||
// ToastUtils.showToast("餐品重量不足")
|
||||
// return
|
||||
// }
|
||||
// if (eatWeight <= 5) {
|
||||
// ToastUtils.showToast("取餐重量过小")
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
if (eatNum <= 0) {
|
||||
ToastUtils.showToast("您好,当前重量不足一份")
|
||||
notEnoughOneBlock()
|
||||
return
|
||||
}
|
||||
showWaitingDialog("加载中,请稍候……")
|
||||
val order = FoodOrder(
|
||||
val request = PlaceOrderRequest(
|
||||
deviceId = GlobalData.deviceId,
|
||||
foodId = foodInfo.foodId,
|
||||
foodId = foodInfo.foodId.toLong(),
|
||||
foodName = foodInfo.foodName ?: "",
|
||||
foodMaterialId = foodInfo.foodMaterialId ?: "",
|
||||
specId = foodInfo.specId ?: "",
|
||||
foodWeight = foodWeight,
|
||||
eatWeight = eatWeight,
|
||||
//根据specId对应规格重量计算
|
||||
foodMaterialId = foodInfo.foodMaterialId?.toLongOrNull(),
|
||||
specId = foodInfo.specId?.toLongOrNull(),
|
||||
foodWeight = foodWeight.toBigDecimal(),
|
||||
eatWeight = eatWeight.toBigDecimal(),
|
||||
eatNum = eatNum,
|
||||
userId = userId,
|
||||
userId = userId?.toLongOrNull(),
|
||||
notPay = chargeMode != 0,
|
||||
//即放即取-1,称重-2
|
||||
mode = if (pickupMode == 1) 1 else 2,
|
||||
paymentFrom = if (settlementMode == 0) 1 else 2,
|
||||
member = isMember
|
||||
)
|
||||
submitOrder(order, successBlock)
|
||||
submitOrder(request, successBlock)
|
||||
}
|
||||
|
||||
private fun submitOrder(order: FoodOrder, successBlock: () -> Unit) {
|
||||
viewModel.createOrder(order) { orderId ->
|
||||
runOnUiThread {
|
||||
binding.root.postDelayed({
|
||||
hideWaitingDialog()
|
||||
if (orderId.isBlank()) {
|
||||
//ToastUtils.showToast("订单id为空")
|
||||
return@postDelayed
|
||||
}
|
||||
foodOrderId = orderId
|
||||
successBlock()
|
||||
|
||||
if (checkedItem?.isFromSearch == true) {
|
||||
//当前菜名为手动搜索选择,非识别结果,保存向量数据
|
||||
lifecycleScope.launch {
|
||||
saveFoodVector(checkedItem!!)
|
||||
private fun submitOrder(request: PlaceOrderRequest, successBlock: () -> Unit) {
|
||||
viewModel.placeOrder(
|
||||
orderRequest = request,
|
||||
onSuccess = { orderId ->
|
||||
runOnUiThread {
|
||||
binding.root.postDelayed({
|
||||
hideWaitingDialog()
|
||||
if (orderId.isNullOrBlank()) {
|
||||
return@postDelayed
|
||||
}
|
||||
}
|
||||
}, 300)
|
||||
foodOrderId = orderId
|
||||
successBlock()
|
||||
|
||||
if (checkedItem?.isFromSearch == true) {
|
||||
lifecycleScope.launch {
|
||||
saveFoodVector(checkedItem!!)
|
||||
}
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
onFailure = { errorMsg ->
|
||||
runOnUiThread {
|
||||
hideWaitingDialog()
|
||||
ToastUtils.showToast(errorMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun getEatNum(realWeight: Double?, specWeight: Double?): Int {
|
||||
@@ -1147,7 +1148,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
ObjectBox.put(
|
||||
Food(
|
||||
collectId = idList[0],
|
||||
foodId = "$foodId",
|
||||
foodId = foodId.toString(),
|
||||
foodName = foodName,
|
||||
foodVector = imageVector,
|
||||
version = foodModelVersion
|
||||
@@ -1325,14 +1326,17 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
} else {
|
||||
//binding.layoutRescan.visibility = View.GONE
|
||||
showWaitingDialog("正在查询菜品信息,请稍后……")
|
||||
viewModel.getFoodInfo(foodName) { list ->
|
||||
viewModel.getFoodByNames(names = foodName, onSuccess = { list ->
|
||||
runOnUiThread {
|
||||
hideWaitingDialog()
|
||||
log("registerDataChange main,getFoodInfo耗时:${System.currentTimeMillis() - startTime}")
|
||||
startTime = System.currentTimeMillis()
|
||||
updateFoodInfo(list.toMutableList(), scoreList)
|
||||
updateFoodInfo(list.map { it.toFoodInfo() }.toMutableList(), scoreList)
|
||||
}
|
||||
}
|
||||
}, onFailure = { errorMsg ->
|
||||
hideWaitingDialog()
|
||||
ToastUtils.showToast(errorMsg)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -302,11 +302,17 @@ class PayActivity : BaseActivity<ActivityPayBinding>() {
|
||||
//0-即放即取,1-余量计量
|
||||
val pickupMode = SPUtil.getInstance().get(GlobalKey.KEY_PICKUP_MODE, 0)
|
||||
val mode = if (pickupMode == 1) 1 else 2
|
||||
userViewModel.bindOrder(userId, foodOrderId, mode = mode) { bindResult ->
|
||||
runOnUiThread {
|
||||
block(bindResult)
|
||||
}
|
||||
val uid = userId.toLongOrNull() ?: run {
|
||||
runOnUiThread { block(false) }
|
||||
return
|
||||
}
|
||||
userViewModel.bindUserOrder(
|
||||
userId = uid,
|
||||
orderNo = foodOrderId,
|
||||
mode = mode,
|
||||
onSuccess = { runOnUiThread { block(true) } },
|
||||
onFailure = { runOnUiThread { block(false) } }
|
||||
)
|
||||
}
|
||||
|
||||
fun qrCodePay(scanInfo: String) {
|
||||
|
||||
Reference in New Issue
Block a user