feat(network): 添加新系统API V2支持及相关数据模型

- 引入 ApiServiceV2 接口定义新系统API端点
- 添加 RemoteRepositoryV2 实现新API的数据访问层
- 创建 NetViewModelV2 提供新API的业务逻辑处理
- 定义 v2 包下的数据模型类包括请求响应对象
- 在 ApiClient 中集成新旧两套API服务实例
- 配置API日志拦截器识别新API调用并打上ApiV2标签
- 实现新系统菜品、人脸、订单、会员等完整功能接口
This commit is contained in:
2026-05-28 09:33:05 +08:00
parent c19d84a7a6
commit 6abd2f9b0b
11 changed files with 838 additions and 3 deletions
@@ -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}")
}
}
}
}