package com.example.chemical.ui.login import android.graphics.Bitmap import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.widget.ImageView import android.widget.TextView import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.request.RequestOptions import com.example.chemical.ChemicalApp import com.example.chemical.R import com.example.chemical.databinding.ActivityScanLoginBinding import com.example.chemical.ui.common.BaseCountDownActivity import com.example.chemical.utils.MediaPlayerHelper import com.example.chemical.utils.TimesUils import com.example.chemical.utils.UiManager import com.example.chemical.weidith.AuthenticationDialog import com.example.chemical.weidith.CustomDialog import com.google.zxing.BarcodeFormat import com.google.zxing.MultiFormatWriter import com.google.zxing.WriterException import com.google.zxing.common.BitMatrix import com.kongzue.dialogx.dialogs.PopTip import com.lztek.toolkit.Lztek import com.rc.core.log.RcLog import com.rc.httpcore.HttpClient import com.rc.httpcore.HttpConfig import com.rc.httpcore.client.ApiRepository import com.rc.httpcore.exception.NetException import retrofit2.HttpException import java.net.ConnectException import java.net.SocketTimeoutException //扫码登录 class ScanLoginActivity : BaseCountDownActivity() { private var mLztek: Lztek? = null private var mDeviceNum: String? = null //设备唯一标识 override fun createViewBinding() = ActivityScanLoginBinding.inflate(LayoutInflater.from(this)) override fun initData() { super.initData() MediaPlayerHelper.playRawMp3(this, R.raw.login_wei_xin_sao_ma) viewBinding.deptName.text = "${ChemicalApp.confs!!.deptName}-${ChemicalApp.confs!!.roomNum}" viewBinding.tvReturn.text = "返回${ChemicalApp.confs!!.backTime}s" Glide.with(this) .load("${HttpConfig.API_BASE_IMG_URL}${ChemicalApp.confs!!.circularLogo}") .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.AUTOMATIC)) .into(viewBinding.image) val stringExtra = intent.getStringExtra("mtypes") val map = mutableMapOf() if (stringExtra != null) { map["mtypes"] = stringExtra } when (stringExtra) { "1" -> { viewBinding.linType.visibility = View.GONE } "6" -> { viewBinding.tvFace.visibility = View.GONE } } try { var str = intent.getStringExtra("faceList") if (str != null) { map["faceList"] = str } } catch (e: Exception) { } //人脸识别 viewBinding.tvFace.setOnClickListener { UiManager.switcher(this, map, FacialLoginActivity::class.java) finish() } //刷卡 viewBinding.tvCrad.setOnClickListener { UiManager.switcher(this, map, SwipeActivity::class.java) finish() } } override fun initViews(savedInstanceState: Bundle?) { super.initViews(savedInstanceState) val stringExtra = intent.getStringExtra("mtypes") if (stringExtra == "1") { viewBinding.linType.visibility = View.GONE } else if (stringExtra == "5") { viewBinding.tvCrad.visibility = View.GONE } val map = mutableMapOf() if (stringExtra != null) { map["mtypes"] = stringExtra } viewBinding.tvFace.setOnClickListener { var str = intent.getStringExtra("faceList") if (str != null) { map["faceList"] = str } UiManager.switcher(this, map, FacialLoginActivity::class.java) finish() } viewBinding.tvCrad.setOnClickListener { UiManager.switcher(this, map, SwipeActivity::class.java) finish() } val currentDateTime = TimesUils.getCurrentDateTime() mLztek = Lztek.create(this) val toUpperCase = mLztek!!.ethMac.toUpperCase() mDeviceNum = toUpperCase.replace(":", "") RcLog.info("=========当前设备得mac地址$mDeviceNum") val text = HttpConfig.API_BASE_QC_URL + "?code=${currentDateTime}&subId=${ChemicalApp.subjectId!!}&type=11&macId=${mDeviceNum}" // 要生成二维码的文本内容 val width = 130 // 二维码宽度 val height = 130 // 二维码高度 loadQRCodeIntoImageView(text, width, height, viewBinding.img) myHandler.start() viewBinding.tvReturn.setOnClickListener { finish() } } private val myHandler = MyHandler { logInAuthScan() } //用户登录 private fun logInAuthScan() { HttpClient.token = null showLoading("查询中...") val currentDateTime = TimesUils.getCurrentDateTime() RcLog.info("=获取时间作为code$currentDateTime") val disposable = ApiRepository.getScanCode(mDeviceNum!!, currentDateTime, ChemicalApp.subjectId!!) .subscribe({ data -> dismissLoading() myHandler.stop() ChemicalApp.userData = data // ChemicalApp!!.userData!!.cardNum = data.cardNum authenticationInfo(data.userId, ChemicalApp.subjectId!!) }, { throwable -> dismissLoading() throwableView(throwable) }) addDisposable(disposable) } //验证当前人员身份 private fun authenticationInfo(userId: String, subId: String) { showLoading("验证中...") val disposable = ApiRepository.userCardValidation(userId, subId) .subscribe({ data -> dismissLoading() val allFalse = with(data) { cabinetAdmin == false && belongUser == false && toipcUser == false && safeUser == false && collegeAdmin == false && schoolLevelAdmin == false && adminUser == false apply == false && white == false } if (allFalse) { HttpClient.token = null ChemicalApp.userData = null customDialogView(2, "当前身份不符合") } else { //校级管理员 schoolLevelAdmin //院级管理员 collegeAdmin //实验室负责人 adminUser //安全负责人 safeUser //柜锁管理员 cabinetAdmin //是否化学品归属人 belongUser //是否化学品归属课题组下成员 toipcUser if (data.schoolLevelAdmin == true || data.collegeAdmin == true) { authenticationDialog(data.faceImg, data.userName) } else if (data.adminUser == true || data.safeUser == true || data.cabinetAdmin == true) { //实验室负责人 or 安全负责人 or 柜锁管理员 authenticationDialog(data.faceImg, data.userName) } else if (data.belongUser == true || data.toipcUser == true) { //当前身份 归属人or课题组 authenticationDialog(data.faceImg, data.userName) } else if (data.white == true || data.apply == true) {// 白名单和实验室准入 authenticationDialog(data.faceImg, data.userName) } else { HttpClient.token = null ChemicalApp.userData = null customDialogView(2, "当前身份不符合") } } }, { throwable -> PopTip.show(throwable.message) dismissLoading() HttpClient.token = null ChemicalApp.userData = null }) addDisposable(disposable) } // 生成二维码的函数 private fun generateQRCode(text: String, width: Int, height: Int): Bitmap? { try { val bitMatrix: BitMatrix = MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height) val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) for (x in 0 until width) { for (y in 0 until height) { bitmap.setPixel( x, y, if (bitMatrix[x, y]) 0xFF000000.toInt() else 0xFFFFFFFF.toInt() ) } } return bitmap } catch (e: WriterException) { e.printStackTrace() } return null } // 使用 Glide 加载二维码到 ImageView private fun loadQRCodeIntoImageView( text: String, width: Int, height: Int, imageView: ImageView ) { val bitmap = generateQRCode(text, width, height) bitmap?.let { Glide.with(this) .load(it) .apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE)) .into(imageView) } } override fun onDestroy() { super.onDestroy() myHandler.stop() // 移除回调,以防止内存泄漏 try { handlerBack.removeCallbacks(countdownRunnable) } catch (e: Exception) { } } class MyHandler(private val callback: () -> Unit) { private val handler = Handler() // private val interval: Long = 10 * 60 * 1000 // 10分钟 private val interval: Long = 3000 // 3秒 private val runnable = object : Runnable { override fun run() { callback.invoke() handler.postDelayed(this, interval) } } fun start() { handler.postDelayed(runnable, interval) } fun stop() { handler.removeCallbacks(runnable) handler.removeCallbacksAndMessages(null) } } override fun onBackPressed() { super.onBackPressed() finish() } override fun cdTime(cd: Int) { viewBinding.tvReturn.text = "返回${cd}s" } private val handlerBack = Handler(Looper.getMainLooper()) private var timeLeftInSeconds = 2 private var mTvView: TextView? = null private var mDialogsAut: AuthenticationDialog? = null //身份认证成功 private fun authenticationDialog(faceImg: String?, userName: String) { MediaPlayerHelper.playRawMp3(this, R.raw.login_ren_zheng_tong_hua) mDialogsAut = AuthenticationDialog( this, faceImg, ChemicalApp.confs!!.subName, ChemicalApp.confs!!.deptName, "${ChemicalApp.confs!!.buildName}${ChemicalApp.confs!!.floorName}", userName, object : AuthenticationDialog.IClickLit { override fun onUpView(tvView: TextView) { mTvView = tvView } }) mDialogsAut!!.show() // 开始倒计时 handlerBack.post(countdownRunnable) // 获取对话框的 Window 对象 mDialogsAut!!.window?.decorView?.setOnTouchListener { _, event -> // 判断是否点击了对话框外部空白区域 if (event.action == MotionEvent.ACTION_DOWN) { val x = event.x val y = event.y val dialogView = mDialogsAut!!.window?.decorView if (dialogView != null && (x < 0 || x > dialogView.width || y < 0 || y > dialogView.height)) { // 在此处执行点击对话框外部空白区域时的操作 // 例如关闭对话框 // 移除回调,以防止内存泄漏 mDialogsAut!!.dismiss() finish() return@setOnTouchListener true } } return@setOnTouchListener false } } private val countdownRunnable = object : Runnable { override fun run() { if (timeLeftInSeconds > 0) { mTvView!!.text = "${timeLeftInSeconds}秒后自动返回首页" timeLeftInSeconds-- handlerBack.postDelayed(this, 1000) } else { mDialogsAut!!.dismiss() finish() } } } /** * 0 没有图标 1 绿色(成功) 2红色(失败) * 失败或者成功的弹框 */ private fun customDialogView(types: Int, msg: String) { val customDialog = CustomDialog(this, types, msg) if (!this.isFinishing && !this.isDestroyed) { customDialog.show() } } /** * 异常处理 */ private fun throwableView(throwable: Throwable) { RcLog.info("${throwable.message}") // when (throwable) { // is NetException -> { // if (throwable.message.isNullOrEmpty()) { // "接口请求失败(${throwable.code})" // } else { // throwable.message!! // } // } // is SocketTimeoutException -> "请求超时,请稍后重试" // is ConnectException -> "无法连接服务器,请检查网络" // is HttpException -> "服务器繁忙,请稍后重试" // else -> null // }?.let { customDialogView(2, "$it") } customDialogView(2, "${throwable.message}") } }