README.md
@@ -592,7 +592,7 @@ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", "terminal/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { generallibrary/src/main/java/com/dayu/general/BaseApplication.kt
@@ -55,6 +55,13 @@ } /** * 获取MainActivity实例 */ fun getMainActivity(): com.dayu.general.activity.MainActivity? { return mainActivityInstance } /** * 请求获取水价,如果为空则调用MainActivity的获取方法 */ fun requestWaterPrice(): Double { generallibrary/src/main/java/com/dayu/general/activity/CardReplaceActivity.kt
@@ -66,8 +66,6 @@ cardNum = intent.getStringExtra("cardNum") initView() // 获取支付方式 getPaymentMethods() // 无论是否有clientNum,都先显示读卡界面,等待用户刷新卡 resetToReadingState() @@ -85,100 +83,8 @@ } } /** * 获取支付方式列表 */ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { override fun onNext(response: BaseResponse<PaymentMethodResponse>) { if (response.success) { // 获取支付方式列表 val paymentMethods = response.content?.obj ?: listOf() if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods // 更新支付方式显示 updatePaymentMethodRadioGroup() } } else { Toast.makeText( this@CardReplaceActivity, "获取支付方式失败: ${response.msg}", Toast.LENGTH_SHORT ).show() } } override fun onError(e: Throwable?) { super.onError(e) Toast.makeText( this@CardReplaceActivity, "获取支付方式失败: ${e?.message ?: "网络异常"}", Toast.LENGTH_SHORT ).show() } } ) } /** * 更新支付方式RadioGroup */ private fun updatePaymentMethodRadioGroup() { // 清空原有RadioButton binding.paymentMethodGroup.removeAllViews() // 动态添加RadioButton paymentMethodList.forEachIndexed { index, method -> val radioButton = RadioButton(this) radioButton.id = View.generateViewId() // 生成唯一ID radioButton.layoutParams = android.widget.LinearLayout.LayoutParams( 0, resources.getDimensionPixelSize(R.dimen.dimen_40), 1.0f ) // 如果不是最后一个按钮,添加右边距 if (index < paymentMethodList.size - 1) { (radioButton.layoutParams as android.widget.LinearLayout.LayoutParams).rightMargin = resources.getDimensionPixelSize(R.dimen.dimen_15) } radioButton.text = method.name radioButton.background = resources.getDrawable(R.drawable.radio_selector) radioButton.buttonDrawable = null radioButton.gravity = android.view.Gravity.CENTER radioButton.setTextColor(resources.getColorStateList(R.color.radio_button_text_color)) radioButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) // 添加到RadioGroup binding.paymentMethodGroup.addView(radioButton) // 默认选中第一个 if (index == 0) { radioButton.isChecked = true paymentMethod = method.name paymentId = method.id } } // 设置支付方式选择监听 binding.paymentMethodGroup.setOnCheckedChangeListener { group, checkedId -> // 根据选中的ID获取支付方式 for (i in 0 until group.childCount) { val radioButton = group.getChildAt(i) as RadioButton if (radioButton.id == checkedId) { paymentMethod = radioButton.text.toString() paymentId = paymentMethodList[i].id break } } } } /** * 重置到读卡状态 generallibrary/src/main/java/com/dayu/general/activity/CardReturnActivity.kt
@@ -381,7 +381,7 @@ val intent = Intent(this, NfcWreatActivity::class.java).apply { putExtra("cardAddr", cardNumber) putExtra("operationTypeCode", CardOperationType.ReturnCard.code) // 使用返还类型进行写卡 putExtra("operationTypeCode", CardOperationType.SUPPLEMENT.code) // 使用返还类型进行写卡 putExtra("orderNumber", returnResult.orderNo) putExtra("returnAmount", returnAmount) putExtra("userCard", updatedUserCard as java.io.Serializable) generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
@@ -53,7 +53,7 @@ binding.successMessage.text = message } CardOperationType.ReturnCard -> { CardOperationType.SUPPLEMENT -> { // 设置标题 binding.titleBar.setCenterText("返还成功") generallibrary/src/main/java/com/dayu/general/activity/MainActivity.kt
@@ -9,6 +9,7 @@ import android.widget.Toast import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.general.BaseApplication @@ -16,9 +17,13 @@ import com.dayu.general.adapter.TabAdapter import com.dayu.general.bean.net.UserInfoResult import com.dayu.general.bean.net.WaterPriceResult import com.dayu.general.dao.BaseDaoSingleton import com.dayu.general.databinding.ActivityMainBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.tool.CardOperationType import com.tencent.bugly.crashreport.CrashReport import kotlinx.coroutines.launch class MainActivity : BaseNfcActivity() { @@ -232,4 +237,111 @@ } return super.onKeyDown(keyCode, event) } /** * 向服务器上报写卡操作结果 * 写卡成功后调用此方法通知服务器操作完成,成功后更新本地数据库isReported为true * * @param cardAddr 卡地址/卡号 * @param operationTypeCode 操作类型代码 * @param orderNumber 订单号 * @param regionNumber 区域号 * @param projectNumber 项目号 */ fun postCardData( cardAddr: String, operationTypeCode: Int, orderNumber: String = "", regionNumber: String = "", projectNumber: String = "" ) { val map = mutableMapOf<String, Any>() // 添加卡地址参数 if (cardAddr.isNotEmpty()) { map["cardAddr"] = cardAddr } // 添加操作类型参数 // 判断是否为管理卡制作操作类型(100-108),如果是则传递MANAGEMENT_CARD_WRITE的值(7) val operateTypeToSend = if (operationTypeCode in 100..108) { CardOperationType.MANAGEMENT_CARD_WRITE.code } else { operationTypeCode } map["operateType"] = operateTypeToSend // 添加订单号参数(如果存在) if (orderNumber.isNotEmpty()) { map["orderNumber"] = orderNumber } // 添加区域号和项目号参数 if (regionNumber.isNotEmpty()) { map["regionNumber"] = regionNumber } if (projectNumber.isNotEmpty()) { map["projectNumber"] = projectNumber } // 调用服务器接口上报操作结果 ApiManager.getInstance().requestPostHideLoading( this, "terminal/card/termCallBack", // 终端写卡回调接口 String::class.java, map, object : SubscriberListener<BaseResponse<String>>() { override fun onNext(t: BaseResponse<String>) { if (t.success) { // 上报成功,更新本地数据库isReported为true updateCardReportedStatus(cardAddr, orderNumber) } else { // 上报失败,记录错误但不影响用户操作 CrashReport.postCatchedException(Exception("上报写卡结果失败: ${t.msg}")) } } override fun onError(e: Throwable?) { super.onError(e) // 网络错误,记录错误但不影响用户操作 CrashReport.postCatchedException(e ?: Exception("上报写卡结果网络错误")) } } ) } /** * 更新本地数据库中的上报状态 * 将CardRegistrationBean中的isReported状态设置为true * * @param cardNumber 卡号 * @param orderNumber 订单号 */ private fun updateCardReportedStatus(cardNumber: String, orderNumber: String = "") { lifecycleScope.launch { try { val cardRegistrationDao = BaseDaoSingleton.getInstance(this@MainActivity) .cardRegistrationDao() // 根据订单号查找CardRegistrationBean记录 val cardRegistration = if (orderNumber.isNotEmpty()) { cardRegistrationDao.getByOrderId(orderNumber) } else { // 如果没有订单号,则通过卡号查找 cardRegistrationDao.getByCardNumber(cardNumber) } if (cardRegistration != null) { // 创建更新后的CardRegistrationBean对象,将isReported设置为true val updatedCardRegistration = cardRegistration.copy(isReported = true) // 更新数据库记录 cardRegistrationDao.update(updatedCardRegistration) } } catch (e: Exception) { // 记录异常信息,但不影响用户操作 CrashReport.postCatchedException(e) e.printStackTrace() } } } } generallibrary/src/main/java/com/dayu/general/activity/ManageListActivity.kt
@@ -24,7 +24,7 @@ binding?.tvAreaCard?.setOnClickListener { var intent = Intent(this, ManagerReadActivity::class.java).apply { putExtra("cardType", CardCommon.REGION_CARD) putExtra("operationTypeCode", CardOperationType.RegionCard.code) putExtra("operationTypeCode", CardOperationType.RegionCardMake.code) } startActivity(intent) } @@ -33,7 +33,7 @@ binding?.tvCheckCard?.setOnClickListener { var intent = Intent(this, ManagerReadActivity::class.java).apply { putExtra("cardType", CardCommon.CHECK_CARD) putExtra("operationTypeCode", CardOperationType.CheckCard.code) putExtra("operationTypeCode", CardOperationType.CheckCardMake.code) } startActivity(intent) } @@ -42,7 +42,7 @@ binding?.tvDebugCard?.setOnClickListener { var intent = Intent(this, ManagerReadActivity::class.java).apply { putExtra("cardType", CardCommon.DEBUG_CARD) putExtra("operationTypeCode", CardOperationType.DebugCard.code) putExtra("operationTypeCode", CardOperationType.DebugCardMake.code) } startActivity(intent) } @@ -51,7 +51,7 @@ binding?.tvCleanCard?.setOnClickListener { var intent = Intent(this, ManagerReadActivity::class.java).apply { putExtra("cardType", CardCommon.CLEAN_CARD_TYPE) putExtra("operationTypeCode", CardOperationType.CleanCard.code) putExtra("operationTypeCode", CardOperationType.CleanCardMake.code) } startActivity(intent) } generallibrary/src/main/java/com/dayu/general/activity/ManagerReadActivity.kt
@@ -15,6 +15,7 @@ import com.dayu.general.model.CardInfoModel import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.tool.BaseCommon.Companion.protocol import com.dayu.general.tool.CardCommon import com.dayu.general.tool.NfcReadHelper @@ -48,18 +49,34 @@ CardCommon.CLEAN_CARD_TYPE -> binding.titleBar.setCenterText("制作清零卡") else -> binding.titleBar.setCenterText("读卡") } binding.titleBar.setOnItemclickListner(ClickType_LEFT_IMAGE) { this.finish() } // 根据卡类型设置输入框可见性 when (cardType) { CardCommon.REGION_CARD -> { // 区域表号卡:显示区域号输入框 // 区域表号卡:显示区域号和项目号输入框 binding.regionNumberLayout.visibility = View.VISIBLE binding.projectNumberLayout.visibility = View.VISIBLE // 为区域号输入框添加输入验证 binding.regionNumberEt.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} override fun beforeTextChanged( s: CharSequence?, start: Int, count: Int, after: Int ) { } override fun onTextChanged( s: CharSequence?, start: Int, before: Int, count: Int ) { } override fun afterTextChanged(s: Editable?) { val text = s.toString() if (text.length > 12) { @@ -68,35 +85,96 @@ } } }) // 为项目号输入框添加输入验证(范围1-255) binding.projectNumberEt.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged( s: CharSequence?, start: Int, count: Int, after: Int ) { } override fun onTextChanged( s: CharSequence?, start: Int, before: Int, count: Int ) { } override fun afterTextChanged(s: Editable?) { val text = s.toString() if (text.isNotEmpty()) { try { val number = text.toInt() if (number > 255) { binding.projectNumberEt.setText("255") binding.projectNumberEt.setSelection(3) } else if (number < 1 && text.length > 1) { binding.projectNumberEt.setText("1") binding.projectNumberEt.setSelection(1) } } catch (e: NumberFormatException) { // 如果输入的不是数字,清空 binding.projectNumberEt.setText("") } } } }) } CardCommon.CHECK_CARD, CardCommon.DEBUG_CARD, CardCommon.CLEAN_CARD_TYPE -> { // 检查卡、调试卡、清零卡:隐藏区域号输入框,只显示卡地址和备注 // 检查卡、调试卡、清零卡:隐藏区域号和项目号输入框,只显示卡地址和备注 binding.regionNumberLayout.visibility = View.GONE binding.projectNumberLayout.visibility = View.GONE } else -> { // 其他卡类型:隐藏区域号输入框 // 其他卡类型:隐藏区域号和项目号输入框 binding.regionNumberLayout.visibility = View.GONE binding.projectNumberLayout.visibility = View.GONE } } binding.btnNext.setOnClickListener { if (viewModel.cardNumber.value.isNullOrEmpty()) { if (viewModel.cardNumber.get().isNullOrEmpty()) { ToastUtil.show("请先读取卡号") } else if (cardType == CardCommon.REGION_CARD) { // 区域表号卡需要验证区域号 val regionNumber = viewModel.regionNumber.value // 区域表号卡需要验证区域号和项目号 val regionNumber = viewModel.regionNumber.get() val projectNumber = viewModel.projectNumber.get() if (regionNumber.isNullOrEmpty()) { ToastUtil.show("请输入区域号") } else if (regionNumber.length != 12) { ToastUtil.show("区域号必须为12位数字") } else if (projectNumber.isNullOrEmpty()) { ToastUtil.show("请输入项目号") } else { postCardData(cardType, viewModel.cardNumber.value!!, getRemark(), regionNumber) try { val projectNum = projectNumber.toInt() if (projectNum < 1 || projectNum > 255) { ToastUtil.show("项目号必须在1-255范围内") } else { postCardData( cardType, viewModel.cardNumber.get()!!, getRemark(), regionNumber, projectNumber ) } } catch (e: NumberFormatException) { ToastUtil.show("项目号必须为数字") } } } else { // 其他卡类型(包括调试卡、检查卡、清零卡)不需要区域号 postCardData(cardType, viewModel.cardNumber.value!!, getRemark()) // 其他卡类型(包括调试卡、检查卡、清零卡)不需要区域号和项目号 postCardData(cardType, viewModel.cardNumber.get()!!, getRemark()) } } } @@ -115,7 +193,7 @@ /** * 获取备注信息 */ fun getRemark(): String = viewModel.remark.value ?: "" fun getRemark(): String = viewModel.remark.get() ?: "" override fun onNfcBack(intent: Intent) { // 处理NFC读取结果 @@ -132,81 +210,134 @@ } private fun bytesToHexString(bytes: ByteArray?): String? { if (bytes == null || bytes.isEmpty()) return null val sb = StringBuilder() for (b in bytes) { sb.append(String.format("%02X", b)) } return sb.toString() } /** * 提交数据 - 不带区域号的版本 */ fun postCardData(cardType: String, cardAddr: String, remark: String) { postCardData(cardType, cardAddr, remark, null) } /** * 提交数据 - 带区域号的版本 */ fun postCardData(cardType: String, cardAddr: String, remark: String, regionNumber: String?) { val map = mutableMapOf<String, Any>() if (cardAddr.isNotEmpty()) { map["cardAddr"] = cardAddr private fun bytesToHexString(bytes: ByteArray?): String? { if (bytes == null || bytes.isEmpty()) return null val sb = StringBuilder() for (b in bytes) { sb.append(String.format("%02X", b)) } return sb.toString() } if (cardType.isNotEmpty()) { // map["cardType"] = cardType map["cardType"] = "5" /** * 提交数据 - 不带区域号的版本 */ fun postCardData(cardType: String, cardAddr: String, remark: String) { postCardData(cardType, cardAddr, remark, null, null) } if (remark.isNotEmpty()) { map["remarks"] = remark /** * 提交数据 - 带区域号的版本 */ fun postCardData(cardType: String, cardAddr: String, remark: String, regionNumber: String?) { postCardData(cardType, cardAddr, remark, regionNumber, null) } // 如果是区域表号卡并且有区域号,添加到请求参数中 if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) { map["regionNumber"] = regionNumber } // 使用正确的类型参数 ApiManager.getInstance().requestPostLoading( this, "/sell/card/create_manager_card", String::class.java, map, object : SubscriberListener<BaseResponse<String>>() { override fun onNext(t: BaseResponse<String>) { if (t.success) { var intent = Intent(this@ManagerReadActivity, NfcWreatActivity::class.java).apply { putExtra("cardAddr", cardAddr) putExtra("orderId", t.content) putExtra("cardType", cardType) if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) { putExtra("regionNumber", regionNumber) } /** * 提交数据 - 完整版本,支持区域号和项目号 */ fun postCardData( cardType: String, cardAddr: String, remark: String, regionNumber: String?, projectNumber: String? ) { val map = mutableMapOf<String, Any>() if (cardAddr.isNotEmpty()) { map["cardAddr"] = cardAddr } if (cardType.isNotEmpty()) { // 根据卡类型设置对应的数字编号 val cardTypeNumber = when (cardType) { CardCommon.REGION_CARD -> "2" // 设置区域表号卡 CardCommon.ELECTRIC_PRICE_CARD -> "3" // 取数卡 CardCommon.CHECK_CARD -> "4" // 检查卡 CardCommon.DEBUG_CARD -> "5" // 测试卡 CardCommon.CLEAN_CARD_TYPE -> "6" // 清零卡 CardCommon.IP_CARD -> "7" // IP设置卡 CardCommon.AREA_CARD -> "8" // 域名设置卡(区域设置卡) CardCommon.GPS_CARD -> "9" // GPS卡 CardCommon.VALVE_TIME_CARD -> "10" // 时间配置卡(配置开关阀时间) else -> "5" // 默认值 } map["cardType"] = cardTypeNumber } if (remark.isNotEmpty()) { map["remarks"] = remark } // 如果是区域表号卡并且有区域号,添加到请求参数中 if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) { map["regionNumber"] = regionNumber } // 如果是区域表号卡并且有项目号,添加到请求参数中 if (cardType == CardCommon.REGION_CARD && !projectNumber.isNullOrEmpty()) { map["projectNumber"] = projectNumber } map["protocol"] = protocol map["securityCode"]="A0B1C289" // 使用正确的类型参数 ApiManager.getInstance().requestPostLoading( this, "terminal/card/createManagementCard", String::class.java, map, object : SubscriberListener<BaseResponse<String>>() { override fun onNext(t: BaseResponse<String>) { if (t.success) { var intent = Intent(this@ManagerReadActivity, NfcWreatActivity::class.java).apply { putExtra("cardAddr", cardAddr) putExtra("orderNumber", t.content) putExtra("cardType", cardType) // 根据卡类型设置操作类型代码 val operationTypeCode = when (cardType) { CardCommon.REGION_CARD -> 100 // 区域表号卡操作类型 CardCommon.CHECK_CARD -> 101 // 检查卡操作类型 CardCommon.DEBUG_CARD -> 102 // 调试卡操作类型 CardCommon.CLEAN_CARD_TYPE -> 103 // 清零卡操作类型 CardCommon.IP_CARD -> 104 // IP设置卡操作类型 CardCommon.AREA_CARD -> 105 // 域名设置卡操作类型 CardCommon.GPS_CARD -> 106 // GPS卡操作类型 CardCommon.VALVE_TIME_CARD -> 107 // 时间配置卡操作类型 CardCommon.ELECTRIC_PRICE_CARD -> 108 // 取数卡操作类型 else -> -1 } putExtra("operationTypeCode", operationTypeCode) // 传递区域号和项目号(仅当是区域表号卡时) if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) { putExtra("regionNumber", regionNumber) } if (cardType == CardCommon.REGION_CARD && !projectNumber.isNullOrEmpty()) { putExtra("projectNumber", projectNumber) } } this@ManagerReadActivity.finish() startActivity(intent) } else { // 处理搜索失败的情况 ToastUtil.show(t.msg) } this@ManagerReadActivity.finish() startActivity(intent) } else { // 处理搜索失败的情况 ToastUtil.show(t.msg) } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("接口调取失败: ${e?.message ?: "未知错误"}") } } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}") } } ) ) } } } generallibrary/src/main/java/com/dayu/general/activity/NewCard2Activity.kt
@@ -24,6 +24,7 @@ import com.dayu.general.databinding.ActivityNewCardGeBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.tool.BaseCommon.Companion.protocol import com.dayu.general.tool.CardCommon.Companion.USER_CARD_TYPE_1 import com.dayu.general.tool.CardOperationType import com.dayu.general.tool.NfcReadHelper @@ -170,7 +171,7 @@ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", "terminal/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { @@ -323,7 +324,7 @@ params["amount"] = rechargeAmount // 充值金额(元) params["paymentId"] = paymentId // 支付方式ID params["remarks"] = remark // 备注 params["protocol"] = "p206V1_0_1" // 协议 params["protocol"] = protocol // 协议 params["operator"] = BaseApplication.userId // 操作人ID // 执行卡片激活API请求 generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -7,7 +7,11 @@ import com.dayu.baselibrary.tools.nfc.NFCCallBack import com.dayu.baselibrary.utils.MornyUtil import com.dayu.baselibrary.utils.ToastUtil import com.dayu.general.BaseApplication import com.dayu.general.bean.card.AreaCard import com.dayu.general.bean.card.CheckCard import com.dayu.general.bean.card.ClearCard import com.dayu.general.bean.card.DebugCard import com.dayu.general.bean.card.UserCard import com.dayu.general.dao.BaseDaoSingleton import com.dayu.general.databinding.ActivityNfcWriteGeBinding @@ -20,39 +24,79 @@ import kotlinx.coroutines.launch /** * NFC写卡操作界面 * * 功能说明: * 1. 支持多种卡类型的写卡操作(开卡、充值、销卡、返还、补扣、补卡、检查卡、区域表号卡、调试卡等) * 2. 通过NFC技术将数据写入IC卡 * 3. 写卡成功后向服务器上报操作结果 * 4. 更新本地数据库中的写卡状态 * * @author: zuo * @date: 2021/3/30 * @description:写卡界面 * @description: 写卡界面 */ class NfcWreatActivity : BaseNfcActivity() { /** 数据绑定对象 */ var binding: ActivityNfcWriteGeBinding? = null /** 卡类型标识 */ var cardType = "" /** 卡地址/卡号 */ var cardAddr = "" /** 卡工本费(分为单位) */ var cardFee = 0 // 充值相关金额 // ==================== 充值相关金额 ==================== /** 充值金额(元) */ private var rechargeAmount = 0.0 /** 赠送金额(元) */ private var bonusAmount = 0.0 // 销卡相关信息 // ==================== 销卡相关信息 ==================== /** 退款金额(元) */ private var refundAmount = 0.0 /** 卡内余额(元) */ private var cardBalance = 0.0 // 返还相关信息 // ==================== 返还相关信息 ==================== /** 返还金额(元) */ private var returnAmount = 0.0 // 补扣相关信息 // ==================== 补扣相关信息 ==================== /** 补扣金额(元) */ private var deductAmount = 0.0 // 补卡相关信息 // ==================== 补卡相关信息 ==================== /** 补卡工本费(元) */ private var cardCost = 0.0 /** 补卡金额(元) */ private var reissueAmount = 0.0 //订单编号 /** 订单编号 */ var orderNumber = "" /** 用户卡对象,包含要写入卡内的所有数据 */ private lateinit var userCard: UserCard private var operationTypeCode = -1; /** 操作类型代码 */ private var operationTypeCode = -1 /** 操作类型枚举 */ private var operationType: CardOperationType? = null // ==================== 管理卡制作相关参数 ==================== /** 区域号(12位数字) */ private var regionNumber: String = "" /** 项目号(1-255) */ private var projectNumber: String = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -62,9 +106,11 @@ } /** * 获取数据 * 获取传入的初始化数据 * 从Intent中提取写卡所需的各种参数 */ private fun getInitData() { // 获取基本卡信息 cardType = intent?.getStringExtra("cardType") ?: "" cardAddr = intent?.getStringExtra("cardAddr") ?: "" operationTypeCode = intent?.getIntExtra("operationTypeCode", -1) ?: -1 @@ -89,185 +135,282 @@ cardCost = intent?.getDoubleExtra("cardCost", 0.0) ?: 0.0 reissueAmount = intent?.getDoubleExtra("reissueAmount", 0.0) ?: 0.0 // 获取卡工本费 if (intent?.hasExtra("cardFee") == true) { cardFee = intent?.getIntExtra("cardFee", 0) ?: 0 } // 获取用户卡对象(兼容不同Android版本) if (intent?.hasExtra("userCard") == true) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { userCard = intent?.getSerializableExtra("userCard", UserCard::class.java)!! } else { userCard = (intent?.getSerializableExtra("userCard") as? UserCard)!! } } // 获取区域号和项目号 regionNumber = intent?.getStringExtra("regionNumber") ?: "" projectNumber = intent?.getStringExtra("projectNumber") ?: "" // 验证orderNumber不能为空 if (orderNumber.isEmpty()) { ToastUtil.show("订单号不能为空,请重新操作") finish() return } // 根据操作类型设置界面显示内容 if (operationTypeCode != -1) { when (operationType) { CardOperationType.CleanCard -> { val textData = StringBuilder() // 判断是否来自销卡操作(有退款金额或卡内余额信息) if (refundAmount > 0 || cardBalance > 0) { textData.append("销卡清零操作\n") textData.append("卡地址:$cardAddr\n") if (cardBalance > 0) { textData.append("卡内余额:${String.format("%.2f", cardBalance)}元\n") } if (refundAmount > 0) { textData.append("退款金额:${String.format("%.2f", refundAmount)}元") } else { textData.append("无退款金额") } } else { textData.append("清零卡写卡") } binding?.cardData?.text = textData.toString() } CardOperationType.OpenCard -> { var textData = StringBuilder() textData.append("用户开卡\n") if (cardFee != 0) { textData.append("工本费:" + cardFee + "元\n") } if (userCard.balance != 0) { textData.append("充值金额:" + MornyUtil.changeF2Y(userCard.balance) + "元") } binding?.cardData?.text = textData.toString() } CardOperationType.Recharge -> { var textData = StringBuilder() textData.append("用户充值\n") // 显示充值金额 if (rechargeAmount > 0) { textData.append( "充值金额:" + String.format( "%.2f", rechargeAmount ) + "元\n" ) } // 显示赠送金额 if (bonusAmount > 0) { textData.append("赠送金额:" + String.format("%.2f", bonusAmount) + "元\n") } // 显示总金额(写入卡内的总余额) if (userCard.balance != 0) { val totalBalanceInYuan = userCard.balance / 100.0 // 转换为元 textData.append( "充值后余额:" + MornyUtil.changeF2Y(userCard.balance)+ "元" ) } binding?.cardData?.text = textData.toString() } CardOperationType.CancelCard -> { var textData = StringBuilder() textData.append("销卡\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("退款金额:" + refundAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.ReturnCard -> { var textData = StringBuilder() textData.append("返还\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("返还金额:" + returnAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.DeductCard -> { var textData = StringBuilder() textData.append("补扣\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("补扣金额:" + deductAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.ReplaceCard -> { var textData = StringBuilder() textData.append("补卡\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") if (cardCost > 0) { textData.append("工本费:" + String.format("%.2f", cardCost) + "元\n") } if (reissueAmount > 0) { textData.append("补卡金额:" + String.format("%.2f", reissueAmount) + "元") } binding?.cardData?.text = textData.toString() } CardOperationType.CheckCard -> { var textData = StringBuilder() textData.append("检查卡制作") binding?.cardData?.text = textData.toString() } CardOperationType.RegionCard -> { var textData = StringBuilder() textData.append("区域表号卡制作") binding?.cardData?.text = textData.toString() } CardOperationType.DebugCard -> { var textData = StringBuilder() textData.append("调试卡制作") binding?.cardData?.text = textData.toString() } null -> TODO() } setupUIForOperationType() } } /** * 根据操作类型设置界面显示内容 * 为不同的卡操作类型显示相应的提示信息 */ private fun setupUIForOperationType() { when (operationType) { CardOperationType.CleanCardMake -> { val textData = StringBuilder() // 判断是否来自销卡操作(有退款金额或卡内余额信息) if (refundAmount > 0 || cardBalance > 0) { textData.append("销卡清零操作\n") textData.append("卡地址:$cardAddr\n") if (cardBalance > 0) { textData.append("卡内余额:${String.format("%.2f", cardBalance)}元\n") } if (refundAmount > 0) { textData.append("退款金额:${String.format("%.2f", refundAmount)}元") } else { textData.append("无退款金额") } } else { textData.append("清零卡写卡") } binding?.cardData?.text = textData.toString() } CardOperationType.OpenCard -> { // 开卡操作显示信息 var textData = StringBuilder() textData.append("用户开卡\n") if (cardFee != 0) { textData.append("工本费:" + cardFee + "元\n") } if (userCard.balance != 0) { textData.append("充值金额:" + MornyUtil.changeF2Y(userCard.balance) + "元") } binding?.cardData?.text = textData.toString() } CardOperationType.Recharge -> { // 充值操作显示信息 var textData = StringBuilder() textData.append("用户充值\n") // 显示充值金额 if (rechargeAmount > 0) { textData.append( "充值金额:" + String.format( "%.2f", rechargeAmount ) + "元\n" ) } // 显示赠送金额 if (bonusAmount > 0) { textData.append("赠送金额:" + String.format("%.2f", bonusAmount) + "元\n") } // 显示总金额(写入卡内的总余额) if (userCard.balance != 0) { val totalBalanceInYuan = userCard.balance / 100.0 // 转换为元 textData.append( "充值后余额:" + MornyUtil.changeF2Y(userCard.balance) + "元" ) } binding?.cardData?.text = textData.toString() } CardOperationType.CancelCard -> { // 销卡操作显示信息 var textData = StringBuilder() textData.append("销卡\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("退款金额:" + refundAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.SUPPLEMENT -> { // 返还操作显示信息 var textData = StringBuilder() textData.append("返还\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("返还金额:" + returnAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.DeductCard -> { // 补扣操作显示信息 var textData = StringBuilder() textData.append("补扣\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("补扣金额:" + deductAmount + "元") binding?.cardData?.text = textData.toString() } CardOperationType.ReplaceCard -> { // 补卡操作显示信息 var textData = StringBuilder() textData.append("补卡\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") if (cardCost > 0) { textData.append("工本费:" + String.format("%.2f", cardCost) + "元\n") } if (reissueAmount > 0) { textData.append("补卡金额:" + String.format("%.2f", reissueAmount) + "元") } binding?.cardData?.text = textData.toString() } CardOperationType.CheckCardMake -> { // 检查卡制作显示信息 var textData = StringBuilder() textData.append("检查卡制作") binding?.cardData?.text = textData.toString() } CardOperationType.RegionCardMake -> { // 区域表号卡制作显示信息 var textData = StringBuilder() textData.append("区域表号卡制作\n") if (regionNumber.isNotEmpty()) { textData.append("区域号:$regionNumber\n") } if (projectNumber.isNotEmpty()) { textData.append("项目号:$projectNumber") } binding?.cardData?.text = textData.toString() } CardOperationType.DebugCardMake -> { // 调试卡制作显示信息 var textData = StringBuilder() textData.append("调试卡制作") binding?.cardData?.text = textData.toString() } CardOperationType.CheckCardMake -> { var textData = StringBuilder() textData.append("制作检查卡") binding?.cardData?.text = textData.toString() } CardOperationType.DebugCardMake -> { var textData = StringBuilder() textData.append("制作调试卡") binding?.cardData?.text = textData.toString() } CardOperationType.CleanCardMake -> { var textData = StringBuilder() textData.append("制作清零卡") binding?.cardData?.text = textData.toString() } CardOperationType.IpCardMake -> { var textData = StringBuilder() textData.append("制作IP设置卡") binding?.cardData?.text = textData.toString() } CardOperationType.AreaCardMake -> { var textData = StringBuilder() textData.append("制作域名设置卡") binding?.cardData?.text = textData.toString() } CardOperationType.GpsCardMake -> { var textData = StringBuilder() textData.append("制作GPS卡") binding?.cardData?.text = textData.toString() } CardOperationType.ValveTimeCardMake -> { var textData = StringBuilder() textData.append("制作时间配置卡") binding?.cardData?.text = textData.toString() } CardOperationType.ElectricPriceCardMake -> { var textData = StringBuilder() textData.append("制作取数卡") binding?.cardData?.text = textData.toString() } null -> TODO() CardOperationType.MANAGEMENT_CARD_WRITE -> TODO() } } /** * NFC刷卡回调处理 * 当用户将卡片贴近设备时触发此方法 * * @param intent NFC意图,包含卡片信息 */ override fun onNfcBack(intent: Intent) { // 读取卡号 val nfcReadHelper = NfcReadHelper.getInstance(intent, this) // 使用正常的getCardNumber()方法,它会自动关闭连接 val cardNumber = nfcReadHelper.getCardNumber() // 验证卡号是否与预期一致 if (cardNumber.isNotEmpty() && cardNumber == cardAddr) { val nfcWreatHelper = NfcWreatHelper.getInstance(intent, this) // 根据操作类型执行相应的写卡操作 when (operationType) { CardOperationType.CleanCard -> { CardOperationType.CleanCardMake -> { // 清零卡操作(暂未实现具体逻辑) } CardOperationType.OpenCard -> { // 开卡操作:将用户信息写入卡片 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("写卡失败: ${msg ?: "未知错误"}") } } } }) } CardOperationType.Recharge -> { // 充值操作:更新卡内余额 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 充值写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("充值写卡失败: ${msg ?: "未知错误"}") } @@ -277,14 +420,16 @@ } CardOperationType.CancelCard -> { // 销卡操作:将卡类型设置为无效 var userCard = UserCard() userCard.cardType = "00"; userCard.cardType = "00" // 设置为无效卡类型 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 销卡写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("销卡写卡失败: ${msg ?: "未知错误"}") } @@ -293,13 +438,15 @@ }) } CardOperationType.ReturnCard -> { CardOperationType.SUPPLEMENT -> { // 返还操作:更新卡内余额 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 返还写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("返还写卡失败: ${msg ?: "未知错误"}") } @@ -309,12 +456,14 @@ } CardOperationType.DeductCard -> { // 补扣操作:更新卡内余额 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 补扣写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("补扣写卡失败: ${msg ?: "未知错误"}") } @@ -324,12 +473,14 @@ } CardOperationType.ReplaceCard -> { // 补卡操作:将原卡数据写入新卡 nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { postCardData(cardAddr) // 补卡写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("补卡写卡失败: ${msg ?: "未知错误"}") } @@ -338,33 +489,115 @@ }) } CardOperationType.CheckCard -> { // 检查卡写卡逻辑 ToastUtil.show("检查卡写卡成功!") postCardData(cardAddr) CardOperationType.CheckCardMake -> { // 检查卡写卡逻辑(功能卡,无需写入用户数据) var checkCard = CheckCard() nfcWreatHelper.writeDataAsync( checkCard.getZeroBytes(), 7, 0, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { // 检查卡写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("检查卡写卡失败: ${msg ?: "未知错误"}") } } } }) } CardOperationType.RegionCard -> { // 区域表号卡写卡逻辑 ToastUtil.show("区域表号卡写卡成功!") postCardData(cardAddr) CardOperationType.RegionCardMake -> { // 区域表号卡写卡逻辑(功能卡,无需写入用户数据) var areaCard = AreaCard() areaCard.areaNumber = regionNumber.toInt() areaCard.projectCode = projectNumber.toInt() nfcWreatHelper.writeDataAsync( areaCard.getZeroBytes(), 7, 0, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { // 区域表号卡写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("区域表号卡写卡失败: ${msg ?: "未知错误"}") } } } }) } CardOperationType.DebugCard -> { // 调试卡写卡逻辑 ToastUtil.show("调试卡写卡成功!") postCardData(cardAddr) CardOperationType.DebugCardMake -> { // 调试卡写卡逻辑(功能卡,无需写入用户数据) var debugCard = DebugCard() nfcWreatHelper.writeDataAsync( debugCard.getZeroBytes(), 7, 0, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 确保Toast在主线程中调用 runOnUiThread { if (flag) { // 调试卡写卡成功,更新写卡状态 updateCardWrittenStatus(cardAddr) } else { ToastUtil.show("调试卡写卡失败: ${msg ?: "未知错误"}") } } } }) } // 新的管理卡制作操作类型处理 CardOperationType.RegionCardMake, CardOperationType.CheckCardMake, CardOperationType.CleanCardMake, CardOperationType.IpCardMake, CardOperationType.AreaCardMake, CardOperationType.GpsCardMake, CardOperationType.ValveTimeCardMake, CardOperationType.ElectricPriceCardMake -> { // 管理卡写卡逻辑(功能卡,无需写入用户数据) val operationName = when (operationType) { CardOperationType.RegionCardMake -> "区域表号卡" CardOperationType.CheckCardMake -> "检查卡" CardOperationType.DebugCardMake -> "调试卡" CardOperationType.CleanCardMake -> "清零卡" CardOperationType.IpCardMake -> "IP设置卡" CardOperationType.AreaCardMake -> "域名设置卡" CardOperationType.GpsCardMake -> "GPS卡" CardOperationType.ValveTimeCardMake -> "时间配置卡" CardOperationType.ElectricPriceCardMake -> "取数卡" else -> "管理卡" } ToastUtil.show("${operationName}写卡成功!") updateCardWrittenStatus(cardAddr) } null -> TODO() CardOperationType.MANAGEMENT_CARD_WRITE -> TODO() } } else { // 卡号不匹配,提示用户 ToastUtil.show("卡片错误,当前刷的卡与刚刚的卡不一致") } } /** * 更新CardRegistrationBean中的isCardWritten状态为true * 更新本地数据库中的写卡状态 * 将CardRegistrationBean中的isCardWritten状态设置为true * 然后跳转到写卡成功界面,并通知MainActivity调用postCardData * * @param cardNumber 卡号 */ private fun updateCardWrittenStatus(cardNumber: String) { lifecycleScope.launch { @@ -372,27 +605,36 @@ val cardRegistrationDao = BaseDaoSingleton.getInstance(this@NfcWreatActivity) .cardRegistrationDao() // 根据卡号查找CardRegistrationBean记录 val cardRegistration = cardRegistrationDao.getByCardNumber(cardNumber) // 根据订单号查找CardRegistrationBean记录 val cardRegistration = cardRegistrationDao.getByOrderId(orderNumber) if (cardRegistration != null) { // 创建更新后的CardRegistrationBean对象,将isCardWritten设置为true val updatedCardRegistration = cardRegistration.copy(isCardWritten = true) // 更新数据库记录 cardRegistrationDao.update(updatedCardRegistration) // 在主线程中关闭Activity // 在主线程中关闭Activity并跳转到成功页面 runOnUiThread { setResult(RESULT_OK) finish() // 跳转到写卡成功界面 Intent(this@NfcWreatActivity, CardWriteSuccessActivity::class.java).apply { putExtra("cardNumber", cardNumber) putExtra("userCard", userCard) if (::userCard.isInitialized) { putExtra("userCard", userCard) } putExtra("operationTypeCode", operationTypeCode) startActivity(this) } // 通知MainActivity调用postCardData notifyMainActivityToPostCardData(cardNumber) } } } catch (e: Exception) { // 记录异常信息 CrashReport.postCatchedException(e) e.printStackTrace() runOnUiThread { @@ -402,40 +644,28 @@ } } fun postCardData(cardAddr: String) { val map = mutableMapOf<String, Any>() if (cardAddr.isNotEmpty()) { map["cardAddr"] = cardAddr } map["operateType"] = operationTypeCode if (orderNumber.isNotEmpty()) { map["orderNumber"] = orderNumber } // 使用正确的类型参数 ApiManager.getInstance().requestPostLoading( this, "terminal/card/termCallBack", String::class.java, map, object : SubscriberListener<BaseResponse<String>>() { override fun onNext(t: BaseResponse<String>) { if (t.success) { updateCardWrittenStatus(cardAddr) } else { // 处理搜索失败的情况 ToastUtil.show(t.msg) } } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("上报失败: ${e?.message ?: "未知错误"}") } /** * 通知MainActivity调用postCardData上报写卡结果 * * @param cardNumber 卡号 */ private fun notifyMainActivityToPostCardData(cardNumber: String) { try { val mainActivity = BaseApplication.getMainActivity() if (mainActivity != null) { // 调用MainActivity的postCardData方法 mainActivity.postCardData( cardAddr = cardNumber, operationTypeCode = operationTypeCode, orderNumber = orderNumber, regionNumber = regionNumber, projectNumber = projectNumber ) } ) } catch (e: Exception) { e.printStackTrace() CrashReport.postCatchedException(e) } } generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
@@ -154,7 +154,7 @@ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "sell/paymentmethod/get", "terminal/paymentmethod/get", PaymentMethodResponse::class.java, null, object : SubscriberListener<BaseResponse<PaymentMethodResponse>>() { @@ -322,6 +322,25 @@ 0.0 } // 获取当前余额(转换为元) val currentBalance = userCard?.let { // 将分转换为元 it.balance / 100.0 } ?: run { // 如果用户卡为空,则使用服务器返回的余额 cardInfo?.balance ?: 0.0 } // 计算充值后的总余额 val totalAmountAfterRecharge = currentBalance + rechargeAmount + bonusAmount // 检查是否超过最大余额限制9999.99元 if (totalAmountAfterRecharge > 9999.99) { val maxRechargeAmount = 9999.99 - currentBalance ToastUtil.show("充值失败:充值后余额不能超过9999.99元\n当前余额:${String.format("%.2f", currentBalance)}元\n最多可充值:${String.format("%.2f", maxRechargeAmount)}元") return } // 调用充值接口 callRechargeApi(rechargeAmount, bonusAmount) } generallibrary/src/main/java/com/dayu/general/bean/net/NewCardInfo.kt
@@ -3,9 +3,7 @@ // 支付方式数据类 data class PaymentMethod( val id: Long, val name: String, val remarks: String, val deleted: Int val name: String ) // 支付方式接口返回数据类 generallibrary/src/main/java/com/dayu/general/model/CardInfoModel.kt
@@ -1,28 +1,34 @@ package com.dayu.general.model import androidx.lifecycle.MutableLiveData import androidx.databinding.ObservableField import androidx.lifecycle.ViewModel class CardInfoModel : ViewModel() { val cardNumber = MutableLiveData<String>() val remark = MutableLiveData<String>() val regionNumber = MutableLiveData<String>() val cardNumber = ObservableField<String>() val remark = ObservableField<String>() val regionNumber = ObservableField<String>() val projectNumber = ObservableField<String>() init { cardNumber.value = "" remark.value = "" regionNumber.value = "" cardNumber.set("") remark.set("") regionNumber.set("") projectNumber.set("") } fun setCardNumber(number: String) { cardNumber.value = number cardNumber.set(number) } fun setRemark(remarkText: String) { remark.value = remarkText remark.set(remarkText) } fun setRegionNumber(regionNum: String) { regionNumber.value = regionNum regionNumber.set(regionNum) } fun setProjectNumber(projectNum: String) { projectNumber.set(projectNum) } } generallibrary/src/main/java/com/dayu/general/tool/BaseCommon.kt
@@ -10,7 +10,7 @@ val YuanMo: Int = 1 val QiHe: Int = 2 val protocol:String="p206V1_0_1" } generallibrary/src/main/java/com/dayu/general/tool/CardOperationType.kt
@@ -10,11 +10,19 @@ object CancelCard : CardOperationType(3, "销卡") object ReplaceCard : CardOperationType(4, "补卡") object DeductCard : CardOperationType(5, "补扣") object CleanCard : CardOperationType(6, "清零卡") object CheckCard : CardOperationType(7, "检查卡") object ReturnCard : CardOperationType(8, "返还") object RegionCard : CardOperationType(9, "区域表号卡") object DebugCard : CardOperationType(10, "调试卡") object SUPPLEMENT : CardOperationType(6, "返还") object MANAGEMENT_CARD_WRITE : CardOperationType(7, "管理类型卡写卡") // 管理卡制作操作类型(使用100+的代码) object RegionCardMake : CardOperationType(100, "制作区域表号卡") object CheckCardMake : CardOperationType(101, "制作检查卡") object DebugCardMake : CardOperationType(102, "制作调试卡") object CleanCardMake : CardOperationType(103, "制作清零卡") object IpCardMake : CardOperationType(104, "制作IP设置卡") object AreaCardMake : CardOperationType(105, "制作域名设置卡") object GpsCardMake : CardOperationType(106, "制作GPS卡") object ValveTimeCardMake : CardOperationType(107, "制作时间配置卡") object ElectricPriceCardMake : CardOperationType(108, "制作取数卡") companion object { fun fromCode(code: Int): CardOperationType? { @@ -24,11 +32,18 @@ 3 -> CancelCard 4 -> ReplaceCard 5 -> DeductCard 6 -> CleanCard 7 -> CheckCard 8 -> ReturnCard 9 -> RegionCard 10 -> DebugCard 6 -> SUPPLEMENT 7 -> MANAGEMENT_CARD_WRITE // 管理卡制作操作类型 100 -> RegionCardMake 101 -> CheckCardMake 102 -> DebugCardMake 103 -> CleanCardMake 104 -> IpCardMake 105 -> AreaCardMake 106 -> GpsCardMake 107 -> ValveTimeCardMake 108 -> ElectricPriceCardMake else -> null } } generallibrary/src/main/java/com/dayu/general/tool/NfcWreatHelper.kt
@@ -78,24 +78,20 @@ * @param b 书写的块(从0开始数) * @param callback 操作结果回调 */ fun writeDataAsync(str: ByteArray?, a: Int, b: Int, callback: (Boolean) -> Unit): Disposable { fun writeDataAsync(str: ByteArray?, a: Int, b: Int, callback: NFCCallBack): Disposable { showLoading() val disposable = Observable.fromCallable { writeData(str, a, b, object : NFCCallBack { override fun isSusses(flag: Boolean, msg: String?) { // 这个回调在IO线程中,不处理UI相关操作 } }) writeData(str, a, b, callback) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ result -> hideLoading() callback(result) callback.isSusses(result, if (result) "写卡成功" else "写卡失败") }, { error -> hideLoading() error.printStackTrace() callback(false) callback.isSusses(false, "写卡异常: ${error.message}") }) compositeDisposable.add(disposable) @@ -112,7 +108,7 @@ */ fun writeData(str: ByteArray?, a: Int, b: Int, callBack: NFCCallBack): Boolean { try { return adapter.writeData(str, a, b, false, callBack) return adapter.writeData(str, a, b, true, callBack) } catch (e: Exception) { e.printStackTrace() } generallibrary/src/main/res/layout/activity_card_replace.xml
@@ -107,7 +107,7 @@ android:layout_above="@+id/bottom_button_container" android:layout_below="@+id/titleBar" android:orientation="vertical" android:visibility="gone"> android:visibility="visible"> <ScrollView android:layout_width="match_parent" @@ -125,40 +125,40 @@ <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="6dp" app:cardElevation="1dp"> app:cardCornerRadius="8dp" app:cardElevation="3dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="14dp"> android:padding="20dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginBottom="16dp" android:text="卡片信息" android:textColor="@color/base_blue_bg" android:textSize="17sp" android:textSize="20sp" android:textStyle="bold" /> <!-- 新卡卡地址 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="8dp"> android:padding="12dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="新卡卡地址:" android:textColor="#333333" android:textSize="15sp" android:textSize="17sp" android:textStyle="bold" /> <TextView @@ -167,26 +167,29 @@ android:layout_height="wrap_content" android:layout_weight="1" android:background="#F5F5F5" android:padding="8dp" android:padding="12dp" android:text="--" android:textColor="#333333" android:textSize="15sp" android:textSize="17sp" android:textIsSelectable="true" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="2dp" android:layout_height="2dp" android:layout_marginTop="4dp" android:layout_marginBottom="4dp" android:background="@color/base_blue_bg" /> <!-- 持卡人和卡片状态 - 同一行显示 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:layout_marginBottom="1dp" android:layout_marginTop="4dp" android:layout_marginBottom="2dp" android:background="#FFFFFF" android:orientation="horizontal" android:padding="10dp"> android:padding="12dp"> <!-- 持卡人 --> <LinearLayout @@ -200,17 +203,17 @@ android:layout_height="wrap_content" android:text="持卡人" android:textColor="#333333" android:textSize="13sp" android:textSize="15sp" android:textStyle="bold" /> <TextView android:id="@+id/tv_user_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:layout_marginTop="6dp" android:text="--" android:textColor="#666666" android:textSize="15sp" /> android:textSize="17sp" /> </LinearLayout> <!-- 卡片状态 --> @@ -225,17 +228,18 @@ android:layout_height="wrap_content" android:text="卡片状态" android:textColor="#333333" android:textSize="13sp" android:textSize="15sp" android:textStyle="bold" /> <TextView android:id="@+id/tv_card_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:layout_marginTop="6dp" android:text="正常" android:textColor="#4CAF50" android:textSize="15sp" /> android:textSize="17sp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> @@ -243,18 +247,18 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="8dp"> android:padding="12dp"> <TextView android:layout_width="80dp" android:layout_width="90dp" android:layout_height="wrap_content" android:text="卡号:" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <TextView @@ -264,25 +268,25 @@ android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="14sp" /> android:textSize="16sp" /> </LinearLayout> <!-- 客户编号 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:layout_marginBottom="2dp" android:background="#FFFFFF" android:gravity="center_vertical" android:orientation="horizontal" android:padding="8dp"> android:padding="12dp"> <TextView android:layout_width="80dp" android:layout_width="90dp" android:layout_height="wrap_content" android:text="客户编号:" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <TextView @@ -292,24 +296,25 @@ android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="14sp" /> android:textSize="16sp" /> </LinearLayout> <!-- 手机号 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="8dp"> android:padding="12dp"> <TextView android:layout_width="80dp" android:layout_width="90dp" android:layout_height="wrap_content" android:text="手机号:" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <TextView @@ -319,24 +324,25 @@ android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="14sp" /> android:textSize="16sp" /> </LinearLayout> <!-- 卡内余额 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:background="#F8F9FA" android:layout_marginBottom="2dp" android:background="#FFFFFF" android:gravity="center_vertical" android:orientation="horizontal" android:padding="8dp"> android:padding="12dp"> <TextView android:layout_width="80dp" android:layout_width="90dp" android:layout_height="wrap_content" android:text="卡内余额:" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <TextView @@ -346,7 +352,7 @@ android:layout_weight="1" android:text="0.00元" android:textColor="#FF6B35" android:textSize="14sp" android:textSize="18sp" android:textStyle="bold" /> </LinearLayout> @@ -366,70 +372,44 @@ android:background="#FFFFFF" android:elevation="4dp" android:orientation="vertical" android:padding="16dp" android:visibility="gone"> <!-- 支付方式选择区域 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginBottom="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="支付方式" android:textColor="#333333" android:textSize="16sp" android:textStyle="bold" /> <RadioGroup android:id="@+id/payment_method_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- 支付方式RadioButton将动态添加 --> </RadioGroup> </LinearLayout> android:padding="20dp" android:visibility="visible"> <!-- 工本费和返回金额输入区域 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="16dp"> android:layout_marginBottom="20dp"> <!-- 返回金额输入 --> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginEnd="8dp" android:layout_marginEnd="12dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:layout_marginBottom="8dp" android:text="返回金额(元)" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <EditText android:id="@+id/et_return_amount" android:layout_width="match_parent" android:layout_height="48dp" android:layout_height="56dp" android:background="@drawable/edit_text_bg" android:hint="返回金额" android:inputType="numberDecimal" android:padding="12dp" android:padding="16dp" android:text="" android:textColor="#333333" android:textColorHint="#999999" android:textSize="16sp" /> android:textSize="18sp" /> </LinearLayout> <!-- 工本费输入 --> @@ -437,32 +417,31 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginEnd="8dp" android:layout_marginStart="12dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:layout_marginBottom="8dp" android:text="工本费(元)" android:textColor="#333333" android:textSize="14sp" android:textSize="16sp" android:textStyle="bold" /> <EditText android:id="@+id/et_card_cost" android:layout_width="match_parent" android:layout_height="48dp" android:layout_height="56dp" android:background="@drawable/edit_text_bg" android:hint="工本费" android:inputType="numberDecimal" android:padding="12dp" android:padding="16dp" android:text="" android:textColor="#333333" android:textColorHint="#999999" android:textSize="16sp" /> android:textSize="18sp" /> </LinearLayout> </LinearLayout> @@ -470,11 +449,11 @@ <Button android:id="@+id/btn_replace" android:layout_width="match_parent" android:layout_height="48dp" android:layout_height="56dp" android:background="@drawable/button_blue_bg" android:text="确认补卡" android:textColor="#FFFFFF" android:textSize="@dimen/big_text_size" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout> generallibrary/src/main/res/layout/activity_manager_read.xml
@@ -87,6 +87,34 @@ android:textSize="16sp" /> </LinearLayout> <!-- 项目号输入框 - 仅在区域表号卡时显示 --> <LinearLayout android:id="@+id/project_number_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp" android:visibility="gone"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="项目号:" android:textColor="#333333" android:textSize="16sp" /> <EditText android:id="@+id/project_number_et" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:hint="请输入项目号(1-255)" android:inputType="number" android:maxLength="3" android:text="@={viewModel.projectNumber}" android:textSize="16sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"