增加配置接口;调试人脸识别;验证手机号密码登录和人脸登录功能;

This commit is contained in:
马增飞
2025-12-29 18:41:48 +08:00
parent 6c28260069
commit 17d47a876f
21 changed files with 141 additions and 55 deletions
Generated
+1
View File
@@ -0,0 +1 @@
SmartPlateCabinet
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
@@ -1,5 +1,6 @@
package com.sw.platecabinet
import android.util.Log
import com.sw.plate.App
import com.sw.plate.utils.AppUtil
import com.sw.platecabinet.utils.CrashHandler
@@ -24,9 +25,14 @@ class MyApp : App() {
* 初始化全局数据
*/
private fun initGlobalData() {
var deviceId = AppUtil.getUDID(this)
deviceId = "be154831-3466-3ba2-a2ea-57652c919fed"
Log.d("MyApp", "initialize: deviceId=$deviceId")
GlobalData.deviceId = deviceId
GlobalData.appVersion = AppUtil.getAppVersionCode(this).toString()
GlobalData.globalEquipmentCode = "202501171634"
GlobalData.appBaseUrl = "http://192.168.1.201:14801"
// GlobalData.appBaseUrl = "http://192.168.1.201:14801"
}
}
@@ -200,10 +200,10 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
private fun disableSystemUICompletely() {
Timber.d("disableSystemUICompletely")
// 禁用系统手势(Android 10+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.systemBarsBehavior =
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// window.insetsController?.systemBarsBehavior =
// WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// }
// 全屏+隐藏导航栏(所有版本通用)
@@ -330,10 +330,12 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
*/
open fun handleLoginSuccess(equipmentUserInfo: EquipmentUserInfo, isAdmin: Boolean) {
Timber.d("handleLoginSuccess isAdmin = $isAdmin")
equipmentUserInfo.isIntercept = false
val cardBalance = equipmentUserInfo.cardBalance?:0.toDouble()
val balanceIsNotEnough = cardBalance <= 0.toDouble()
if (balanceIsNotEnough && equipmentUserInfo.showBalanceNotEnoughDialog) {
//提示余额不足弹窗
equipmentUserInfo.isIntercept = true
BalanceNotEnoughDialog(this).show()
return
}
@@ -1,20 +1,22 @@
package com.sw.platecabinet.activity
import android.content.Intent
import android.util.Log
import androidx.activity.viewModels
import com.sw.plate.utils.AppUtil
import com.sw.plate.utils.ToastUtils
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.databinding.ActivityDeviceInitBinding
import com.sw.platecabinet.databinding.ItemTitleTimeBinding
import com.sw.platecabinet.ext.gone
import com.sw.platecabinet.ext.invisible
import com.sw.platecabinet.viewmodel.SettingViewModel
/**
* 设备初始化界面
*/
class DeviceInitActivity : BaseActivity<ActivityDeviceInitBinding>() {
// private val deviceViewModel by viewModels<DeviceViewModel>()
override fun inflateViewBinding(): ActivityDeviceInitBinding {
return ActivityDeviceInitBinding.inflate(layoutInflater)
}
@@ -24,9 +26,6 @@ class DeviceInitActivity : BaseActivity<ActivityDeviceInitBinding>() {
}
override fun initialize() {
var deviceId = AppUtil.getUDID(this)
deviceId = "be154831-3466-3ba2-a2ea-57652c919fed"
GlobalData.deviceId = deviceId
// val isSuccess = deviceViewModel.checkEquipmentInfo()
// if (isSuccess) {
// goLoginActivity()
@@ -41,11 +40,29 @@ class DeviceInitActivity : BaseActivity<ActivityDeviceInitBinding>() {
// binding.btnInit.setOnClickListener {
// deviceViewModel.getDeviceToken()
// }
binding.btnInit.gone()
binding.ivQrCode.invisible()
binding.root.postDelayed({
goLoginActivity()
}, 1000)
// binding.btnInit.gone()
// binding.ivQrCode.invisible()
// binding.root.postDelayed({
// goLoginActivity()
// }, 1000)
showWaitingDialog("加载中……")
viewModel.getDeviceConfig { deviceConfig ->
runOnUiThread {
if (deviceConfig == null) {
hideWaitingDialog()
ToastUtils.showToast("获取设备配置数据失败")
return@runOnUiThread
}
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
binding.root.postDelayed({
hideWaitingDialog()
goLoginActivity()
}, 500)
}
}
// goLoginActivity()
}
override fun registerDataChange() {
@@ -81,7 +81,7 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
openRectInfoDraw = true
recognizeViewModel.setDrawRectInfoTextValue(true)
//viewModel.generateToken()
viewModel.activeEngine()
// viewModel.activeEngine()
viewModel.getUserFaceCache()
binding.llToPwd.setOnClickListener {
@@ -173,7 +173,7 @@ class LoginByFaceActivity : BaseActivity<ActivityLoginFaceBinding>(),
recognizeViewModel.recognizeUserId.observe(this, Observer { userId: String? ->
Timber.i("recognizeUserId observe userId = $userId")
viewModel.getUserInfoById(memberId = userId?.toIntOrNull())
viewModel.getUserInfoById(memberId = userId)
})
recognizeViewModel.drawRectInfoText.observe(this, Observer { info ->
@@ -53,9 +53,9 @@ class LoginByPwdActivity : BaseActivity<ActivityLoginByPwdBinding>() {
super.handleLoginSuccess(equipmentUserInfo, isAdmin)
// val cardBalance = equipmentUserInfo.cardBalance?:0.toDouble()
// val balanceIsNotEnough = cardBalance <= 0.toDouble()
// if (balanceIsNotEnough) {
// return
// }
if (equipmentUserInfo.isIntercept) {
return
}
LoginByFaceActivity.goInitActivity()
finish()
}
@@ -6,11 +6,22 @@ import com.sw.platecabinet.model.response.EquipmentUserInfo
* 错误信息 code == 200 成功
*/
data class ErrorInfo(
val code: Int = 200,
val code: String = "200",
val msg: String = "",
val equipmentUserInfo: EquipmentUserInfo? = null
) {
fun isSuccess(): Boolean {
return code == 200
return code == "00000"
}
}
data class DeviceConfig(
var arcsoftAppId: String? = null,
var arcsoftSdkKey: String? = null,
var arcsoftActiveKey: String? = null
)
data class CodeMsg(
val code: String? = "",
val msg: String? = ""
)
@@ -14,7 +14,7 @@ data class BindParam(
/**
* 设备Id
*/
val equipmentId: Int? = null,
val equipmentId: String? = null,
/**
* 设备编号
*/
@@ -27,7 +27,7 @@ data class BindParam(
*
* 会员Id
*/
val memberId: Int? = null,
val memberId: String? = null,
/**
*餐盘编号
*/
@@ -17,7 +17,7 @@ data class LoginParam(
/**
* 会员信息
*/
val memberId: Int? = null,
val memberId: String? = null,
/**
* 密码
*/
@@ -1,11 +1,12 @@
package com.sw.platecabinet.model.response
data class ApiResponse<T>(
val code: Int,
val success: Boolean? = false,
val code: String,
// val success: Boolean? = false,
val msg: String? = "",
val data: T? = null,
val result: T? = null,
// val result: T? = null,
) {
fun isSuccess(): Boolean = code == 200
// fun isSuccess(): Boolean = code == 200
fun isSuccess(): Boolean = code == "00000"
}
@@ -14,12 +14,12 @@ data class EquipmentUserInfo(
/**
* 主键
*/
val id: Int? = 0,
val id: Long? = 0,
/**
*
* 设备Id
*/
val equipmentId: Int? = 0,
val equipmentId: String? = "",
/**
* 设备编号
*/
@@ -31,7 +31,7 @@ data class EquipmentUserInfo(
/**
* 会员Id
*/
val memberId: Int? = 0,
val memberId: String? = "",
/**
* 餐盘编号
*/
@@ -62,7 +62,8 @@ data class EquipmentUserInfo(
/**
* 用于cardBalance后续拦截判断
*/
var showBalanceNotEnoughDialog: Boolean = false
var showBalanceNotEnoughDialog: Boolean = false,
var isIntercept: Boolean = false
) : Parcelable {
/**
@@ -77,7 +77,7 @@ data class SearchResult(
// val rewardBalance: String? = "",
// @SerializedName("topUpBalance")
// val topUpBalance: String? = ""
val id: Int? = 0,
val id: String? = "",
val name: String? = "",
val phone: String? = "",
) : Parcelable
@@ -1,5 +1,6 @@
package com.sw.platecabinet.network
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.MyApp
import com.sw.platecabinet.network.api.ApiService
import com.sw.platecabinet.network.interceptor.RequestInterceptor
@@ -11,10 +12,10 @@ import timber.log.Timber
import java.util.concurrent.TimeUnit
object ApiClient {
private const val BASE_URL = "https://vip.shuziweidao.com"
private const val DEVICE_BASE_URL = "http://device.shuziweidao.com:8889/"
// private const val BASE_URL = "http://192.168.1.8:9092"
//private const val BASE_URL = "https://vip.shuziweidao.com"
// private const val DEVICE_BASE_URL = "http://device.shuziweidao.com:8889/"
private var DEVICE_BASE_URL = GlobalData.appBaseUrl
// private const val BASE_URL = "http://192.168.1.8:9092"
private const val TIME_OUT = 30L // 超时时间(秒)
val okHttpClient = OkHttpClient.Builder()
@@ -1,6 +1,7 @@
package com.sw.platecabinet.network.api
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.model.DeviceConfig
import com.sw.platecabinet.model.request.BindParam
import com.sw.platecabinet.model.request.EquipmentParam
import com.sw.platecabinet.model.request.LoginParam
@@ -119,7 +120,7 @@ interface ApiService {
@POST
suspend fun plateUnbind(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/sideboard/app/plateUnbind",
@Field("id") id: Int
@Field("id") id: Long
): ApiResponse<Any?>
/**
@@ -167,6 +168,19 @@ interface ApiService {
/**
* 获取人脸增量数据
*/
@POST("/terminal/neglect/common/app/faceFeature/increment/list")
suspend fun getFaceIncrementList(@Body param:Map<String, Long>): ApiResponse<List<UserFaceModel>?>
@POST
suspend fun getFaceIncrementList(
@Url url:String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/faceFeature/increment/list",
@Body param:Map<String, Long>
): ApiResponse<List<UserFaceModel>?>
/**
* 获取设备配置数据
*/
@GET
suspend fun getDeviceConfig(
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/common/app/getYxEquipmentByEquipmentCode"
): ApiResponse<DeviceConfig?>
}
@@ -17,7 +17,7 @@ class RequestInterceptor : Interceptor {
.header("Content-Type", "application/json")
.header("Accept", "application/json")
// .header("Authorization", "Bearer ${getToken()}")
.header("Authorization", getToken())
// .header("Authorization", getToken())
.header("X-Access-Token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjYW50ZWVuSWQiOiJiZTE1NDgzMS0zNDY2LTNiYTItYTJlYS01NzY1MmM5MTlmZWQiLCJ0eXBlIjoiNCIsInVzZXJJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDEifQ.sN40cOC-O5WQFrF4IDUs8fFlkNdUKLbJt_rHyTsgYYM")
.header("X-DEVICE-CODE", GlobalData.deviceId)
.header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d")
@@ -1,6 +1,8 @@
package com.sw.platecabinet.repository
import com.google.gson.JsonParseException
import com.sw.inbound.utils.GsonUtils
import com.sw.platecabinet.model.CodeMsg
import com.sw.platecabinet.model.response.ApiResponse
import retrofit2.HttpException
import timber.log.Timber
@@ -18,31 +20,37 @@ abstract class BaseRepository {
when (e) {
is HttpException -> {
ApiResponse(code = e.code(), msg = e.message())
val jsonData = e.response()?.errorBody()?.string()
val codeMsg = GsonUtils.fromJson(jsonData, CodeMsg::class.java)
if (codeMsg?.msg.isNullOrBlank()) {
ApiResponse(code = "" + e.code(), msg = e.message())
} else {
ApiResponse(code = codeMsg?.code?:"", msg = codeMsg?.msg?:"")
}
}
is SocketTimeoutException -> {
ApiResponse(code = -2, msg = "请求超时: ${e.message}")
ApiResponse(code = "-2", msg = "请求超时: ${e.message}")
}
is ConnectException -> {
ApiResponse(code = -3, msg = "连接失败: ${e.message}")
ApiResponse(code = "-3", msg = "连接失败: ${e.message}")
}
is SSLHandshakeException -> {
ApiResponse(code = -4, msg = "SSL握手失败: ${e.message}")
ApiResponse(code = "-4", msg = "SSL握手失败: ${e.message}")
}
is JsonParseException -> {
ApiResponse(code = -5, msg = "JSON解析错误: ${e.message}")
ApiResponse(code = "-5", msg = "JSON解析错误: ${e.message}")
}
is IOException -> {
ApiResponse(code = -6, msg = "网络IO错误: ${e.message}")
ApiResponse(code = "-6", msg = "网络IO错误: ${e.message}")
}
else -> {
ApiResponse(code = -1, msg = "未知错误: ${e.message ?: "无错误信息"}")
ApiResponse(code = "-1", msg = "未知错误: ${e.message ?: "无错误信息"}")
}
}
}
@@ -1,6 +1,7 @@
package com.sw.platecabinet.repository
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.model.DeviceConfig
import com.sw.platecabinet.model.request.BindParam
import com.sw.platecabinet.model.request.EquipmentParam
import com.sw.platecabinet.model.request.LoginParam
@@ -97,7 +98,7 @@ class RemoteRepository constructor(
return safeApiCall { apiService.plateBind(param = param) }
}
suspend fun plateUnbind(id: Int): ApiResponse<Any?> {
suspend fun plateUnbind(id: Long ): ApiResponse<Any?> {
return safeApiCall { apiService.plateUnbind(id = id) }
}
@@ -139,4 +140,8 @@ class RemoteRepository constructor(
)
}
}
suspend fun getDeviceConfig(): ApiResponse<DeviceConfig?> {
return safeApiCall { apiService.getDeviceConfig() }
}
}
@@ -149,7 +149,7 @@ class SettingViewModel : BaseViewModel() {
// }
// }
fun unbindPlate(id: Int, block:(Pair<Boolean?, ErrorInfo>)-> Unit) {
fun unbindPlate(id: Long, block:(Pair<Boolean?, ErrorInfo>)-> Unit) {
block(null to ErrorInfo())
launchWithLoading {
val response = repository.plateUnbind(id)
@@ -187,7 +187,7 @@ class SettingViewModel : BaseViewModel() {
launchWithLoading {
// val bindParam = BindParam(plateNumber = plateNumber)
val response = repository.findByPlateNumber(plateNumber)
if (response.code == 200) {
if (response.code == "00000") {
_searchUserInfo.value = response.data
} else {
_searchUserInfo.value = EquipmentUserInfo(
@@ -11,6 +11,7 @@ import com.sw.plate.utils.arcface.facedb.entity.FaceEntity
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.GlobalData.globalEquipmentCode
import com.sw.platecabinet.GlobalKey
import com.sw.platecabinet.model.DeviceConfig
import com.sw.platecabinet.model.request.LoginParam
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.model.response.UserFaceModel
@@ -140,7 +141,7 @@ class UserViewModel : BaseViewModel() {
/**
* 通过用户id获取用户信息
*/
fun getUserInfoById(memberId: Int?, action:(EquipmentUserInfo?)->Unit={}) {
fun getUserInfoById(memberId: String?, action:(EquipmentUserInfo?)->Unit={}) {
_currentUserInfo.value = null
launchWithLoading {
val loginParam = LoginParam(memberId = memberId)
@@ -159,5 +160,16 @@ class UserViewModel : BaseViewModel() {
Timber.d("resetUserInfo")
_currentUserInfo.value = null
}
fun getDeviceConfig(block: (DeviceConfig?) -> Unit) {
// Timber.tag(TAG).d("getDeviceConfig")
launch {
val response = repository.getDeviceConfig()
if (parseResponse(response)) {
block(response.data)
} else {
block(null)
}
}
}
}
@@ -28,7 +28,7 @@
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
android:visibility="visible"
android:visibility="invisible"
tools:ignore="HardcodedText" />
<Space
@@ -43,6 +43,7 @@
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="37dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/ic_logo512" />
tools:src="@mipmap/ic_logo512"
android:visibility="invisible"/>
</LinearLayout>