diff --git a/.idea/misc.xml b/.idea/misc.xml index 7e8cd7e..e236b7d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + diff --git a/app/src/main/java/com/sw/platecabinet/MyApp.kt b/app/src/main/java/com/sw/platecabinet/MyApp.kt index bf7bb09..4bbd37f 100644 --- a/app/src/main/java/com/sw/platecabinet/MyApp.kt +++ b/app/src/main/java/com/sw/platecabinet/MyApp.kt @@ -3,16 +3,20 @@ package com.sw.platecabinet import android.util.Log import com.sw.plate.App import com.sw.plate.utils.AppUtil +import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.utils.CrashHandler import timber.log.Timber class MyApp : App() { companion object { const val DEBUG: Boolean = true + var instance: MyApp? = null + var plateList: List? = null } override fun onCreate() { super.onCreate() + instance = this Timber.plant(Timber.DebugTree()) Timber.d("初始化") initGlobalData() diff --git a/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt index 3c4f449..643b29b 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/BaseActivity.kt @@ -25,6 +25,7 @@ import com.sw.plate.utils.arcface.facedb.entity.FaceEntity import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel import com.sw.plate.utils.comn.SerialApi import com.sw.plate.utils.comn.SerialPortManager +import com.sw.platecabinet.MyApp import com.sw.platecabinet.R import com.sw.platecabinet.databinding.ItemTitleTimeBinding import com.sw.platecabinet.dialog.BalanceNotEnoughDialog @@ -33,6 +34,7 @@ import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.model.response.UserFaceModel import com.sw.platecabinet.utils.IntervalExecutor import com.sw.platecabinet.utils.PermissionHelper +import com.sw.platecabinet.utils.PlateUtils import com.sw.platecabinet.utils.SpTool import com.sw.platecabinet.view.CustomLoadingDialog import com.sw.platecabinet.viewmodel.SettingViewModel @@ -106,7 +108,34 @@ abstract class BaseActivity : AppCompatActivity() { * 处理扫描枪数据 */ protected open fun handleScanKeyInfo(scanInfo: String) { - settingViewModel.findByPlateNumber(plateNumber = scanInfo) +// settingViewModel.findByPlateNumber(plateNumber = scanInfo) + var plateNumber = scanInfo + if (scanInfo.length > 6) { + plateNumber = scanInfo.take(6) + } +// ToastUtils.showToast(plateNumber) + var item = MyApp.plateList?.firstOrNull { it.plateNumber == plateNumber } + if (item == null) { + //柜子未关联该餐盘,直接找空位置放入盘子 + item = MyApp.plateList?.firstOrNull { it.plateNumber.isNullOrBlank() } + if (item ==null) { + //柜子已满 + MainActivity.start(context = context, pageType = PageType.PLATE_CABINET_FULL) + return + } + //找到位置,放入餐盘,清除已有id和时间 + item.plateNumber = plateNumber + item.faceId = null + item.updateTime = null + PlateUtils.open(this, item.equipmentBoxCode) + return + } + //放入餐盘,清除已有id和时间 + item.plateNumber = plateNumber + item.faceId = null + item.updateTime = null + PlateUtils.open(this, item.equipmentBoxCode) + SpTool.savePlateData(MyApp.plateList!!) } override fun dispatchKeyEvent(event: KeyEvent): Boolean { @@ -279,7 +308,7 @@ abstract class BaseActivity : AppCompatActivity() { lifecycleScope.launch { viewModel.currentUserInfo.collect { if (it == null) return@collect - it.showBalanceNotEnoughDialog = true +// it.showBalanceNotEnoughDialog = true handleLoginSuccess(it, false) } } @@ -329,57 +358,57 @@ abstract class BaseActivity : AppCompatActivity() { * @param isAdmin true 管理员 执行绑盘此操作 false 用户,提示错误 */ 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 - } - viewModel.resetUserInfo() -// if (equipmentUserInfo.isOtherEquipment()) { -// MainActivity.start( -// context, -// pageType = PageType.PLATE_TIP, -// equipmentUserInfo = equipmentUserInfo, -// isAdmin -// ) +// 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 // } - if (equipmentUserInfo.equipmentBoxCode?.isNotEmpty() == true) { - SerialApi.openPlate( - equipmentUserInfo.equipmentBoxCode!!.toInt(), - object : SerialPortManager.SendCallback { - override fun onSuccess() { - MainActivity.start( - context, - pageType = PageType.PLATE_TIP, - isAdmin = isAdmin - ) - } - - override fun onFail(e: Exception?) { - ToastUtils.showToast("柜门打开失败") - } - }) - } else { - if (isAdmin) { - settingViewModel.getEquipmentList { - loadEquipmentList(it) - } - } else { - Timber.d("无餐盘信息") - MainActivity.start( - context, - pageType = PageType.PLATE_TIP, - equipmentUserInfo = equipmentUserInfo, - isAdmin = isAdmin - ) - } - } +// viewModel.resetUserInfo() +//// if (equipmentUserInfo.isOtherEquipment()) { +//// MainActivity.start( +//// context, +//// pageType = PageType.PLATE_TIP, +//// equipmentUserInfo = equipmentUserInfo, +//// isAdmin +//// ) +//// return +//// } +// if (equipmentUserInfo.equipmentBoxCode?.isNotEmpty() == true) { +// SerialApi.openPlate( +// equipmentUserInfo.equipmentBoxCode!!.toInt(), +// object : SerialPortManager.SendCallback { +// override fun onSuccess() { +// MainActivity.start( +// context, +// pageType = PageType.PLATE_TIP, +// isAdmin = isAdmin +// ) +// } +// +// override fun onFail(e: Exception?) { +// ToastUtils.showToast("柜门打开失败") +// } +// }) +// } else { +// if (isAdmin) { +// settingViewModel.getEquipmentList { +// loadEquipmentList(it) +// } +// } else { +// Timber.d("无餐盘信息") +// MainActivity.start( +// context, +// pageType = PageType.PLATE_TIP, +// equipmentUserInfo = equipmentUserInfo, +// isAdmin = isAdmin +// ) +// } +// } } override fun onDestroy() { @@ -407,7 +436,7 @@ abstract class BaseActivity : AppCompatActivity() { private var faceTimestamp = 0L private fun getFaceIncrementList() { - val timestamp = SpTool.getLastFaceTimestamp() + val timestamp = SpTool.lastFaceTimestamp if (timestamp == 0L) { return } @@ -422,15 +451,15 @@ abstract class BaseActivity : AppCompatActivity() { } updateFaceData(list) if (list.size >= settingViewModel.PAGE_SIZE) { - faceTimestamp = list.last().faceUpdateTimestamp?:0 + faceTimestamp = list.last().faceUpdateTimestamp ?: 0 taskPageNo++ getFaceIncrementList() return@runOnUiThread } if (list.isNotEmpty()) { - faceTimestamp = list.last().faceUpdateTimestamp?:0 + faceTimestamp = list.last().faceUpdateTimestamp ?: 0 } - SpTool.setLastFaceTimestamp(faceTimestamp) + SpTool.lastFaceTimestamp = faceTimestamp } } } diff --git a/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt index f3bd5a4..51e4939 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/DeviceInitActivity.kt @@ -6,10 +6,13 @@ 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.MyApp 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.model.response.EquipmentUserInfo +import com.sw.platecabinet.utils.SpTool import com.sw.platecabinet.viewmodel.SettingViewModel /** @@ -45,6 +48,7 @@ class DeviceInitActivity : BaseActivity() { // binding.root.postDelayed({ // goLoginActivity() // }, 1000) + initPlateList() showWaitingDialog("加载中……") viewModel.getDeviceConfig { deviceConfig -> runOnUiThread { @@ -88,4 +92,23 @@ class DeviceInitActivity : BaseActivity() { } + private fun initPlateList() { +// SpTool.putString(SpTool.PLATE_BOX_DATA, "") + var list = SpTool.getPlateData() + if (list.isNullOrEmpty()) { + list = mutableListOf() + repeat(22) { index -> + list.add( + EquipmentUserInfo( + equipmentBoxCode = "${index + 1}", +// faceId = null, +// plateNumber = if (index == 4) "011075" else null, +// updateTime = null + ) + ) + } + } + MyApp.plateList = list + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt index b66f172..cf66db1 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByFaceActivity.kt @@ -7,13 +7,21 @@ import android.hardware.Camera import android.os.Build import android.os.CountDownTimer import android.util.DisplayMetrics +import android.util.Log import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver import androidx.activity.viewModels import androidx.annotation.RequiresApi +import androidx.fragment.app.viewModels import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope import com.arcsoft.face.ErrorInfo +import com.google.gson.Gson +import com.sw.inbound.utils.DateTimeUtils +import com.sw.inbound.utils.GsonUtils +import com.sw.plate.App +import com.sw.plate.utils.Base64 import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.arcface.ConfigUtil import com.sw.plate.utils.arcface.ErrorCodeUtil @@ -24,17 +32,31 @@ import com.sw.plate.utils.arcface.PreviewConfig import com.sw.plate.utils.arcface.camera.CameraListener import com.sw.plate.utils.arcface.camera.DualCameraHelper import com.sw.plate.utils.arcface.face.constants.LivenessType +import com.sw.plate.utils.arcface.face.model.CompareResult import com.sw.plate.utils.arcface.face.model.FacePreviewInfo import com.sw.plate.utils.arcface.face.model.RecognizeConfiguration -import com.sw.plate.utils.arcface.faceserver.FaceServer +import com.sw.plate.utils.arcface.facedb.FaceDatabase import com.sw.plate.utils.arcface.facedb.entity.FaceEntity +import com.sw.plate.utils.arcface.model.UserFaceInfo import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel +import com.sw.plate.utils.arcface.viewmodel.RecognizeViewModel.REGISTER_STATUS_READY +import com.sw.platecabinet.MyApp import com.sw.platecabinet.R import com.sw.platecabinet.databinding.ActivityLoginFaceBinding import com.sw.platecabinet.databinding.ItemTitleTimeBinding +import com.sw.platecabinet.ext.gone +import com.sw.platecabinet.ext.invisible +import com.sw.platecabinet.ext.visible +import com.sw.platecabinet.model.request.BindParam import com.sw.platecabinet.model.response.EquipmentUserInfo -import com.sw.platecabinet.network.task.TaskManager +import com.sw.platecabinet.utils.IntervalExecutor import com.sw.platecabinet.utils.PermissionHelper +import com.sw.platecabinet.utils.PlateUtils +import com.sw.platecabinet.utils.SpTool +import com.sw.platecabinet.utils.countDownByFlow +import com.sw.platecabinet.viewmodel.SettingViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.runBlocking import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -64,6 +86,7 @@ class LoginByFaceActivity : BaseActivity(), } companion object { + private const val TAG = "LoginByFaceActivity" private var instance: LoginByFaceActivity? = null fun goInitActivity() { @@ -82,17 +105,26 @@ class LoginByFaceActivity : BaseActivity(), recognizeViewModel.setDrawRectInfoTextValue(true) //viewModel.generateToken() // viewModel.activeEngine() - viewModel.getUserFaceCache() - binding.llToPwd.setOnClickListener { - val intent = Intent(this, LoginByPwdActivity::class.java) - startActivity(intent) - } + // TODO: 暂时注释人脸接口数据,测试本地采集 +// viewModel.getUserFaceCache() +// Thread { +// val faceDao = FaceDatabase.getInstance(App.getContext()).faceDao(); +// faceDao.deleteAll() +// faceDao.resetId() +// }.start() - // TODO: 测试请求 - TaskManager.startTask() + +// binding.llToPwd.setOnClickListener { +// val intent = Intent(this, LoginByPwdActivity::class.java) +// startActivity(intent) +// } + +// TaskManager.startTask() EventBus.getDefault().register(this) + + binding.btnCollectFace.setOnClickListener { collectFace() } } private fun checkCameraPermission() { @@ -131,7 +163,11 @@ class LoginByFaceActivity : BaseActivity(), private fun initArcViewModel() { recognizeViewModel.setLiveType(livenessType) - + recognizeViewModel.prepareRegister() + recognizeViewModel.setOnRegisterFinishedCallback { facePreviewInfo, userFaceInfo -> + this.userFaceInfo = userFaceInfo + Log.d(TAG, "initArcViewModel: userFaceInfo == null : ${userFaceInfo == null}") + } recognizeViewModel.ftInitCode.observe(this, Observer { ftInitCode: Int? -> if (ftInitCode != ErrorInfo.MOK) { val error: String? = getString( @@ -171,9 +207,19 @@ class LoginByFaceActivity : BaseActivity(), Timber.i("recognizeNotice observe notice = $notice") }) - recognizeViewModel.recognizeUserId.observe(this, Observer { userId: String? -> - Timber.i("recognizeUserId observe userId = $userId") - viewModel.getUserInfoById(memberId = userId) + recognizeViewModel.recognizeUserId.observe(this, Observer { result: CompareResult? -> + Timber.i("recognizeUserId observe userId = ${result?.faceEntity?.userName}") + currentUserId = result?.faceEntity?.userName +// viewModel.getUserInfoById(memberId = userId) + //ToastUtils.showToast(userId) +// if (!currentUserId.isNullOrBlank()) { +//// ToastUtils.showToast("您已采集过人脸信息") +// return@Observer +// } + if (currentPlateInfo?.faceId == currentUserId) { + return@Observer + } + openPlate(currentUserId) }) recognizeViewModel.drawRectInfoText.observe(this, Observer { info -> @@ -181,6 +227,69 @@ class LoginByFaceActivity : BaseActivity(), }) } +// private val settingViewModel by viewModels() + + /** + * 查询餐盘数据 + */ + private fun getPlateData(block: (List) -> Unit) { + MyApp.plateList?.let { + block(it) + } +// settingViewModel.getEquipmentList { items -> +// block(items) +// } + } + + private var currentPlateInfo: EquipmentUserInfo? = null + + /** + * 打开餐盘柜 + */ + private fun openPlate(userId: String?) { + getPlateData { items -> + Log.d(TAG, "openPlate: ${Gson().toJson(items)}") + var item = items.firstOrNull { it.faceId == userId } + if (item != null) { + //餐盘已取 + ToastUtils.showToast("您已拿过餐盘!") + return@getPlateData + } + // 未查询到当前用户 + item = items.firstOrNull { it.plateNumber.isNullOrEmpty().not() } + if (item == null) { + //暂无餐盘 + ToastUtils.showToast("暂无餐盘,请联系管理人员!") + return@getPlateData + } + // TODO: 待定如何在设置页面显示plateNumber,可以增加字段处理 + item.faceId = userId + item.updateTime = DateTimeUtils.getDateTimeString() + //打开柜子 + PlateUtils.open(this, item.equipmentBoxCode) + + currentPlateInfo = item + MyApp.plateList = items + SpTool.savePlateData(items) + } + } + +// /** +// * 绑定餐盘 +// */ +// private fun bindPlate(item: EquipmentUserInfo) { +// val bindParam = BindParam( +// equipmentId = item.equipmentId, +// equipmentCode = item.equipmentCode, +// equipmentBoxCode = item.equipmentBoxCode, +// faceId = item.faceId, +// plateNumber = item.plateNumber +// ) +// settingViewModel.bindPlate(bindParam) { pair -> +// Log.d(TAG, "openPlate: state:${pair.first},msg:${pair.second.code},${pair.second.msg}") +// } +// } + private fun initArcView() { //在布局结束后才做初始化操作 binding.dualCameraTexturePreviewRgb.getViewTreeObserver().addOnGlobalLayoutListener(this) @@ -198,6 +307,8 @@ class LoginByFaceActivity : BaseActivity(), recognizeViewModel.destroy() EventBus.getDefault().unregister(this) + countDownJob?.cancel() + super.onDestroy() } @@ -320,6 +431,10 @@ class LoginByFaceActivity : BaseActivity(), if (facePreviewInfoList != null && rgbFaceRectTransformer != null) { drawPreviewInfo(facePreviewInfoList) } + if (facePreviewInfoList.isNullOrEmpty()) { + currentPlateInfo = null + currentUserId = null + } recognizeViewModel.clearLeftFace(facePreviewInfoList) } @@ -444,5 +559,100 @@ class LoginByFaceActivity : BaseActivity(), startActivity(intent) } + private fun collectFace() { + //toast("currentUserId=$currentUserId") + if (currentUserId != null) { + ToastUtils.showToast("您已采集过人脸信息") + return + } + currentUserId = null + userFaceInfo = null + recognizeViewModel.updateRegisterStatus(REGISTER_STATUS_READY) + //showWaitingDialog("人脸信息中……") + +// binding.tvFaceTip.gone() + binding.btnCollectFace.invisible() + binding.layoutState.visible() + binding.pbCollectLoading.visible() + binding.tvCollectState.text = "采集中......" + getFaceData { faceData -> + Log.d("LoginByFaceActivity", "faceData: $faceData") + runOnUiThread { + //hideWaitingDialog() + //toast("人脸信息已采集") + binding.pbCollectLoading.gone() + //binding.tvCollectState.text = "采集完成" + userFaceInfo = null + countDown() + } +// sendFaceData(faceData) + saveFaceInfo(faceData) + } + } + + private fun getFaceData(block: (String) -> Unit) { + runBlocking { + job = executor.startIntervalTask(5) { +// if (currentUserId != null && currentUserId!!.isNotBlank()) { +// toast("您已采集过人脸信息") +// return@startIntervalTask +// } + if (userFaceInfo == null) { + return@startIntervalTask + } + val faceData = Base64.encode(userFaceInfo!!.faceFeature!!.featureData) + block(faceData) + job?.cancel() + } + } + + } + + private var userFaceInfo: UserFaceInfo? = null + private var countDownJob: Job? = null + private var job: Job? = null + val executor = IntervalExecutor() + private var currentUserId: String? = null + private fun countDown() { + countDownJob = countDownByFlow( + total = 3, + scope = lifecycleScope, + onStart = { + binding.tvCollectState.text = "采集完成(3s)" + }, + onTick = { seconds -> + binding.tvCollectState.text = "采集完成(${seconds}s)" + }, + onFinish = { + //binding.tvCollectState.text = "采集完成" + currentUserId = null + binding.layoutState.invisible() +// binding.tvFaceTip.visible() + binding.btnCollectFace.visible() + } + ) + } + + private fun saveFaceInfo(faceData: String) { + Thread { + try { + val tempId = "${System.currentTimeMillis()}" + val faceEntity = FaceEntity( + tempId, + null, + Base64.decode(faceData) + ).also { + it.userType = "2" + } + FaceDatabase.getInstance(this).faceDao().insert(faceEntity) + recognizeViewModel.refreshFaceList(); + runOnUiThread { + ToastUtils.showToast("你的人脸信息已采集") + } + } catch (e: Exception) { + e.printStackTrace() + } + }.start() + } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt index a504208..a7e2e94 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/LoginByPwdActivity.kt @@ -1,62 +1,62 @@ -package com.sw.platecabinet.activity - -import android.content.Intent -import com.sw.plate.utils.ToastUtils -import com.sw.platecabinet.databinding.ActivityLoginByPwdBinding -import com.sw.platecabinet.databinding.ItemTitleTimeBinding -import com.sw.platecabinet.dialog.BalanceNotEnoughDialog -import com.sw.platecabinet.model.request.LoginParam -import com.sw.platecabinet.model.response.EquipmentUserInfo -import com.sw.platecabinet.utils.KeyboardUtils - -/** - * 密码登录 - */ -class LoginByPwdActivity : BaseActivity() { - - override fun inflateViewBinding(): ActivityLoginByPwdBinding { - return ActivityLoginByPwdBinding.inflate(layoutInflater) - } - - override fun inflateTitleBinding(): ItemTitleTimeBinding { - return binding.includeHeader - } - - override fun initialize() { - binding.btnLogin.setOnClickListener { - val phone = binding.etPhone.text.toString() - val pwd = binding.etPwd.text.toString() - if (phone.isEmpty() || pwd.isEmpty()) { - ToastUtils.showToast("手机或校验码不能为空") - return@setOnClickListener - } - val loginParam = LoginParam( - //equipmentId = equipmentId, - phone = phone, - password = pwd - ) - viewModel.loginWithPwd(loginParam) - KeyboardUtils.hideKeyboard(this) - } - binding.tvFaceRec.setOnClickListener { - val intent = Intent(this, LoginByFaceActivity::class.java) - startActivity(intent) - } - } - - override fun onResume() { - super.onResume() - viewModel.resetUserInfo() - } - - override fun handleLoginSuccess(equipmentUserInfo: EquipmentUserInfo, isAdmin: Boolean) { - super.handleLoginSuccess(equipmentUserInfo, isAdmin) -// val cardBalance = equipmentUserInfo.cardBalance?:0.toDouble() -// val balanceIsNotEnough = cardBalance <= 0.toDouble() - if (equipmentUserInfo.isIntercept) { - return - } - LoginByFaceActivity.goInitActivity() - finish() - } -} \ No newline at end of file +//package com.sw.platecabinet.activity +// +//import android.content.Intent +//import com.sw.plate.utils.ToastUtils +//import com.sw.platecabinet.databinding.ActivityLoginByPwdBinding +//import com.sw.platecabinet.databinding.ItemTitleTimeBinding +//import com.sw.platecabinet.dialog.BalanceNotEnoughDialog +//import com.sw.platecabinet.model.request.LoginParam +//import com.sw.platecabinet.model.response.EquipmentUserInfo +//import com.sw.platecabinet.utils.KeyboardUtils +// +///** +// * 密码登录 +// */ +//class LoginByPwdActivity : BaseActivity() { +// +// override fun inflateViewBinding(): ActivityLoginByPwdBinding { +// return ActivityLoginByPwdBinding.inflate(layoutInflater) +// } +// +// override fun inflateTitleBinding(): ItemTitleTimeBinding { +// return binding.includeHeader +// } +// +// override fun initialize() { +// binding.btnLogin.setOnClickListener { +// val phone = binding.etPhone.text.toString() +// val pwd = binding.etPwd.text.toString() +// if (phone.isEmpty() || pwd.isEmpty()) { +// ToastUtils.showToast("手机或校验码不能为空") +// return@setOnClickListener +// } +// val loginParam = LoginParam( +// //equipmentId = equipmentId, +// phone = phone, +// password = pwd +// ) +// viewModel.loginWithPwd(loginParam) +// KeyboardUtils.hideKeyboard(this) +// } +// binding.tvFaceRec.setOnClickListener { +// val intent = Intent(this, LoginByFaceActivity::class.java) +// startActivity(intent) +// } +// } +// +// override fun onResume() { +// super.onResume() +// viewModel.resetUserInfo() +// } +// +// override fun handleLoginSuccess(equipmentUserInfo: EquipmentUserInfo, isAdmin: Boolean) { +// super.handleLoginSuccess(equipmentUserInfo, isAdmin) +//// val cardBalance = equipmentUserInfo.cardBalance?:0.toDouble() +//// val balanceIsNotEnough = cardBalance <= 0.toDouble() +// if (equipmentUserInfo.isIntercept) { +// return +// } +// LoginByFaceActivity.goInitActivity() +// finish() +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt index c59af1c..08ebdab 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/MainActivity.kt @@ -2,14 +2,13 @@ package com.sw.platecabinet.activity import android.content.Context import android.content.Intent +import com.sw.platecabinet.MyApp import com.sw.platecabinet.R import com.sw.platecabinet.databinding.ActivityMainBinding import com.sw.platecabinet.databinding.ItemTitleTimeBinding -import com.sw.platecabinet.fragment.BindPlateFragment import com.sw.platecabinet.fragment.PlateCabinetFullFragment import com.sw.platecabinet.fragment.PlateOpenFragment import com.sw.platecabinet.fragment.SettingListFragment -import com.sw.platecabinet.fragment.UnBindPlateFragment import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.utils.FragmentHelper @@ -58,12 +57,15 @@ class MainActivity : BaseActivity() { fragmentHelper = FragmentHelper(supportFragmentManager, R.id.fragment_container) val page = when (pageType) { PageType.SETTING_LIST -> SettingListFragment() - PageType.BIND_PLATE -> BindPlateFragment.newInstance(equipmentUserInfo) +// PageType.BIND_PLATE -> BindPlateFragment.newInstance(equipmentUserInfo) PageType.PLATE_TIP -> PlateOpenFragment.newInstance(equipmentUserInfo, isAdmin) - PageType.UNBIND_PLATE -> UnBindPlateFragment.newInstance(equipmentUserInfo) +// PageType.UNBIND_PLATE -> UnBindPlateFragment.newInstance(equipmentUserInfo) PageType.PLATE_CABINET_FULL -> PlateCabinetFullFragment() + else -> null + } + page?.let { + fragmentHelper.addFragment(it) } - fragmentHelper.addFragment(page) } override fun onLeftDoubleClick() { diff --git a/app/src/main/java/com/sw/platecabinet/activity/UnBindDialogActivity.kt b/app/src/main/java/com/sw/platecabinet/activity/UnBindDialogActivity.kt index 75aa630..10438b9 100644 --- a/app/src/main/java/com/sw/platecabinet/activity/UnBindDialogActivity.kt +++ b/app/src/main/java/com/sw/platecabinet/activity/UnBindDialogActivity.kt @@ -1,57 +1,57 @@ -package com.sw.platecabinet.activity - -import android.graphics.Color -import android.view.Gravity -import android.view.ViewGroup -import androidx.core.graphics.drawable.toDrawable -import androidx.core.view.WindowCompat -import com.sw.platecabinet.GlobalKey -import com.sw.platecabinet.databinding.ActivityUnbindDialogBinding -import com.sw.platecabinet.databinding.ItemTitleTimeBinding -import com.sw.platecabinet.ext.dp -import com.sw.platecabinet.model.response.EquipmentUserInfo - -/** - * 解绑确认弹窗界面 - */ -class UnBindDialogActivity : BaseActivity() { - private var equipmentUserInfo: EquipmentUserInfo? = null - - override fun inflateViewBinding(): ActivityUnbindDialogBinding { - return ActivityUnbindDialogBinding.inflate(layoutInflater) - } - - override fun inflateTitleBinding(): ItemTitleTimeBinding? { - return null - } - - override fun initialize() { - window?.apply { - WindowCompat.setDecorFitsSystemWindows(this, false) - setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) - - attributes = attributes.apply { - y = 314.dp - width = (context.resources.displayMetrics.widthPixels * 0.8).toInt() - height = ViewGroup.LayoutParams.MATCH_PARENT - gravity = Gravity.CENTER - } - } - equipmentUserInfo = - intent.getParcelableExtra(GlobalKey.PARAM_EQUIPMENT_INFO) - if (equipmentUserInfo == null) return - binding.tvTipInfo.text = "即将解除【${equipmentUserInfo!!.name}】的餐盘" - binding.tvCancel.setOnClickListener { - finish() - } - binding.tvConfirm.setOnClickListener { - setResult(RESULT_OK) - finish() - } - } - - override fun finish() { - super.finish() - overridePendingTransition(0, 0) // 确保退出也无动画 - } -} \ No newline at end of file +//package com.sw.platecabinet.activity +// +//import android.graphics.Color +//import android.view.Gravity +//import android.view.ViewGroup +//import androidx.core.graphics.drawable.toDrawable +//import androidx.core.view.WindowCompat +//import com.sw.platecabinet.GlobalKey +//import com.sw.platecabinet.databinding.ActivityUnbindDialogBinding +//import com.sw.platecabinet.databinding.ItemTitleTimeBinding +//import com.sw.platecabinet.ext.dp +//import com.sw.platecabinet.model.response.EquipmentUserInfo +// +///** +// * 解绑确认弹窗界面 +// */ +//class UnBindDialogActivity : BaseActivity() { +// private var equipmentUserInfo: EquipmentUserInfo? = null +// +// override fun inflateViewBinding(): ActivityUnbindDialogBinding { +// return ActivityUnbindDialogBinding.inflate(layoutInflater) +// } +// +// override fun inflateTitleBinding(): ItemTitleTimeBinding? { +// return null +// } +// +// override fun initialize() { +// window?.apply { +// WindowCompat.setDecorFitsSystemWindows(this, false) +// setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) +// +// attributes = attributes.apply { +// y = 314.dp +// width = (context.resources.displayMetrics.widthPixels * 0.8).toInt() +// height = ViewGroup.LayoutParams.MATCH_PARENT +// gravity = Gravity.CENTER +// } +// } +// equipmentUserInfo = +// intent.getParcelableExtra(GlobalKey.PARAM_EQUIPMENT_INFO) +// if (equipmentUserInfo == null) return +// binding.tvTipInfo.text = "即将解除【${equipmentUserInfo!!.name}】的餐盘" +// binding.tvCancel.setOnClickListener { +// finish() +// } +// binding.tvConfirm.setOnClickListener { +// setResult(RESULT_OK) +// finish() +// } +// } +// +// override fun finish() { +// super.finish() +// overridePendingTransition(0, 0) // 确保退出也无动画 +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt index 8a29a2f..581a152 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/BindPlateFragment.kt @@ -1,317 +1,317 @@ -package com.sw.platecabinet.fragment - -import android.annotation.SuppressLint -import android.os.Bundle -import android.text.Editable -import android.text.TextUtils -import android.text.TextWatcher -import android.view.inputmethod.EditorInfo -import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.sw.plate.utils.ToastUtils -import com.sw.plate.utils.comn.SerialApi -import com.sw.plate.utils.comn.SerialPortManager -import com.sw.platecabinet.R -import com.sw.platecabinet.activity.MainActivity -import com.sw.platecabinet.activity.PageType -import com.sw.platecabinet.adapter.GenericItemAdapter -import com.sw.platecabinet.adapter.GridSpacingItemDecoration -import com.sw.platecabinet.adapter.dpToPx -import com.sw.platecabinet.databinding.FragmentBindPlateBinding -import com.sw.platecabinet.databinding.ItemSearchUserInfoBinding -import com.sw.platecabinet.dialog.UserBindRemindDialog -import com.sw.platecabinet.ext.maskName -import com.sw.platecabinet.ext.maskPhone -import com.sw.platecabinet.model.ErrorInfo -import com.sw.platecabinet.model.request.BindParam -import com.sw.platecabinet.model.response.EquipmentUserInfo -import com.sw.platecabinet.model.response.SearchResult -import com.sw.platecabinet.utils.Debouncer -import com.sw.platecabinet.utils.KeyboardUtils -import com.sw.platecabinet.viewmodel.SettingViewModel -import com.sw.platecabinet.viewmodel.UserViewModel -import kotlinx.coroutines.launch -import timber.log.Timber - -/** - * 餐盘柜绑定 - */ -class BindPlateFragment : BaseFragment( - FragmentBindPlateBinding::inflate -) { - private lateinit var adapter: GenericItemAdapter - internal val KEY_ACTION_TYPE = "actionType" - private var info: EquipmentUserInfo? = null - private var checkedItem: SearchResult.Member? = null - private var lastText = "" - private val debouncer = Debouncer(2000) - - private val userViewModel by viewModels() - - companion object { - @JvmStatic - fun newInstance(userInfo: EquipmentUserInfo?) = - BindPlateFragment().apply { - arguments = Bundle().apply { - putParcelable(KEY_ACTION_TYPE, userInfo) - } - } - } - - @SuppressLint("SetTextI18n") - override fun initialize() { - arguments?.let { args -> - info = args.getParcelable(KEY_ACTION_TYPE) - info?.let { - binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" - if (!TextUtils.isEmpty(it.plateNumber)) { -// binding.etCode.text = Editable.Factory.getInstance().newEditable(it.plateNumber) - binding.etCode.apply { - setText(it.plateNumber) - setSelection(length()) - } - } - } - } - initView() - initListener() - } - - private fun initView() { - adapter = createAdapter() - binding.recyclerview.layoutManager = GridLayoutManager(context, 2) - // 添加间距装饰(12dp) - binding.recyclerview.addItemDecoration( - GridSpacingItemDecoration( - spanCount = 2, - spacing = requireContext().dpToPx(6), - includeEdge = false // 包含边缘间距 - ) - ) - binding.recyclerview.adapter = adapter - binding.recyclerview.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - super.onScrolled(recyclerView, dx, dy) - val layoutManager = recyclerView.layoutManager as LinearLayoutManager - val lastVisibleItem = layoutManager.findLastVisibleItemPosition() - val totalItems = layoutManager.itemCount - - if (!viewModel.isLoading && viewModel.canLoadMore - && lastVisibleItem >= totalItems - 3 - ) { - viewModel.getSearchMemberList( - param = lastText, - pageNum = viewModel.currentPage - ) - } - } - }) - (activity as MainActivity).registerKeyEventInfo { -// binding.etCode.text.clear() -// binding.etCode.postDelayed({ -// binding.etCode.text.clear() -// binding.etCode.text = Editable.Factory.getInstance().newEditable(it) - activity?.runOnUiThread { - if (binding.etUserInfo.isFocused) { - return@runOnUiThread - } - binding.etCode.apply { - if (it.length > 6) { - setText(it.substring(0, 6)) - } else { - setText(it) - } - if (length() > 0) { - setSelection(length()) - } - } - binding.etUserInfo.requestFocus() - } -// }, 50) - } - } - - private fun initListener() { - binding.etCode.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged( - s: CharSequence?, - start: Int, - count: Int, - after: Int - ) { - Timber.d("beforeTextChanged s = ${s.toString()}, start = $start, count = $count, after = $after") - } - - override fun onTextChanged( - s: CharSequence?, - start: Int, - before: Int, - count: Int - ) { - Timber.d("onTextChanged s = ${s.toString()}, start = $start, count = $count, before = $before") - } - - override fun afterTextChanged(s: Editable?) { - Timber.d("afterTextChanged s = ${s.toString()}") - } - }) - binding.etUserInfo.setOnEditorActionListener { _, actionId, keyEvent -> - if (actionId == EditorInfo.IME_ACTION_SEARCH) { - val currentText = binding.etUserInfo.text.toString() - val containsNewlines = currentText.contains('\n') || currentText.contains('\r') - if (containsNewlines) { - Timber.d("非用户主动搜索") - true - } - debouncer.debounce { - // 执行搜索操作 - viewModel.getSearchMemberList(param = currentText, pageNum = 1) - // 隐藏键盘 - KeyboardUtils.hideKeyboard(requireActivity()) - } - true // 表示已处理该事件 - } else { - false // 未处理其他动作 - } - } - binding.ivSearch.setOnClickListener { - debouncer.debounce { - // 执行搜索操作 - viewModel.getSearchMemberList( - param = binding.etUserInfo.text.toString(), - pageNum = 1 - ) - // 隐藏键盘 - KeyboardUtils.hideKeyboard(requireActivity()) - } - } - binding.llBind.setOnClickListener { - if (equipmentBoxCode.isNullOrBlank().not()) { - showBindDialog() - return@setOnClickListener - } - if (info == null || info!!.equipmentCode?.isEmpty() == true || info!!.equipmentBoxCode?.isEmpty() == true) { - ToastUtils.showToast("传入的设备信息异常") - return@setOnClickListener - } - val plateNumber = binding.etCode.text.toString() - if (plateNumber.isEmpty()) { - ToastUtils.showToast("请输入餐盘号") - return@setOnClickListener - } - if (checkedItem == null) { - ToastUtils.showToast("请选择要绑定的会员") - return@setOnClickListener - } - if (checkedItem!!.id == null) { - ToastUtils.showToast("选中的会员信息异常") - return@setOnClickListener - } - val bindParam = BindParam( - equipmentId = info?.equipmentId, - equipmentCode = info?.equipmentCode, - equipmentBoxCode = info?.equipmentBoxCode, - faceId = checkedItem?.faceId, - plateNumber = plateNumber - ) - viewModel.bindPlate(bindParam) { pair -> - updateBindState(pair) - } - KeyboardUtils.hideKeyboard(requireActivity()) - } - binding.tvBack.setOnClickListener { activity?.finish() } - } - - /** - * 监听数据变化 - */ - override fun registerDataChange() { - super.registerDataChange() - lifecycleScope.launch { - viewModel.searchMemberList.collect { - adapter.updateData(it) - } - } -// lifecycleScope.launch { -// viewModel.bindStateChange.collect { -// updateBindState(it) +//package com.sw.platecabinet.fragment +// +//import android.annotation.SuppressLint +//import android.os.Bundle +//import android.text.Editable +//import android.text.TextUtils +//import android.text.TextWatcher +//import android.view.inputmethod.EditorInfo +//import androidx.fragment.app.viewModels +//import androidx.lifecycle.lifecycleScope +//import androidx.recyclerview.widget.GridLayoutManager +//import androidx.recyclerview.widget.LinearLayoutManager +//import androidx.recyclerview.widget.RecyclerView +//import com.sw.plate.utils.ToastUtils +//import com.sw.plate.utils.comn.SerialApi +//import com.sw.plate.utils.comn.SerialPortManager +//import com.sw.platecabinet.R +//import com.sw.platecabinet.activity.MainActivity +//import com.sw.platecabinet.activity.PageType +//import com.sw.platecabinet.adapter.GenericItemAdapter +//import com.sw.platecabinet.adapter.GridSpacingItemDecoration +//import com.sw.platecabinet.adapter.dpToPx +//import com.sw.platecabinet.databinding.FragmentBindPlateBinding +//import com.sw.platecabinet.databinding.ItemSearchUserInfoBinding +//import com.sw.platecabinet.dialog.UserBindRemindDialog +//import com.sw.platecabinet.ext.maskName +//import com.sw.platecabinet.ext.maskPhone +//import com.sw.platecabinet.model.ErrorInfo +//import com.sw.platecabinet.model.request.BindParam +//import com.sw.platecabinet.model.response.EquipmentUserInfo +//import com.sw.platecabinet.model.response.SearchResult +//import com.sw.platecabinet.utils.Debouncer +//import com.sw.platecabinet.utils.KeyboardUtils +//import com.sw.platecabinet.viewmodel.SettingViewModel +//import com.sw.platecabinet.viewmodel.UserViewModel +//import kotlinx.coroutines.launch +//import timber.log.Timber +// +///** +// * 餐盘柜绑定 +// */ +//class BindPlateFragment : BaseFragment( +// FragmentBindPlateBinding::inflate +//) { +// private lateinit var adapter: GenericItemAdapter +// internal val KEY_ACTION_TYPE = "actionType" +// private var info: EquipmentUserInfo? = null +// private var checkedItem: SearchResult.Member? = null +// private var lastText = "" +// private val debouncer = Debouncer(2000) +// +// private val userViewModel by viewModels() +// +// companion object { +// @JvmStatic +// fun newInstance(userInfo: EquipmentUserInfo?) = +// BindPlateFragment().apply { +// arguments = Bundle().apply { +// putParcelable(KEY_ACTION_TYPE, userInfo) +// } +// } +// } +// +// @SuppressLint("SetTextI18n") +// override fun initialize() { +// arguments?.let { args -> +// info = args.getParcelable(KEY_ACTION_TYPE) +// info?.let { +// binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" +// if (!TextUtils.isEmpty(it.plateNumber)) { +//// binding.etCode.text = Editable.Factory.getInstance().newEditable(it.plateNumber) +// binding.etCode.apply { +// setText(it.plateNumber) +// setSelection(length()) +// } +// } // } // } - } - - private fun createAdapter(): GenericItemAdapter { - return GenericItemAdapter( - items = emptyList(), - bindingInflater = ItemSearchUserInfoBinding::inflate, - bindCallback = { item, position -> - this.tvName.text = item.name.maskName() - this.tvPhone.text = item.phone.maskPhone() - if (item.id != checkedItem?.id) { - this.llRoot.setBackgroundResource(R.drawable.grid_item_bind) - } else { - this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind) - } - - this.llRoot.setOnClickListener { - Timber.d("itemClick ${item.name}, position = $position") - checkedItem = item - adapter.notifyDataSetChanged() - //TODO 调用接口查询用户是否已绑盘 - this@BindPlateFragment.equipmentBoxCode = null - (activity as? MainActivity)?.showWaitingDialog("查询中,请稍后……") - userViewModel.getUserInfoById(memberId = item.faceId) { - (activity as? MainActivity)?.hideWaitingDialog() - this@BindPlateFragment.equipmentBoxCode = it?.equipmentBoxCode - } - } - } - ) - } - - private var equipmentBoxCode:String? = null - - private fun showBindDialog() { - UserBindRemindDialog( - activity = requireActivity(), - content = "您已绑定编号为${equipmentBoxCode}的柜子,请解绑后重试" - ) - .show() - } - - private fun updateBindState(pair: Pair){ - if (pair.first == null) return // 解绑状态过滤 - val errorInfo = pair.second - if (errorInfo.isSuccess()) { - if (errorInfo.equipmentUserInfo == null) { - ToastUtils.showToast("数据异常") - return - } -// if (errorInfo.equipmentUserInfo.isOtherEquipment()) { -// MainActivity.start( -// requireContext(), -// pageType = PageType.PLATE_TIP, -// equipmentUserInfo = errorInfo.equipmentUserInfo, -// isAdmin = true -// ) -// } else { - SerialApi.openPlate( - errorInfo.equipmentUserInfo.equipmentBoxCode!!.toInt(), - object : SerialPortManager.SendCallback { - override fun onSuccess() { - ToastUtils.showToast("绑定成功") - activity?.finish() - } - - override fun onFail(e: Exception?) { - ToastUtils.showToast("绑定失败") - } - }) +// initView() +// initListener() +// } +// +// private fun initView() { +// adapter = createAdapter() +// binding.recyclerview.layoutManager = GridLayoutManager(context, 2) +// // 添加间距装饰(12dp) +// binding.recyclerview.addItemDecoration( +// GridSpacingItemDecoration( +// spanCount = 2, +// spacing = requireContext().dpToPx(6), +// includeEdge = false // 包含边缘间距 +// ) +// ) +// binding.recyclerview.adapter = adapter +// binding.recyclerview.addOnScrollListener(object : RecyclerView.OnScrollListener() { +// override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { +// super.onScrolled(recyclerView, dx, dy) +// val layoutManager = recyclerView.layoutManager as LinearLayoutManager +// val lastVisibleItem = layoutManager.findLastVisibleItemPosition() +// val totalItems = layoutManager.itemCount +// +// if (!viewModel.isLoading && viewModel.canLoadMore +// && lastVisibleItem >= totalItems - 3 +// ) { +// viewModel.getSearchMemberList( +// param = lastText, +// pageNum = viewModel.currentPage +// ) +// } // } - } else { - ToastUtils.showToast(errorInfo.msg) - } - } -} \ No newline at end of file +// }) +// (activity as MainActivity).registerKeyEventInfo { +//// binding.etCode.text.clear() +//// binding.etCode.postDelayed({ +//// binding.etCode.text.clear() +//// binding.etCode.text = Editable.Factory.getInstance().newEditable(it) +// activity?.runOnUiThread { +// if (binding.etUserInfo.isFocused) { +// return@runOnUiThread +// } +// binding.etCode.apply { +// if (it.length > 6) { +// setText(it.substring(0, 6)) +// } else { +// setText(it) +// } +// if (length() > 0) { +// setSelection(length()) +// } +// } +// binding.etUserInfo.requestFocus() +// } +//// }, 50) +// } +// } +// +// private fun initListener() { +// binding.etCode.addTextChangedListener(object : TextWatcher { +// override fun beforeTextChanged( +// s: CharSequence?, +// start: Int, +// count: Int, +// after: Int +// ) { +// Timber.d("beforeTextChanged s = ${s.toString()}, start = $start, count = $count, after = $after") +// } +// +// override fun onTextChanged( +// s: CharSequence?, +// start: Int, +// before: Int, +// count: Int +// ) { +// Timber.d("onTextChanged s = ${s.toString()}, start = $start, count = $count, before = $before") +// } +// +// override fun afterTextChanged(s: Editable?) { +// Timber.d("afterTextChanged s = ${s.toString()}") +// } +// }) +// binding.etUserInfo.setOnEditorActionListener { _, actionId, keyEvent -> +// if (actionId == EditorInfo.IME_ACTION_SEARCH) { +// val currentText = binding.etUserInfo.text.toString() +// val containsNewlines = currentText.contains('\n') || currentText.contains('\r') +// if (containsNewlines) { +// Timber.d("非用户主动搜索") +// true +// } +// debouncer.debounce { +// // 执行搜索操作 +// viewModel.getSearchMemberList(param = currentText, pageNum = 1) +// // 隐藏键盘 +// KeyboardUtils.hideKeyboard(requireActivity()) +// } +// true // 表示已处理该事件 +// } else { +// false // 未处理其他动作 +// } +// } +// binding.ivSearch.setOnClickListener { +// debouncer.debounce { +// // 执行搜索操作 +// viewModel.getSearchMemberList( +// param = binding.etUserInfo.text.toString(), +// pageNum = 1 +// ) +// // 隐藏键盘 +// KeyboardUtils.hideKeyboard(requireActivity()) +// } +// } +// binding.llBind.setOnClickListener { +// if (equipmentBoxCode.isNullOrBlank().not()) { +// showBindDialog() +// return@setOnClickListener +// } +// if (info == null || info!!.equipmentCode?.isEmpty() == true || info!!.equipmentBoxCode?.isEmpty() == true) { +// ToastUtils.showToast("传入的设备信息异常") +// return@setOnClickListener +// } +// val plateNumber = binding.etCode.text.toString() +// if (plateNumber.isEmpty()) { +// ToastUtils.showToast("请输入餐盘号") +// return@setOnClickListener +// } +// if (checkedItem == null) { +// ToastUtils.showToast("请选择要绑定的会员") +// return@setOnClickListener +// } +// if (checkedItem!!.id == null) { +// ToastUtils.showToast("选中的会员信息异常") +// return@setOnClickListener +// } +// val bindParam = BindParam( +// equipmentId = info?.equipmentId, +// equipmentCode = info?.equipmentCode, +// equipmentBoxCode = info?.equipmentBoxCode, +// faceId = checkedItem?.faceId, +// plateNumber = plateNumber +// ) +// viewModel.bindPlate(bindParam) { pair -> +// updateBindState(pair) +// } +// KeyboardUtils.hideKeyboard(requireActivity()) +// } +// binding.tvBack.setOnClickListener { activity?.finish() } +// } +// +// /** +// * 监听数据变化 +// */ +// override fun registerDataChange() { +// super.registerDataChange() +// lifecycleScope.launch { +// viewModel.searchMemberList.collect { +// adapter.updateData(it) +// } +// } +//// lifecycleScope.launch { +//// viewModel.bindStateChange.collect { +//// updateBindState(it) +//// } +//// } +// } +// +// private fun createAdapter(): GenericItemAdapter { +// return GenericItemAdapter( +// items = emptyList(), +// bindingInflater = ItemSearchUserInfoBinding::inflate, +// bindCallback = { item, position -> +// this.tvName.text = item.name.maskName() +// this.tvPhone.text = item.phone.maskPhone() +// if (item.id != checkedItem?.id) { +// this.llRoot.setBackgroundResource(R.drawable.grid_item_bind) +// } else { +// this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind) +// } +// +// this.llRoot.setOnClickListener { +// Timber.d("itemClick ${item.name}, position = $position") +// checkedItem = item +// adapter.notifyDataSetChanged() +// //TODO 调用接口查询用户是否已绑盘 +// this@BindPlateFragment.equipmentBoxCode = null +// (activity as? MainActivity)?.showWaitingDialog("查询中,请稍后……") +// userViewModel.getUserInfoById(memberId = item.faceId) { +// (activity as? MainActivity)?.hideWaitingDialog() +// this@BindPlateFragment.equipmentBoxCode = it?.equipmentBoxCode +// } +// } +// } +// ) +// } +// +// private var equipmentBoxCode:String? = null +// +// private fun showBindDialog() { +// UserBindRemindDialog( +// activity = requireActivity(), +// content = "您已绑定编号为${equipmentBoxCode}的柜子,请解绑后重试" +// ) +// .show() +// } +// +// private fun updateBindState(pair: Pair){ +// if (pair.first == null) return // 解绑状态过滤 +// val errorInfo = pair.second +// if (errorInfo.isSuccess()) { +// if (errorInfo.equipmentUserInfo == null) { +// ToastUtils.showToast("数据异常") +// return +// } +//// if (errorInfo.equipmentUserInfo.isOtherEquipment()) { +//// MainActivity.start( +//// requireContext(), +//// pageType = PageType.PLATE_TIP, +//// equipmentUserInfo = errorInfo.equipmentUserInfo, +//// isAdmin = true +//// ) +//// } else { +// SerialApi.openPlate( +// errorInfo.equipmentUserInfo.equipmentBoxCode!!.toInt(), +// object : SerialPortManager.SendCallback { +// override fun onSuccess() { +// ToastUtils.showToast("绑定成功") +// activity?.finish() +// } +// +// override fun onFail(e: Exception?) { +// ToastUtils.showToast("绑定失败") +// } +// }) +//// } +// } else { +// ToastUtils.showToast(errorInfo.msg) +// } +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/fragment/PlateOpenFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/PlateOpenFragment.kt index 1aa3c1d..2a2a9ce 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/PlateOpenFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/PlateOpenFragment.kt @@ -41,12 +41,14 @@ class PlateOpenFragment : binding.tvTitle.text = "暂无餐盘信息" binding.tvSubTitle.text = "请联系管理员" binding.tvTitle.setTextColor(requireContext().getColor(R.color.tip_title_fail)) - } else if (it.isOtherEquipment()) { - binding.ivType.setImageResource(R.drawable.ic_tip_warn) - binding.tvTitle.text = "暂无餐盘信息" - binding.tvSubTitle.text = "您的餐盘绑定在${it.equipmentName ?: " "}号柜上" - binding.tvTitle.setTextColor(requireContext().getColor(R.color.tip_title_fail)) - } else { + } +// else if (it.isOtherEquipment()) { +// binding.ivType.setImageResource(R.drawable.ic_tip_warn) +// binding.tvTitle.text = "暂无餐盘信息" +// binding.tvSubTitle.text = "您的餐盘绑定在${it.equipmentName ?: " "}号柜上" +// binding.tvTitle.setTextColor(requireContext().getColor(R.color.tip_title_fail)) +// } + else { binding.ivType.setImageResource(R.drawable.ic_tip_success) binding.tvTitle.text = "柜门开启" binding.tvSubTitle.text = "餐盘取出后请关闭柜门" diff --git a/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt index f55994c..b8ace5b 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/SettingListFragment.kt @@ -11,7 +11,9 @@ import com.sw.plate.utils.ToastUtils import com.sw.plate.utils.comn.SerialApi import com.sw.plate.utils.comn.SerialPortManager import com.sw.platecabinet.GlobalData +import com.sw.platecabinet.MyApp import com.sw.platecabinet.R +import com.sw.platecabinet.activity.BaseActivity import com.sw.platecabinet.activity.MainActivity import com.sw.platecabinet.activity.PageType import com.sw.platecabinet.adapter.GenericItemAdapter @@ -24,6 +26,8 @@ import com.sw.platecabinet.ext.formatNumber import com.sw.platecabinet.ext.maskName import com.sw.platecabinet.model.response.EquipmentUserInfo import com.sw.platecabinet.utils.ListArrangementUtil +import com.sw.platecabinet.utils.PlateUtils +import com.sw.platecabinet.utils.SpTool import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -80,11 +84,23 @@ class SettingListFragment : override fun onResume() { super.onResume() - viewModel.getEquipmentList{ +// viewModel.getEquipmentList{ +// updateAdapter(it) +// } + MyApp.plateList?.let { updateAdapter(it) } } +// private fun getPlateData(block: (List) -> Unit) { +// MyApp.plateList?.let { +// block(it) +// } +//// viewModel.getEquipmentList { items -> +//// block(items) +//// } +// } + private fun createItemAdapter(): GenericItemAdapter { return GenericItemAdapter( items = emptyList(), @@ -110,7 +126,7 @@ class SettingListFragment : item: EquipmentUserInfo, position: Int ) { - if (item.isPlaceholder() == true) { + if (item.isPlaceholder()) { this.llRoot.isVisible = false return } @@ -133,7 +149,9 @@ class SettingListFragment : this.llBindInfo.visibility = View.VISIBLE this.tvUnbind.visibility = View.GONE - this.tvName.text = item.name.maskName() +// this.tvName.text = item.name.maskName() + this.tvName.text = item.plateNumber + this.tvLastTime.text = DateTimeUtils.getTimeAgo(date) } else { this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind) @@ -143,45 +161,25 @@ class SettingListFragment : this.llBindInfo.visibility = View.GONE this.tvUnbind.visibility = View.VISIBLE } - this.llRoot.setOnClickListener { - Timber.d("itemClick llRoot ${item.name}, position = $position") - if (item.isBound()) { - MainActivity.start( - requireContext(), - pageType = PageType.UNBIND_PLATE, - equipmentUserInfo = item - ) - } else { - MainActivity.start( - requireContext(), - pageType = PageType.BIND_PLATE, - equipmentUserInfo = item - ) - } - } +// this.llRoot.setOnClickListener { +//// Timber.d("itemClick llRoot ${item.name}, position = $position") +// if (item.isBound()) { +// MainActivity.start( +// requireContext(), +// pageType = PageType.UNBIND_PLATE, +// equipmentUserInfo = item +// ) +// } else { +// MainActivity.start( +// requireContext(), +// pageType = PageType.BIND_PLATE, +// equipmentUserInfo = item +// ) +// } +// } this.llOpen.setOnClickListener { - Timber.d("itemClick llOpen equipmentBoxCode = ${item.equipmentBoxCode}") - val equipmentBoxCode: Int = item.equipmentBoxCode?.toInt() ?: -1 - if (equipmentBoxCode < 0) { - ToastUtils.showToast("餐盘柜编号错误") - return@setOnClickListener - } - showWaitingDialog("请稍等") - SerialApi.openPlate(equipmentBoxCode, object : SerialPortManager.SendCallback { - override fun onSuccess() { - hideWaitingDialog() - MainActivity.start( - requireContext(), - pageType = PageType.PLATE_TIP, - isAdmin = true - ) - } - - override fun onFail(e: Exception?) { - hideWaitingDialog() - ToastUtils.showToast("柜门打开失败") - } - }) +// item.faceId = null + PlateUtils.open(requireActivity(), item.equipmentBoxCode) } } diff --git a/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt b/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt index dad507b..8c805cf 100644 --- a/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt +++ b/app/src/main/java/com/sw/platecabinet/fragment/UnBindPlateFragment.kt @@ -1,95 +1,95 @@ -package com.sw.platecabinet.fragment - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.activity.result.contract.ActivityResultContracts -import androidx.lifecycle.lifecycleScope -import com.sw.inbound.utils.DateTimeUtils -import com.sw.plate.utils.ToastUtils -import com.sw.platecabinet.GlobalKey -import com.sw.platecabinet.activity.UnBindDialogActivity -import com.sw.platecabinet.databinding.FragmentUnbindPlateBinding -import com.sw.platecabinet.ext.maskName -import com.sw.platecabinet.ext.maskPhone -import com.sw.platecabinet.model.ErrorInfo -import com.sw.platecabinet.model.response.EquipmentUserInfo -import kotlinx.coroutines.launch - -/** - * 餐盘柜绑定 - */ -class UnBindPlateFragment private constructor() : BaseFragment( - FragmentUnbindPlateBinding::inflate -) { - internal val ARG_PARAM1 = "param1" - private var info: EquipmentUserInfo? = null - - companion object { - @JvmStatic - fun newInstance(param1: EquipmentUserInfo?) = - UnBindPlateFragment().apply { - arguments = Bundle().apply { - putParcelable(ARG_PARAM1, param1) - } - } - } - - private val dialogLauncher = registerForActivityResult( - ActivityResultContracts.StartActivityForResult() - ) { result -> - if (result.resultCode == Activity.RESULT_OK) { - viewModel.unbindPlate(info?.id) { pair -> - updateBindState(pair) - } - } - } - - override fun initialize() { - arguments?.let { args -> - info = args.getParcelable(ARG_PARAM1) - info?.let { - binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" - binding.tvPlateNumberValue.text = it.plateNumber - binding.tvNameValue.text = it.name.maskName() - binding.tvPhoneValue.text = it.phone.maskPhone() - val timeInfo = DateTimeUtils.parseDateTime(it.updateTime) - val timeAgo = DateTimeUtils.getTimeAgo(timeInfo) - binding.tvUpdateTimeValue.text = timeAgo - } - } - binding.llUnbind.setOnClickListener { - if (info == null) return@setOnClickListener - val intent = Intent(requireContext(), UnBindDialogActivity::class.java).apply { - putExtra(GlobalKey.PARAM_EQUIPMENT_INFO, info) - } - dialogLauncher.launch(intent) - requireActivity().overridePendingTransition(0, 0) - } - binding.tvBack.setOnClickListener { - activity?.finish() - } - } - - override fun registerDataChange() { - super.registerDataChange() -// lifecycleScope.launch { -// viewModel.bindStateChange.collect { -// updateBindState(it) +//package com.sw.platecabinet.fragment +// +//import android.app.Activity +//import android.content.Intent +//import android.os.Bundle +//import androidx.activity.result.contract.ActivityResultContracts +//import androidx.lifecycle.lifecycleScope +//import com.sw.inbound.utils.DateTimeUtils +//import com.sw.plate.utils.ToastUtils +//import com.sw.platecabinet.GlobalKey +//import com.sw.platecabinet.activity.UnBindDialogActivity +//import com.sw.platecabinet.databinding.FragmentUnbindPlateBinding +//import com.sw.platecabinet.ext.maskName +//import com.sw.platecabinet.ext.maskPhone +//import com.sw.platecabinet.model.ErrorInfo +//import com.sw.platecabinet.model.response.EquipmentUserInfo +//import kotlinx.coroutines.launch +// +///** +// * 餐盘柜绑定 +// */ +//class UnBindPlateFragment private constructor() : BaseFragment( +// FragmentUnbindPlateBinding::inflate +//) { +// internal val ARG_PARAM1 = "param1" +// private var info: EquipmentUserInfo? = null +// +// companion object { +// @JvmStatic +// fun newInstance(param1: EquipmentUserInfo?) = +// UnBindPlateFragment().apply { +// arguments = Bundle().apply { +// putParcelable(ARG_PARAM1, param1) +// } +// } +// } +// +// private val dialogLauncher = registerForActivityResult( +// ActivityResultContracts.StartActivityForResult() +// ) { result -> +// if (result.resultCode == Activity.RESULT_OK) { +// viewModel.unbindPlate(info?.id) { pair -> +// updateBindState(pair) // } // } - } - private fun updateBindState(pair: Pair){ - if (pair.first == null) return // 绑定状态过滤 - val errorInfo = pair.second - if (errorInfo.isSuccess()) { - ToastUtils.showToast("解绑成功") -// activity?.finish() - // 关闭宿主 Activity - requireActivity().finish() - requireActivity().overridePendingTransition(0, 0) - } else { - ToastUtils.showToast(errorInfo.msg) - } - } -} \ No newline at end of file +// } +// +// override fun initialize() { +// arguments?.let { args -> +// info = args.getParcelable(ARG_PARAM1) +// info?.let { +// binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" +// binding.tvPlateNumberValue.text = it.plateNumber +// binding.tvNameValue.text = it.name.maskName() +// binding.tvPhoneValue.text = it.phone.maskPhone() +// val timeInfo = DateTimeUtils.parseDateTime(it.updateTime) +// val timeAgo = DateTimeUtils.getTimeAgo(timeInfo) +// binding.tvUpdateTimeValue.text = timeAgo +// } +// } +// binding.llUnbind.setOnClickListener { +// if (info == null) return@setOnClickListener +// val intent = Intent(requireContext(), UnBindDialogActivity::class.java).apply { +// putExtra(GlobalKey.PARAM_EQUIPMENT_INFO, info) +// } +// dialogLauncher.launch(intent) +// requireActivity().overridePendingTransition(0, 0) +// } +// binding.tvBack.setOnClickListener { +// activity?.finish() +// } +// } +// +// override fun registerDataChange() { +// super.registerDataChange() +//// lifecycleScope.launch { +//// viewModel.bindStateChange.collect { +//// updateBindState(it) +//// } +//// } +// } +// private fun updateBindState(pair: Pair){ +// if (pair.first == null) return // 绑定状态过滤 +// val errorInfo = pair.second +// if (errorInfo.isSuccess()) { +// ToastUtils.showToast("解绑成功") +//// activity?.finish() +// // 关闭宿主 Activity +// requireActivity().finish() +// requireActivity().overridePendingTransition(0, 0) +// } else { +// ToastUtils.showToast(errorInfo.msg) +// } +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt b/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt index 5801b86..3e3f5d3 100644 --- a/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt +++ b/app/src/main/java/com/sw/platecabinet/model/response/EquipmentUserInfo.kt @@ -11,19 +11,19 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class EquipmentUserInfo( - /** - * 主键 - */ - val id: Long? = 0, - /** - * - * 设备Id - */ - val equipmentId: String? = "", - /** - * 设备编号 - */ - var equipmentCode: String? = "", +// /** +// * 主键 +// */ +// val id: Long? = 0, +// /** +// * +// * 设备Id +// */ +// val equipmentId: String? = "", +// /** +// * 设备编号 +// */ +// var equipmentCode: String? = "", /** * 设备盒子编号 */ @@ -31,60 +31,60 @@ data class EquipmentUserInfo( /** * 会员Id */ - val faceId: String? = "", + var faceId: String? = "", /** * 餐盘编号 */ var plateNumber: String? = "", - /** - * 设备名称 - */ - val equipmentName: String? = "", +// /** +// * 设备名称 +// */ +// val equipmentName: String? = "", - val orderNo: String? = "", +// val orderNo: String? = "", /** * * 更新时间 */ - val updateTime: String? = "", + var updateTime: String? = "", - val name: String? = "", - val phone: String? = "", - val faceUrl: String? = "", - val mealTime: String? = "", - val mealTimeInterval: String? = "", - val openTime: String? = "", - val openTimeInterval: String? = "", - val eatCount: Int? = 0, +// val name: String? = "", +// val phone: String? = "", +// val faceUrl: String? = "", +// val mealTime: String? = "", +// val mealTimeInterval: String? = "", +// val openTime: String? = "", +// val openTimeInterval: String? = "", +// val eatCount: Int? = 0, +// +// var cardBalance: Double? = 0.toDouble(), - var cardBalance: Double? = 0.toDouble(), - - /** - * 用于cardBalance后续拦截判断 - */ - var showBalanceNotEnoughDialog: Boolean = false, - var isIntercept: Boolean = false +// /** +// * 用于cardBalance后续拦截判断 +// */ +// var showBalanceNotEnoughDialog: Boolean = false, +// var isIntercept: Boolean = false ) : Parcelable { /** * 是否已绑定 */ fun isBound(): Boolean { - return faceId != null + return faceId.isNullOrBlank().not() } - /** - * 是否是其他设备 - */ - fun isOtherEquipment(): Boolean { - return equipmentCode != null && equipmentCode != "" && GlobalData.globalEquipmentCode != equipmentCode - } +// /** +// * 是否是其他设备 +// */ +// fun isOtherEquipment(): Boolean { +// return equipmentCode != null && equipmentCode != "" && GlobalData.globalEquipmentCode != equipmentCode +// } fun hasEquipmentBox(): Boolean { return !TextUtils.isEmpty(equipmentBoxCode) } fun isPlaceholder(): Boolean { - return equipmentBoxCode == null || equipmentBoxCode == "" + return equipmentBoxCode.isNullOrBlank() } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt b/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt index 27c3908..d38eb28 100644 --- a/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt +++ b/app/src/main/java/com/sw/platecabinet/network/task/HeartBeatTask.kt @@ -1,104 +1,104 @@ -package com.sw.platecabinet.network.task - -import android.content.Context -import android.util.Log -import androidx.work.CoroutineWorker -import androidx.work.WorkerParameters -import com.arcsoft.face.FaceEngine -import com.sw.inbound.utils.GsonUtils -import com.sw.plate.App -import com.sw.plate.utils.Base64 -import com.sw.plate.utils.PrefUtils -import com.sw.plate.utils.arcface.FaceApi -import com.sw.plate.utils.arcface.facedb.entity.FaceEntity -import com.sw.plate.utils.arcface.faceserver.FaceServer -import com.sw.platecabinet.network.ApiClient -import com.sw.platecabinet.repository.RemoteRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.greenrobot.eventbus.EventBus -import timber.log.Timber - -class HeartBeatTask(appContext: Context, workerParams: WorkerParameters) : - CoroutineWorker(appContext, workerParams) { - - companion object { - private const val TAG = "HeartBeatTask" - } - - override suspend fun doWork(): Result { - return try { - // 执行后台任务逻辑 - performSync() - - TaskManager.startTask() - - Result.success() - } catch (e: Exception) { - e.printStackTrace() - Result.retry() - } - } - - private val repository: RemoteRepository by lazy { - RemoteRepository(ApiClient.apiService) - } - - private val faceApi: FaceApi = FaceApi() - - private suspend fun performSync() { -// withContext(Dispatchers.IO) { -// val faceUpdateTimeStamp = PrefUtils.getLong(App.getContext(), "faceUpdateTimeStamp", 0) -// if (faceUpdateTimeStamp == 0L) { -// val timestamp = System.currentTimeMillis() -// PrefUtils.setLong(App.getContext(), "faceUpdateTimeStamp", timestamp) -// } -// val resp = repository.getHeartbeatInterface( -// PrefUtils.getLong( -// App.getContext(), -// "faceUpdateTimeStamp", -// 0 -// ) -// ) -// Timber.tag(TAG).d("performSync: ${GsonUtils.toJson(resp)}") -// val list = resp.data -// if (list.isNullOrEmpty()) { -// return@withContext -// } -// val faceServer = FaceServer.getInstance() -// val faceEngine: FaceEngine? = faceServer.faceEngine +//package com.sw.platecabinet.network.task // -// list.forEachIndexed { index, it -> -// try { -// if (index == list.size - 1) { -// PrefUtils.setLong( -// App.getContext(), -// "faceUpdateTimeStamp", -// it.updateTimeStamp -// ) -// } -// if (it.faceType == "1") { -// if (it.userId.isNullOrBlank().not()) { -// //userId非空,根据userId删除人脸数据 -// faceApi.deleteByUserName(it.userId) -// faceEngine?.removeFaceFeature(it.userId.toInt()) -// } -// } else if (it.faceType == "0") { -// //新增人脸数据 -// val featureData = Base64.decode(it.faceFeature) -// val insertEntity = FaceEntity(it.userId, null, featureData) -// val faceId = faceApi.insert(insertEntity) -// insertEntity.faceId = faceId -//// faceServer.registerFaceFeatureInfoFromDb(insertEntity, faceEngine) +//import android.content.Context +//import android.util.Log +//import androidx.work.CoroutineWorker +//import androidx.work.WorkerParameters +//import com.arcsoft.face.FaceEngine +//import com.sw.inbound.utils.GsonUtils +//import com.sw.plate.App +//import com.sw.plate.utils.Base64 +//import com.sw.plate.utils.PrefUtils +//import com.sw.plate.utils.arcface.FaceApi +//import com.sw.plate.utils.arcface.facedb.entity.FaceEntity +//import com.sw.plate.utils.arcface.faceserver.FaceServer +//import com.sw.platecabinet.network.ApiClient +//import com.sw.platecabinet.repository.RemoteRepository +//import kotlinx.coroutines.Dispatchers +//import kotlinx.coroutines.withContext +//import org.greenrobot.eventbus.EventBus +//import timber.log.Timber // -// EventBus.getDefault().post(insertEntity) -//// callback(insertEntity) -// } -// } catch (e: Exception) { -// e.printStackTrace() -// } -// } +//class HeartBeatTask(appContext: Context, workerParams: WorkerParameters) : +// CoroutineWorker(appContext, workerParams) { +// +// companion object { +// private const val TAG = "HeartBeatTask" +// } +// +// override suspend fun doWork(): Result { +// return try { +// // 执行后台任务逻辑 +// performSync() +// +// TaskManager.startTask() +// +// Result.success() +// } catch (e: Exception) { +// e.printStackTrace() +// Result.retry() // } - } - -} \ No newline at end of file +// } +// +// private val repository: RemoteRepository by lazy { +// RemoteRepository(ApiClient.apiService) +// } +// +// private val faceApi: FaceApi = FaceApi() +// +// private suspend fun performSync() { +//// withContext(Dispatchers.IO) { +//// val faceUpdateTimeStamp = PrefUtils.getLong(App.getContext(), "faceUpdateTimeStamp", 0) +//// if (faceUpdateTimeStamp == 0L) { +//// val timestamp = System.currentTimeMillis() +//// PrefUtils.setLong(App.getContext(), "faceUpdateTimeStamp", timestamp) +//// } +//// val resp = repository.getHeartbeatInterface( +//// PrefUtils.getLong( +//// App.getContext(), +//// "faceUpdateTimeStamp", +//// 0 +//// ) +//// ) +//// Timber.tag(TAG).d("performSync: ${GsonUtils.toJson(resp)}") +//// val list = resp.data +//// if (list.isNullOrEmpty()) { +//// return@withContext +//// } +//// val faceServer = FaceServer.getInstance() +//// val faceEngine: FaceEngine? = faceServer.faceEngine +//// +//// list.forEachIndexed { index, it -> +//// try { +//// if (index == list.size - 1) { +//// PrefUtils.setLong( +//// App.getContext(), +//// "faceUpdateTimeStamp", +//// it.updateTimeStamp +//// ) +//// } +//// if (it.faceType == "1") { +//// if (it.userId.isNullOrBlank().not()) { +//// //userId非空,根据userId删除人脸数据 +//// faceApi.deleteByUserName(it.userId) +//// faceEngine?.removeFaceFeature(it.userId.toInt()) +//// } +//// } else if (it.faceType == "0") { +//// //新增人脸数据 +//// val featureData = Base64.decode(it.faceFeature) +//// val insertEntity = FaceEntity(it.userId, null, featureData) +//// val faceId = faceApi.insert(insertEntity) +//// insertEntity.faceId = faceId +////// faceServer.registerFaceFeatureInfoFromDb(insertEntity, faceEngine) +//// +//// EventBus.getDefault().post(insertEntity) +////// callback(insertEntity) +//// } +//// } catch (e: Exception) { +//// e.printStackTrace() +//// } +//// } +//// } +// } +// +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/network/task/TaskManager.kt b/app/src/main/java/com/sw/platecabinet/network/task/TaskManager.kt index 0f590b7..fb3b78f 100644 --- a/app/src/main/java/com/sw/platecabinet/network/task/TaskManager.kt +++ b/app/src/main/java/com/sw/platecabinet/network/task/TaskManager.kt @@ -1,40 +1,40 @@ -package com.sw.platecabinet.network.task - -import androidx.lifecycle.LifecycleOwner -import androidx.work.ExistingWorkPolicy -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkInfo -import androidx.work.WorkManager -import com.sw.plate.App -import java.util.concurrent.TimeUnit - -object TaskManager { - private const val TASK_NAME = "SmartPlateCabinetTask" -// private var owner: LifecycleOwner?=null -// fun setOwner(owner: LifecycleOwner) { -// this.owner = owner +//package com.sw.platecabinet.network.task +// +//import androidx.lifecycle.LifecycleOwner +//import androidx.work.ExistingWorkPolicy +//import androidx.work.OneTimeWorkRequestBuilder +//import androidx.work.WorkInfo +//import androidx.work.WorkManager +//import com.sw.plate.App +//import java.util.concurrent.TimeUnit +// +//object TaskManager { +// private const val TASK_NAME = "SmartPlateCabinetTask" +//// private var owner: LifecycleOwner?=null +//// fun setOwner(owner: LifecycleOwner) { +//// this.owner = owner +//// } +// fun startTask() { +// val nextRequest = OneTimeWorkRequestBuilder() +// .setInitialDelay(1, TimeUnit.MINUTES) +//// .setInputData(inputData) +// .build() +// WorkManager.getInstance(App.getContext()) +//// .apply{ +//// getWorkInfoByIdLiveData(nextRequest.id) +//// .observe(owner) { workInfo -> +//// if (workInfo?.state == WorkInfo.State.SUCCEEDED) { +//// val result = workInfo.outputData.getString("RESULT_KEY") +//// // 使用返回的结果 +//// } +//// } +//// } +// .enqueueUniqueWork(TASK_NAME, ExistingWorkPolicy.REPLACE, nextRequest) // } - fun startTask() { - val nextRequest = OneTimeWorkRequestBuilder() - .setInitialDelay(1, TimeUnit.MINUTES) -// .setInputData(inputData) - .build() - WorkManager.getInstance(App.getContext()) -// .apply{ -// getWorkInfoByIdLiveData(nextRequest.id) -// .observe(owner) { workInfo -> -// if (workInfo?.state == WorkInfo.State.SUCCEEDED) { -// val result = workInfo.outputData.getString("RESULT_KEY") -// // 使用返回的结果 -// } -// } -// } - .enqueueUniqueWork(TASK_NAME, ExistingWorkPolicy.REPLACE, nextRequest) - } - - fun cancelTask() { - WorkManager.getInstance(App.getContext()) - .cancelUniqueWork(TASK_NAME) - } - -} \ No newline at end of file +// +// fun cancelTask() { +// WorkManager.getInstance(App.getContext()) +// .cancelUniqueWork(TASK_NAME) +// } +// +//} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/utils/FlowCountDown.kt b/app/src/main/java/com/sw/platecabinet/utils/FlowCountDown.kt new file mode 100644 index 0000000..13ad923 --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/FlowCountDown.kt @@ -0,0 +1,33 @@ +package com.sw.platecabinet.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart +import kotlin.ranges.downTo + +// 倒计时Flow扩展函数 +fun countDownByFlow( + total: Int, + scope: CoroutineScope, + onTick: (Int) -> Unit, + onStart: (() -> Unit)? = null, + onFinish: (() -> Unit)? = null +): Job { + return flow { + for (i in total downTo 0) { + emit(i) + if (i != 0) delay(1000) + } + }.flowOn(Dispatchers.Main) + .onStart { onStart?.invoke() } + .onCompletion { onFinish?.invoke() } + .onEach { onTick.invoke(it) } + .launchIn(scope) +} diff --git a/app/src/main/java/com/sw/platecabinet/utils/PlateUtils.kt b/app/src/main/java/com/sw/platecabinet/utils/PlateUtils.kt new file mode 100644 index 0000000..2f7833e --- /dev/null +++ b/app/src/main/java/com/sw/platecabinet/utils/PlateUtils.kt @@ -0,0 +1,41 @@ +package com.sw.platecabinet.utils + +import androidx.fragment.app.FragmentActivity +import com.sw.plate.utils.ToastUtils +import com.sw.plate.utils.comn.SerialApi +import com.sw.plate.utils.comn.SerialPortManager +import com.sw.platecabinet.activity.BaseActivity +import com.sw.platecabinet.activity.MainActivity +import com.sw.platecabinet.activity.PageType +import timber.log.Timber + +object PlateUtils { + + fun open(fragmentActivity: FragmentActivity, code: String?) { + val activity = fragmentActivity as BaseActivity<*> + Timber.d("itemClick llOpen equipmentBoxCode = ${code}") + val equipmentBoxCode: Int = code?.toInt() ?: -1 + if (equipmentBoxCode < 0) { + ToastUtils.showToast("餐盘柜编号错误") + return + } + activity.showWaitingDialog("请稍等") + SerialApi.openPlate(equipmentBoxCode, object : SerialPortManager.SendCallback { + override fun onSuccess() { + activity.hideWaitingDialog() + MainActivity.start( + activity, + pageType = PageType.PLATE_TIP, + isAdmin = true + ) + } + + override fun onFail(e: Exception?) { + activity.hideWaitingDialog() + ToastUtils.showToast("柜门打开失败") + } + }) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/platecabinet/utils/SpTool.kt b/app/src/main/java/com/sw/platecabinet/utils/SpTool.kt index e6ab899..ccee471 100644 --- a/app/src/main/java/com/sw/platecabinet/utils/SpTool.kt +++ b/app/src/main/java/com/sw/platecabinet/utils/SpTool.kt @@ -1,20 +1,42 @@ -package com.sw.platecabinet.utils; +package com.sw.platecabinet.utils -import com.sw.inbound.utils.SPUtil; -import com.sw.platecabinet.MyApp; +import com.google.gson.Gson +import com.sw.inbound.utils.GsonUtils +import com.sw.inbound.utils.SPUtil +import com.sw.inbound.utils.SPUtil.Companion.getInstance +import com.sw.platecabinet.MyApp +import com.sw.platecabinet.model.response.EquipmentUserInfo -public class SpTool { +object SpTool { + const val LAST_FACE_TIMESTAMP: String = "faceTimestamp" + const val PLATE_BOX_DATA: String = "plateBoxBind" + private var spUtil: SPUtil? = null - public static final String LAST_FACE_TIMESTAMP = "faceTimestamp"; - - public static long getLastFaceTimestamp() { - return SPUtil.Companion.getInstance(MyApp.getContext(), "default_sp").get(LAST_FACE_TIMESTAMP, 0L); + init { + spUtil = getInstance(MyApp.instance!!, "default_sp") } - public static void setLastFaceTimestamp(long timestamp) { - SPUtil.Companion.getInstance(MyApp.getContext(), "default_sp").put(LAST_FACE_TIMESTAMP, timestamp); + fun putString(key:String, value:String) { + spUtil?.put(key, value) } + var lastFaceTimestamp: Long + get() = spUtil?.get(SpTool.LAST_FACE_TIMESTAMP, 0L) ?: 0 + set(timestamp) { + spUtil?.put(LAST_FACE_TIMESTAMP, timestamp) + } + fun savePlateData(items: List) { + val jsonData = Gson().toJson(items) + putString(PLATE_BOX_DATA, jsonData) + } + + fun getPlateData(): List? { + val jsonData = spUtil?.get(PLATE_BOX_DATA, "") + if (jsonData.isNullOrBlank()) { + return null + } + return GsonUtils.fromJsonList(jsonData, EquipmentUserInfo::class.java) + } } diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt index d8c16de..f9c4b20 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/SettingViewModel.kt @@ -61,15 +61,15 @@ class SettingViewModel : BaseViewModel() { //// } //// _equipmentList.value = list // } - fun getEquipmentList(block: (List) -> Unit) { - launchWithLoading { - val response = repository.getEquipmentList() - if (parseResponse(response)) { - val list = response.data ?: emptyList() - block(list) - } - } - } +// fun getEquipmentList(block: (List) -> Unit) { +// launchWithLoading { +// val response = repository.getEquipmentList() +// if (parseResponse(response)) { +// val list = response.data ?: emptyList() +// block(list) +// } +// } +// } /** * 搜索会员信息列表 @@ -172,19 +172,19 @@ class SettingViewModel : BaseViewModel() { fun bindPlate(bindParam: BindParam, block:(Pair)-> Unit) { launchWithLoading { - val response = repository.plateBind(bindParam) - if (parseResponse(response)) { - var userInfo = response.data - if (userInfo == null) { - userInfo = EquipmentUserInfo() - userInfo.equipmentBoxCode = bindParam.equipmentBoxCode - userInfo.plateNumber = bindParam.plateNumber - userInfo.equipmentCode = bindParam.equipmentCode - } - block(true to ErrorInfo(equipmentUserInfo = userInfo)) - } else { - block(true to ErrorInfo(response.code, response.msg.toString())) - } +// val response = repository.plateBind(bindParam) +// if (parseResponse(response)) { +// var userInfo = response.data +// if (userInfo == null) { +// userInfo = EquipmentUserInfo() +// userInfo.equipmentBoxCode = bindParam.equipmentBoxCode +// userInfo.plateNumber = bindParam.plateNumber +// userInfo.equipmentCode = bindParam.equipmentCode +// } +// block(true to ErrorInfo(equipmentUserInfo = userInfo)) +// } else { +// block(true to ErrorInfo(response.code, response.msg.toString())) +// } } } @@ -192,20 +192,20 @@ class SettingViewModel : BaseViewModel() { plateNumber: String, equipmentCode: String = globalEquipmentCode ) { - _searchUserInfo.value = null - launchWithLoading { -// val bindParam = BindParam(plateNumber = plateNumber) - val response = repository.findByPlateNumber(plateNumber) - if (response.code == "00000") { - _searchUserInfo.value = response.data - } else { - _searchUserInfo.value = EquipmentUserInfo( - plateNumber = plateNumber, - equipmentCode = equipmentCode, - updateTime = DateTimeUtils.getDateTimeString() - ) - } - } +// _searchUserInfo.value = null +// launchWithLoading { +//// val bindParam = BindParam(plateNumber = plateNumber) +// val response = repository.findByPlateNumber(plateNumber) +// if (response.code == "00000") { +// _searchUserInfo.value = response.data +// } else { +// _searchUserInfo.value = EquipmentUserInfo( +// plateNumber = plateNumber, +// equipmentCode = equipmentCode, +// updateTime = DateTimeUtils.getDateTimeString() +// ) +// } +// } } val PAGE_SIZE = 100 diff --git a/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt b/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt index 00ff265..85a28e6 100644 --- a/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt +++ b/app/src/main/java/com/sw/platecabinet/viewmodel/UserViewModel.kt @@ -83,7 +83,7 @@ class UserViewModel : BaseViewModel() { if (list.isNotEmpty()) { faceTimestamp = list.last().faceUpdateTimestamp?:0 } - SpTool.setLastFaceTimestamp(faceTimestamp) + SpTool.lastFaceTimestamp = faceTimestamp //activeEngine() } } diff --git a/app/src/main/res/layout/activity_login_face.xml b/app/src/main/res/layout/activity_login_face.xml index f38396a..529b200 100644 --- a/app/src/main/res/layout/activity_login_face.xml +++ b/app/src/main/res/layout/activity_login_face.xml @@ -59,39 +59,86 @@ android:layout_gravity="center_horizontal" android:layout_marginTop="129dp" android:text="请正视屏幕" - android:textStyle="bold" android:textColor="#FFCC99" - android:textSize="36sp" /> + android:textSize="36sp" + android:textStyle="bold" /> - + + + + + + + + + + + - - + + + + + + + + android:textSize="36sp" + tools:text="30" /> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_setting_list.xml b/app/src/main/res/layout/fragment_setting_list.xml index 1972189..476308a 100644 --- a/app/src/main/res/layout/fragment_setting_list.xml +++ b/app/src/main/res/layout/fragment_setting_list.xml @@ -1,16 +1,22 @@ + tools:context=".fragment.SettingListFragment" + tools:background="@color/black"> + android:layout_height="match_parent" + app:spanCount="2" + android:overScrollMode="never" + app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" + tools:listitem="@layout/item_bind_view"/> \ No newline at end of file diff --git a/app/src/main/res/layout/item_bind_view.xml b/app/src/main/res/layout/item_bind_view.xml index e31f9a1..a37b128 100644 --- a/app/src/main/res/layout/item_bind_view.xml +++ b/app/src/main/res/layout/item_bind_view.xml @@ -1,5 +1,6 @@ @@ -44,10 +45,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="24dp" - android:text="马*飞(8000)" android:textColor="#585868" android:textSize="18sp" - android:textStyle="bold" /> + android:textStyle="bold" + tools:text="马*飞(8000)" /> drawRectInfoText = new MutableLiveData<>(); - private MutableLiveData recognizeUserId = new MutableLiveData<>(); + private MutableLiveData recognizeUserId = new MutableLiveData<>(); /** * 检测ir活体前,是否需要更新faceData @@ -474,7 +474,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { Disposable disposable = Observable.just(true).observeOn(AndroidSchedulers.mainThread()).subscribe(aBoolean -> { if (similarPass) { if (recognizeUserId != null) { - recognizeUserId.postValue(compareResult.getFaceEntity().getUserName()); + recognizeUserId.postValue(compareResult); } boolean isAdded = false; List compareResults = compareResultList.getValue(); @@ -540,7 +540,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { return recognizeNotice; } - public MutableLiveData getRecognizeUserId() { + public MutableLiveData getRecognizeUserId() { return recognizeUserId; } @@ -561,7 +561,7 @@ public class RecognizeViewModel extends ViewModel implements RecognizeCallback { } } - private void updateRegisterStatus(int status) { + public void updateRegisterStatus(int status) { registerStatus = status; }