feat(network): 添加新系统API V2支持及相关数据模型
- 引入 ApiServiceV2 接口定义新系统API端点 - 添加 RemoteRepositoryV2 实现新API的数据访问层 - 创建 NetViewModelV2 提供新API的业务逻辑处理 - 定义 v2 包下的数据模型类包括请求响应对象 - 在 ApiClient 中集成新旧两套API服务实例 - 配置API日志拦截器识别新API调用并打上ApiV2标签 - 实现新系统菜品、人脸、订单、会员等完整功能接口
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.sw.dualscreen.model.request.v2
|
||||
|
||||
/**
|
||||
* 新系统绑定用户与订单请求参数
|
||||
* 对应接口:/neglect/booth/order/bind-user
|
||||
*/
|
||||
data class BindUserOrderRequest(
|
||||
val userId: Long,
|
||||
val orderNo: String,
|
||||
val mode: Int? = null
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.sw.dualscreen.model.request.v2
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* 新系统开餐下单请求参数
|
||||
* 对应接口:/neglect/booth/order/place
|
||||
*/
|
||||
data class PlaceOrderRequest(
|
||||
val foodId: Long,
|
||||
val foodName: String,
|
||||
val foodWeight: BigDecimal,
|
||||
val eatWeight: BigDecimal,
|
||||
val eatNum: Int,
|
||||
val notPay: Boolean,
|
||||
val mode: Int,
|
||||
val specId: Long?,
|
||||
val userId: Long?,
|
||||
val paymentFrom: Int? = null,
|
||||
val foodMaterialId: Long? = null,
|
||||
val member: Boolean? = null,
|
||||
val remark: String? = null,
|
||||
val deviceId: String? = null
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.sw.dualscreen.model.response.v2
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 新系统采集菜品信息
|
||||
* 对应接口:/neglect/booth/collect/page
|
||||
*/
|
||||
@Parcelize
|
||||
data class CollectedFoodV2(
|
||||
val foodId: String?,
|
||||
val foodName: String?,
|
||||
val version: String?,
|
||||
val foodVector: String?,
|
||||
val picUrls: List<String>?
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.sw.dualscreen.model.response.v2
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 新系统人脸数据 VO
|
||||
* 对应接口:/neglect/booth/face/page 和 /neglect/booth/face/increment
|
||||
*/
|
||||
@Parcelize
|
||||
data class FaceVO(
|
||||
val userFaceId: String?,
|
||||
val userId: String?,
|
||||
val faceFeature: String?,
|
||||
val faceUpdateTimestamp: Long?,
|
||||
val cardNo: String?,
|
||||
val member: Boolean?,
|
||||
val faceDeleted: Boolean?
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.sw.dualscreen.model.response.v2
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* 新系统菜品信息
|
||||
* 对应接口:/neglect/booth/food/by-names
|
||||
*/
|
||||
@Parcelize
|
||||
data class NewFoodInfo(
|
||||
val foodId: Long,
|
||||
val foodName: String?,
|
||||
val calorie: BigDecimal?,
|
||||
val protein: BigDecimal?,
|
||||
val fat: BigDecimal?,
|
||||
val carbohydrate: BigDecimal?,
|
||||
val price: BigDecimal?,
|
||||
val specPrice: BigDecimal?,
|
||||
val specWeight: BigDecimal?,
|
||||
val stapleFood: BigDecimal?,
|
||||
val fruitsVegetables: BigDecimal?,
|
||||
val meatEggs: BigDecimal?,
|
||||
val foodMaterialId: Long?,
|
||||
val specId: Long?,
|
||||
val foodImg: String?,
|
||||
val foodLabel: String?,
|
||||
val vipPrice: BigDecimal? = null,
|
||||
val recommendCalorie: Int = 0,
|
||||
val tablewareStatus: Boolean = false,
|
||||
val tablewareWeight: Int = 0
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.sw.dualscreen.model.response.v2
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* 新系统会员信息
|
||||
* 对应接口:/neglect/booth/member/info 和 /neglect/booth/member/info-by-phone
|
||||
*/
|
||||
@Parcelize
|
||||
data class NewMemberInfo(
|
||||
val id: String?,
|
||||
val phone: String?,
|
||||
val name: String?,
|
||||
val faceUrl: String?,
|
||||
val topUpBalance: BigDecimal?,
|
||||
val rewardBalance: BigDecimal? = BigDecimal.ZERO,
|
||||
val integralBalance: Int?,
|
||||
val member: Boolean?
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.sw.dualscreen.model.response.v2
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* 新系统结算订单数据
|
||||
* 对应接口:/neglect/booth/order/settlement
|
||||
*/
|
||||
@Parcelize
|
||||
data class SettlementOrder(
|
||||
val calorie: BigDecimal?,
|
||||
val incomeSum: BigDecimal?,
|
||||
val discountSum: BigDecimal?,
|
||||
val eatWeightSum: Int?,
|
||||
val orderNo: String?,
|
||||
val list: List<SettlementFoodItem>?
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class SettlementFoodItem(
|
||||
val foodId: String?,
|
||||
val foodName: String?,
|
||||
val specId: String?,
|
||||
val specName: String?,
|
||||
val specWeight: BigDecimal?,
|
||||
val eatNum: Int?,
|
||||
val eatWeight: Int?,
|
||||
val price: BigDecimal?
|
||||
) : Parcelable
|
||||
@@ -3,7 +3,10 @@ package com.sw.dualscreen.network
|
||||
import com.sw.dualscreen.BuildConfig
|
||||
import com.sw.dualscreen.MyApp
|
||||
import com.sw.dualscreen.network.api.ApiService
|
||||
import com.sw.dualscreen.network.api.ApiServiceV2
|
||||
import com.sw.dualscreen.network.interceptor.RequestInterceptor
|
||||
import com.sw.dualscreen.repository.RemoteRepository
|
||||
import com.sw.dualscreen.repository.v2.RemoteRepositoryV2
|
||||
import com.sw.dualscreen.utils.FileUtil
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
@@ -16,7 +19,7 @@ import java.util.concurrent.TimeUnit
|
||||
object ApiClient {
|
||||
private const val BASE_URL = "http://device.shuziweidao.com:8889/"
|
||||
|
||||
private const val TIME_OUT = 30L // 超时时间(秒)
|
||||
private const val TIME_OUT = 30L
|
||||
|
||||
private val okHttpClient = OkHttpClient.Builder()
|
||||
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
|
||||
@@ -27,6 +30,7 @@ object ApiClient {
|
||||
val url = request.url.toString()
|
||||
val tag = if (url.contains("terminal/neglect/common/app/faceFeature/increment/list")) "faceIncrement"
|
||||
else if (url.contains("terminal/neglect/pay/app/turnOrderInfo")) "turnOrderInfo"
|
||||
else if (url.contains("neglect/booth/")) "ApiV2"
|
||||
else "ApiClient"
|
||||
val loggingInterceptor = HttpLoggingInterceptor(logger = {
|
||||
Timber.tag(tag).d("okhttp logger ==>${it}")
|
||||
@@ -47,10 +51,21 @@ object ApiClient {
|
||||
.baseUrl(BASE_URL)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
// .addCallAdapterFactory(CoroutineCallAdapterFactory()) // 协程适配器
|
||||
.build()
|
||||
|
||||
val apiService: ApiService by lazy {
|
||||
retrofit.create(ApiService::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
val apiServiceV2: ApiServiceV2 by lazy {
|
||||
retrofit.create(ApiServiceV2::class.java)
|
||||
}
|
||||
|
||||
val repository: RemoteRepository by lazy {
|
||||
RemoteRepository(apiService)
|
||||
}
|
||||
|
||||
val repositoryV2: RemoteRepositoryV2 by lazy {
|
||||
RemoteRepositoryV2(apiServiceV2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.sw.dualscreen.network.api
|
||||
|
||||
import com.sw.dualscreen.GlobalData
|
||||
import com.sw.dualscreen.model.request.v2.BindUserOrderRequest
|
||||
import com.sw.dualscreen.model.request.v2.PlaceOrderRequest
|
||||
import com.sw.dualscreen.model.response.ApiResponse
|
||||
import com.sw.dualscreen.model.response.DeviceConfig
|
||||
import com.sw.dualscreen.model.response.FoodSearchReq
|
||||
import com.sw.dualscreen.model.response.UserNutrition
|
||||
import com.sw.dualscreen.model.response.v2.CollectedFoodV2
|
||||
import com.sw.dualscreen.model.response.v2.FaceVO
|
||||
import com.sw.dualscreen.model.response.v2.NewFoodInfo
|
||||
import com.sw.dualscreen.model.response.v2.NewMemberInfo
|
||||
import com.sw.dualscreen.model.response.v2.SettlementOrder
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Multipart
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Part
|
||||
import retrofit2.http.PartMap
|
||||
|
||||
/**
|
||||
* 新系统 API 接口服务
|
||||
* 基于 /neglect/booth 模块前缀
|
||||
* 文档版本:2026-05-27
|
||||
*/
|
||||
interface ApiServiceV2 {
|
||||
|
||||
@GET("/neglect/booth/device/config")
|
||||
suspend fun getDeviceConfig(): ApiResponse<DeviceConfig?>
|
||||
|
||||
@POST("/neglect/booth/face/page")
|
||||
suspend fun getFacePage(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<List<FaceVO>?>
|
||||
|
||||
@POST("/neglect/booth/face/increment")
|
||||
suspend fun getFaceIncrement(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<List<FaceVO>?>
|
||||
|
||||
@POST("/neglect/booth/food/by-names")
|
||||
suspend fun getFoodByNames(
|
||||
@Body request: FoodSearchReq
|
||||
): ApiResponse<List<NewFoodInfo>?>
|
||||
|
||||
@POST("/neglect/booth/user/current-food")
|
||||
suspend fun getUserCurrentFood(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<UserNutrition?>
|
||||
|
||||
@POST("/neglect/booth/order/place")
|
||||
suspend fun placeOrder(
|
||||
@Body request: PlaceOrderRequest
|
||||
): ApiResponse<String?>
|
||||
|
||||
@POST("/neglect/booth/order/settlement")
|
||||
suspend fun getSettlementOrders(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<SettlementOrder?>
|
||||
|
||||
@POST("/neglect/booth/member/info")
|
||||
suspend fun getMemberInfo(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<NewMemberInfo?>
|
||||
|
||||
@POST("/neglect/booth/member/info-by-phone")
|
||||
suspend fun getMemberInfoByPhone(
|
||||
@Body request: Map<String, String>
|
||||
): ApiResponse<NewMemberInfo?>
|
||||
|
||||
@POST("/neglect/booth/member/discount")
|
||||
suspend fun getMemberDiscount(
|
||||
@Body request: Map<String, Long>
|
||||
): ApiResponse<String?>
|
||||
|
||||
@POST("/neglect/booth/order/bind-user")
|
||||
suspend fun bindUserOrder(
|
||||
@Body request: BindUserOrderRequest
|
||||
): ApiResponse<Any?>
|
||||
|
||||
@POST("/neglect/booth/collect/page")
|
||||
suspend fun getCollectPage(
|
||||
@Body request: Map<String, Any>
|
||||
): ApiResponse<List<CollectedFoodV2>?>
|
||||
|
||||
@Multipart
|
||||
@POST("/neglect/booth/collect/upload")
|
||||
suspend fun uploadCollect(
|
||||
@PartMap params: HashMap<String, RequestBody>,
|
||||
@Part foodPics: List<MultipartBody.Part>
|
||||
): ApiResponse<List<String>?>
|
||||
|
||||
@POST("/neglect/booth/collect/delete")
|
||||
suspend fun deleteCollect(
|
||||
@Body request: Map<String, Any>
|
||||
): ApiResponse<Any?>
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package com.sw.dualscreen.repository.v2
|
||||
|
||||
import com.sw.dualscreen.model.request.v2.BindUserOrderRequest
|
||||
import com.sw.dualscreen.model.request.v2.PlaceOrderRequest
|
||||
import com.sw.dualscreen.model.response.ApiResponse
|
||||
import com.sw.dualscreen.model.response.DeviceConfig
|
||||
import com.sw.dualscreen.model.response.FoodSearchReq
|
||||
import com.sw.dualscreen.model.response.UserNutrition
|
||||
import com.sw.dualscreen.model.response.v2.CollectedFoodV2
|
||||
import com.sw.dualscreen.model.response.v2.FaceVO
|
||||
import com.sw.dualscreen.model.response.v2.NewFoodInfo
|
||||
import com.sw.dualscreen.model.response.v2.NewMemberInfo
|
||||
import com.sw.dualscreen.model.response.v2.SettlementOrder
|
||||
import com.sw.dualscreen.network.api.ApiServiceV2
|
||||
import com.sw.dualscreen.repository.BaseRepository
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
import java.io.File
|
||||
|
||||
class RemoteRepositoryV2 constructor(
|
||||
private val apiService: ApiServiceV2
|
||||
) : BaseRepository() {
|
||||
|
||||
suspend fun getDeviceConfig(): ApiResponse<DeviceConfig?> {
|
||||
return safeApiCall {
|
||||
apiService.getDeviceConfig()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getFacePage(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = 100L
|
||||
): ApiResponse<List<FaceVO>?> {
|
||||
return safeApiCall {
|
||||
apiService.getFacePage(
|
||||
request = mapOf(
|
||||
"pageNum" to pageNum,
|
||||
"pageSize" to pageSize
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getFaceIncrement(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = 100L,
|
||||
timestamp: Long
|
||||
): ApiResponse<List<FaceVO>?> {
|
||||
return safeApiCall {
|
||||
apiService.getFaceIncrement(
|
||||
request = mapOf(
|
||||
"pageNum" to pageNum,
|
||||
"pageSize" to pageSize,
|
||||
"timestamp" to timestamp
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getFoodByNames(
|
||||
nameList: List<String>,
|
||||
deviceType: Int = 2
|
||||
): ApiResponse<List<NewFoodInfo>?> {
|
||||
return safeApiCall {
|
||||
apiService.getFoodByNames(
|
||||
request = FoodSearchReq(nameList, deviceType)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getUserCurrentFood(
|
||||
userId: Long
|
||||
): ApiResponse<UserNutrition?> {
|
||||
return safeApiCall {
|
||||
apiService.getUserCurrentFood(
|
||||
request = mapOf("id" to userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun placeOrder(
|
||||
orderRequest: PlaceOrderRequest
|
||||
): ApiResponse<String?> {
|
||||
return safeApiCall {
|
||||
apiService.placeOrder(request = orderRequest)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSettlementOrders(
|
||||
userId: Long
|
||||
): ApiResponse<SettlementOrder?> {
|
||||
return safeApiCall {
|
||||
apiService.getSettlementOrders(
|
||||
request = mapOf("id" to userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getMemberInfo(
|
||||
userId: Long
|
||||
): ApiResponse<NewMemberInfo?> {
|
||||
return safeApiCall {
|
||||
apiService.getMemberInfo(
|
||||
request = mapOf("id" to userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getMemberInfoByPhone(
|
||||
phone: String,
|
||||
password: String = ""
|
||||
): ApiResponse<NewMemberInfo?> {
|
||||
return safeApiCall {
|
||||
apiService.getMemberInfoByPhone(
|
||||
request = mapOf(
|
||||
"phone" to phone,
|
||||
"password" to password
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getMemberDiscount(
|
||||
userId: Long
|
||||
): ApiResponse<String?> {
|
||||
return safeApiCall {
|
||||
apiService.getMemberDiscount(
|
||||
request = mapOf("id" to userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bindUserOrder(
|
||||
userId: Long,
|
||||
orderNo: String,
|
||||
mode: Int? = null
|
||||
): ApiResponse<Any?> {
|
||||
return safeApiCall {
|
||||
apiService.bindUserOrder(
|
||||
request = BindUserOrderRequest(userId, orderNo, mode)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCollectPage(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = 100L,
|
||||
foodName: String? = null
|
||||
): ApiResponse<List<CollectedFoodV2>?> {
|
||||
return safeApiCall {
|
||||
val request = mutableMapOf<String, Any>(
|
||||
"pageNum" to pageNum,
|
||||
"pageSize" to pageSize
|
||||
)
|
||||
if (!foodName.isNullOrEmpty()) {
|
||||
request["foodName"] = foodName
|
||||
}
|
||||
apiService.getCollectPage(request = request)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun uploadCollect(
|
||||
foodId: Long,
|
||||
foodName: String,
|
||||
version: String,
|
||||
foodVector: String,
|
||||
fileList: List<File>
|
||||
): ApiResponse<List<String>?> {
|
||||
val params = hashMapOf<String, RequestBody>()
|
||||
params["foodId"] = RequestBody.create(
|
||||
"text/plain".toMediaTypeOrNull(),
|
||||
foodId.toString()
|
||||
)
|
||||
params["foodName"] = RequestBody.create(
|
||||
"text/plain".toMediaTypeOrNull(),
|
||||
foodName
|
||||
)
|
||||
params["version"] = RequestBody.create(
|
||||
"text/plain".toMediaTypeOrNull(),
|
||||
version
|
||||
)
|
||||
params["foodVector"] = RequestBody.create(
|
||||
"text/plain".toMediaTypeOrNull(),
|
||||
foodVector
|
||||
)
|
||||
|
||||
val fileParts = mutableListOf<MultipartBody.Part>()
|
||||
fileList.forEach { file ->
|
||||
val requestFile = file.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val filePart = MultipartBody.Part.createFormData(
|
||||
"foodPics",
|
||||
file.name,
|
||||
requestFile
|
||||
)
|
||||
fileParts.add(filePart)
|
||||
}
|
||||
|
||||
return safeApiCall {
|
||||
apiService.uploadCollect(params = params, foodPics = fileParts)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteCollect(
|
||||
foodId: Long,
|
||||
version: String
|
||||
): ApiResponse<Any?> {
|
||||
return safeApiCall {
|
||||
apiService.deleteCollect(
|
||||
request = mapOf<String, Any>(
|
||||
"foodId" to foodId,
|
||||
"version" to version
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
package com.sw.dualscreen.viewmodel
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.sw.dualscreen.model.request.v2.BindUserOrderRequest
|
||||
import com.sw.dualscreen.model.request.v2.PlaceOrderRequest
|
||||
import com.sw.dualscreen.model.response.FoodSearchReq
|
||||
import com.sw.dualscreen.model.response.UserNutrition
|
||||
import com.sw.dualscreen.model.response.v2.CollectedFoodV2
|
||||
import com.sw.dualscreen.model.response.v2.FaceVO
|
||||
import com.sw.dualscreen.model.response.v2.NewFoodInfo
|
||||
import com.sw.dualscreen.model.response.v2.NewMemberInfo
|
||||
import com.sw.dualscreen.model.response.v2.SettlementOrder
|
||||
import com.sw.dualscreen.network.ApiClient
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class NetViewModelV2 : BaseViewModel() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "NetViewModelV2"
|
||||
const val PAGE_SIZE = 100L
|
||||
}
|
||||
|
||||
fun getDeviceConfig(
|
||||
onSuccess: (config: com.sw.dualscreen.model.response.DeviceConfig?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getDeviceConfig()
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取设备配置失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取设备配置异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFacePage(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = PAGE_SIZE,
|
||||
onSuccess: (list: List<FaceVO>, hasNext: Boolean) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getFacePage(pageNum, pageSize)
|
||||
if (parseResponse(response)) {
|
||||
val list = response.data ?: emptyList()
|
||||
val hasNext = list.size >= pageSize
|
||||
onSuccess(list, hasNext)
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取人脸数据失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取全量人脸数据异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFaceIncrement(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = PAGE_SIZE,
|
||||
timestamp: Long,
|
||||
onSuccess: (list: List<FaceVO>, hasNext: Boolean) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getFaceIncrement(pageNum, pageSize, timestamp)
|
||||
if (parseResponse(response)) {
|
||||
val list = response.data ?: emptyList()
|
||||
val hasNext = list.size >= pageSize
|
||||
onSuccess(list, hasNext)
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取增量人脸数据失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取增量人脸数据异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFoodByNames(
|
||||
nameList: List<String>,
|
||||
deviceType: Int = 2,
|
||||
onSuccess: (list: List<NewFoodInfo>) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getFoodByNames(nameList, deviceType)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data ?: emptyList())
|
||||
} else {
|
||||
onFailure(response.msg ?: "查询菜品失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "查询菜品异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getUserCurrentFood(
|
||||
userId: Long,
|
||||
onSuccess: (nutrition: UserNutrition?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getUserCurrentFood(userId)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取就餐营养数据失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取就餐营养数据异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun placeOrder(
|
||||
orderRequest: PlaceOrderRequest,
|
||||
onSuccess: (orderNo: String?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launchWithLoading {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.placeOrder(orderRequest)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "下单失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "开餐下单异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getSettlementOrders(
|
||||
userId: Long,
|
||||
onSuccess: (order: SettlementOrder?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getSettlementOrders(userId)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "查询结算订单失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "查询结算订单异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMemberInfo(
|
||||
userId: Long,
|
||||
onSuccess: (memberInfo: NewMemberInfo?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getMemberInfo(userId)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取会员信息失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取会员信息异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMemberInfoByPhone(
|
||||
phone: String,
|
||||
password: String = "",
|
||||
onSuccess: (memberInfo: NewMemberInfo?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getMemberInfoByPhone(phone, password)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "查询会员失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "查询会员异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMemberDiscount(
|
||||
userId: Long,
|
||||
onSuccess: (discount: String?) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getMemberDiscount(userId)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data)
|
||||
} else {
|
||||
onFailure(response.msg ?: "查询会员折扣失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "查询会员折扣异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bindUserOrder(
|
||||
userId: Long,
|
||||
orderNo: String,
|
||||
mode: Int? = null,
|
||||
onSuccess: () -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.bindUserOrder(userId, orderNo, mode)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess()
|
||||
} else {
|
||||
onFailure(response.msg ?: "绑定订单失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "绑定订单异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getCollectPage(
|
||||
pageNum: Long = 1L,
|
||||
pageSize: Long = PAGE_SIZE,
|
||||
foodName: String? = null,
|
||||
onSuccess: (list: List<CollectedFoodV2>) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launch {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.getCollectPage(pageNum, pageSize, foodName)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data ?: emptyList())
|
||||
} else {
|
||||
onFailure(response.msg ?: "获取采集列表失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "获取采集列表异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun uploadCollect(
|
||||
foodId: Long,
|
||||
foodName: String,
|
||||
version: String,
|
||||
foodVector: String,
|
||||
fileList: List<okhttp3.MultipartBody.Part>,
|
||||
onSuccess: (picUrls: List<String>) -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launchWithLoading {
|
||||
try {
|
||||
val params = hashMapOf<String, okhttp3.RequestBody>()
|
||||
params["foodId"] = okhttp3.RequestBody.create(
|
||||
okhttp3.MediaType.parse("text/plain"),
|
||||
foodId.toString()
|
||||
)
|
||||
params["foodName"] = okhttp3.RequestBody.create(
|
||||
okhttp3.MediaType.parse("text/plain"),
|
||||
foodName
|
||||
)
|
||||
params["version"] = okhttp3.RequestBody.create(
|
||||
okhttp3.MediaType.parse("text/plain"),
|
||||
version
|
||||
)
|
||||
params["foodVector"] = okhttp3.RequestBody.create(
|
||||
okhttp3.MediaType.parse("text/plain"),
|
||||
foodVector
|
||||
)
|
||||
|
||||
val response = ApiClient.repositoryV2.uploadCollect(
|
||||
foodId, foodName, version, foodVector,
|
||||
fileList.map { it.body().contentType()?.let { ct ->
|
||||
okhttp3.RequestBody.create(ct, (it.body() as okhttp3.ResponseBody).bytes())
|
||||
} ?: it.body() } as List<File>
|
||||
)
|
||||
|
||||
if (parseResponse(response)) {
|
||||
onSuccess(response.data ?: emptyList())
|
||||
} else {
|
||||
onFailure(response.msg ?: "上传采集数据失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "上传采集数据异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteCollect(
|
||||
foodId: Long,
|
||||
version: String,
|
||||
onSuccess: () -> Unit,
|
||||
onFailure: (message: String) -> Unit
|
||||
) {
|
||||
launchWithLoading {
|
||||
try {
|
||||
val response = ApiClient.repositoryV2.deleteCollect(foodId, version)
|
||||
if (parseResponse(response)) {
|
||||
onSuccess()
|
||||
} else {
|
||||
onFailure(response.msg ?: "删除采集菜品失败")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "删除采集菜品异常")
|
||||
onFailure("网络异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user