feat(api): 更新API端点并集成人脸数据库导入功能

- 将所有API端点中的/booth路径替换为/serve
- 新增searchFood API用于菜品搜索功能
- 新增getCollectVectorPage API用于向量数据分页获取
- 添加FaceDbImporter工具类实现从assets导入人脸数据
- 在初始化活动中集成人脸数据导入功能
- 更新订单创建逻辑适配新的API参数结构
- 重构菜品搜索和订单处理相关API调用
- 添加V2数据模型到V1模型的转换扩展函数
- 更新绑定订单接口以使用新的API端点
- 添加测试模式支持以跳过实际拍照操作
This commit is contained in:
2026-05-28 19:57:40 +08:00
parent bf6b2547f3
commit 737baf8486
12 changed files with 517 additions and 261 deletions
@@ -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)
})
}
}