generallibrary/src/main/AndroidManifest.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/java/com/dayu/general/activity/CardReadActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/java/com/dayu/general/adapter/SearchUserListAdapter.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/java/com/dayu/general/bean/net/CardInfoResult.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/res/drawable/item_bg_selector.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/res/layout/activity_card_cancel.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/res/layout/activity_card_read.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
generallibrary/src/main/res/values/strings.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
generallibrary/src/main/AndroidManifest.xml
@@ -105,6 +105,18 @@ </intent-filter> </activity> <!-- 销卡页面 --> <activity android:name=".activity.CardCancelActivity" android:exported="false" android:launchMode="singleTop"> <intent-filter> <action android:name="android.nfc.action.ACTION_NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> </activity> <meta-data android:name="BUGLY_APP_VERSION" android:value="7.1" /> generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt
New file @@ -0,0 +1,357 @@ package com.dayu.general.activity import android.content.Context import android.content.Intent import android.os.Bundle import android.text.TextUtils import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.baselibrary.view.TipDialog import com.dayu.baselibrary.view.TitleBar import com.dayu.general.bean.net.CardInfoResult import com.dayu.general.databinding.ActivityCardCancelBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.tool.NfcReadHelper import com.dayu.general.bean.card.UserCard import com.dayu.general.tool.CardCommon /** * @author: zuo * @desc: 销卡Activity * @since: 2025/3/6 */ class CardCancelActivity : BaseNfcActivity() { private lateinit var binding: ActivityCardCancelBinding private var cardNumber: String? = null private var cardInfo: CardInfoResult? = null companion object { /** * 启动销卡Activity */ fun start(context: Context) { val intent = Intent(context, CardCancelActivity::class.java) context.startActivity(intent) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityCardCancelBinding.inflate(layoutInflater) setContentView(binding.root) initView() } private fun initView() { // 设置TitleBar的返回按钮点击事件 binding.titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) { finish() } // 设置销卡按钮点击事件 binding.btnCancelCard.setOnClickListener { performCardCancel() } } /** * 重置到读卡状态 */ private fun resetToReadingState() { binding.cardReadLL.visibility = android.view.View.VISIBLE binding.cardInfoContainer.visibility = android.view.View.GONE cardNumber = null cardInfo = null binding.etRefundAmount.setText("") binding.etRemarks.setText("") } /** * 显示确认对话框 */ private fun showConfirmDialog(message: String, onConfirm: () -> Unit) { val confirmDialog = TipDialog(this, message) { onConfirm() } confirmDialog.show() } override fun onNfcBack(intent: Intent?) { intent?.let { handleNfcIntent(it) } ?: run { showConfirmDialog("NFC数据异常,请重新刷卡") { } } } /** * 处理NFC刷卡信息 */ private fun handleNfcIntent(intent: Intent) { try { // 检查intent中是否包含NFC Tag if (intent.getParcelableExtra<android.nfc.Tag>(android.nfc.NfcAdapter.EXTRA_TAG) == null) { showConfirmDialog("未检测到NFC卡片,请确保卡片已正确放置") { } return } val nfcAdapter = NfcReadHelper.getInstance(intent, this) val cardTypeAndCardNumber = nfcAdapter.getCardTypeAndCardNumber() if (cardTypeAndCardNumber.isNullOrBlank() || !cardTypeAndCardNumber.contains(",")) { showConfirmDialog("卡片信息读取失败,请重新刷卡") { } return } val parts = cardTypeAndCardNumber.split(",") if (parts.size < 2) { showConfirmDialog("卡片信息格式异常,请重新刷卡") { } return } val cardNumber = parts[0] val cardType = parts[1] this.cardNumber = cardNumber if (cardNumber.isBlank()) { showConfirmDialog("卡号为空,无法进行操作,请重新刷卡") { } return } // 根据卡片类型进行不同处理 when (cardType) { CardCommon.USER_CARD_TYPE_1, CardCommon.USER_CARD_TYPE_2, CardCommon.USER_CARD_TYPE_3 -> { // 用户卡:解析卡内数据并调用接口 handleUserCard(cardNumber, cardType, nfcAdapter) } else -> { // 管理类卡不支持销卡 showConfirmDialog("该卡片类型不支持销卡操作") { resetToReadingState() } } } } catch (e: Exception) { showConfirmDialog("读卡异常:${e.message}") { } e.printStackTrace() } } /** * 处理用户卡 */ private fun handleUserCard(cardNumber: String, cardType: String, nfcAdapter: NfcReadHelper) { // 解析用户卡数据 val userCard = nfcAdapter.getUserCardData() if (userCard == null) { showConfirmDialog("解析卡片数据失败,请重新刷卡") { } return } // 输出用户卡内所有信息到日志 android.util.Log.d("CardCancelActivity", "=== 用户卡信息 ===") android.util.Log.d("CardCancelActivity", "卡号: $cardNumber") android.util.Log.d("CardCancelActivity", "卡片类型: $cardType") android.util.Log.d("CardCancelActivity", "卡内余额: ${userCard.balance}") android.util.Log.d("CardCancelActivity", "==================") // 根据卡号获取卡片详细信息 getCardInfo(cardNumber, cardType, userCard) } /** * 获取卡片详细信息(用户卡专用) */ private fun getCardInfo(cardNumber: String, cardType: String, userCard: UserCard) { val map = mutableMapOf<String, Any>() map["cardAddr"] = cardNumber ApiManager.getInstance().requestGetLoading( this, "terminal/card/readCard", CardInfoResult::class.java, map, object : SubscriberListener<BaseResponse<CardInfoResult>>() { override fun onNext(t: BaseResponse<CardInfoResult>) { if (t.success) { // 读卡成功,显示用户卡详细信息 showUserCardInfo(t.content, cardNumber, cardType, userCard) } else { // 处理获取失败的情况 handleCardInfoError(t.code, t.msg) } } override fun onError(e: Throwable?) { super.onError(e) showConfirmDialog("获取卡信息失败: ${e?.message ?: "网络异常,请检查网络连接"}") { } } } ) } /** * 显示用户卡片信息(包含卡内数据和接口返回数据) */ private fun showUserCardInfo( cardInfo: CardInfoResult?, cardNumber: String, cardType: String, userCard: UserCard ) { // 隐藏读卡提示,显示信息区域 binding.cardReadLL.visibility = android.view.View.GONE binding.cardInfoContainer.visibility = android.view.View.VISIBLE this.cardInfo = cardInfo binding.tvCardNumber.text = cardNumber userCard.let { card -> // 余额转换为元(原始数据可能是分) val balanceInYuan = if (card.balance > 1000) { String.format("%.2f", card.balance / 100.0) } else { card.balance.toString() } binding.tvCardBalance.text = "${balanceInYuan}元" // 默认退款金额设置为卡内余额 binding.etRefundAmount.setText(balanceInYuan) // 卡片状态 binding.tvCardStatus.text = "正常" binding.tvCardStatus.setTextColor(android.graphics.Color.parseColor("#4CAF50")) } // 显示服务器数据 cardInfo?.let { info -> binding.tvUserName.text = info.userName ?: "未知" binding.tvPhone.text = info.phone ?: "未绑定" // 根据status字段显示状态 val statusText = when (info.state) { 1 -> "正常" 2 -> "挂失" 3 -> "锁定" else -> "未知" } } } /** * 处理卡信息获取错误 */ private fun handleCardInfoError(code: String?, msg: String?) { val errorMessage: String = when (code) { "1001" -> { "该卡片未在系统中注册,无法进行销卡操作。" } else -> { when { msg.isNullOrBlank() -> "获取卡信息失败,请重新刷卡重试。" msg.contains("数据不存在") -> "该卡片未在系统中注册,无法进行销卡操作。" msg.contains("网络") -> "网络连接异常,请检查网络连接后重新刷卡。" msg.contains("超时") -> "网络请求超时,请重新刷卡重试。" else -> "获取卡信息失败:$msg\n\n请重新刷卡重试。" } } } // 显示错误信息的对话框 showConfirmDialog(errorMessage) { resetToReadingState() } } /** * 执行销卡操作 */ private fun performCardCancel() { // 验证输入 val refundAmountStr = binding.etRefundAmount.text.toString().trim() val remarks = binding.etRemarks.text.toString().trim() if (TextUtils.isEmpty(refundAmountStr)) { ToastUtil.showToast("请输入退款金额") return } val refundAmount = try { refundAmountStr.toDouble() } catch (e: NumberFormatException) { ToastUtil.showToast("请输入有效的退款金额") return } if (refundAmount < 0) { ToastUtil.showToast("退款金额不能为负数") return } if (TextUtils.isEmpty(remarks)) { ToastUtil.showToast("请输入备注信息") return } // 确认销卡 showConfirmDialog( "确认要销卡吗?\n\n卡号:${cardNumber}\n退款金额:${refundAmount}元\n备注:${remarks}\n\n销卡后此卡将无法再次使用!" ) { callCancelCardApi(refundAmount, remarks) } } /** * 调用销卡API接口 */ private fun callCancelCardApi(refundAmount: Double, remarks: String) { if (cardNumber.isNullOrBlank()) { ToastUtil.showToast("卡号信息异常,请重新刷卡") return } val map = mutableMapOf<String, Any>() map["cardNum"] = cardNumber!! map["refund"] = (refundAmount * 100).toInt() // 转换为分 map["refundType"] = 1838466162264350700L map["remarks"] = remarks map["operator"] = 2024090516595200300L ApiManager.getInstance().requestPostLoading( this, "terminal/card/termCancel", Boolean::class.java, map, object : SubscriberListener<BaseResponse<Boolean>>() { override fun onNext(t: BaseResponse<Boolean>) { if (t.success && t.content == true) { // 销卡成功 showConfirmDialog("销卡成功!\n\n退款金额:${refundAmount}元已退还") { finish() } } else { // 销卡失败 val errorMsg = if (t.msg.isNullOrBlank()) "销卡失败,请重试" else t.msg showConfirmDialog("销卡失败:$errorMsg") { } } } override fun onError(e: Throwable?) { super.onError(e) showConfirmDialog("销卡请求失败: ${e?.message ?: "网络异常,请检查网络连接"}") { } } } ) } } generallibrary/src/main/java/com/dayu/general/activity/CardReadActivity.kt
@@ -307,7 +307,7 @@ binding.tvIdCard.text = info.userCode ?: "未录入" // 使用userCode作为身份证号的替代 // 根据status字段显示状态 val statusText = when (info.status) { val statusText = when (info.state) { 1 -> "正常" 2 -> "挂失" 3 -> "锁定" generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
@@ -267,7 +267,7 @@ binding.redRemainderBlance.text = "$balance 元" // 设置卡状态和对应颜色 val cardStatus = when (info.status) { val cardStatus = when (info.state) { 1 -> "正常" 2 -> "挂失" 3 -> "锁定" @@ -277,7 +277,7 @@ binding.redStatu.text = cardStatus // 根据卡状态设置不同颜色 val statusColor = when (info.status) { val statusColor = when (info.state) { 1 -> android.graphics.Color.parseColor("#4CAF50") // 绿色-正常 2 -> android.graphics.Color.parseColor("#FF9800") // 橙色-挂失 3 -> android.graphics.Color.parseColor("#F44336") // 红色-锁定 @@ -433,7 +433,7 @@ putExtra("bonusAmount", bonusAmount) // 传递赠送金额 } startActivity(intent) finish() } catch (e: Exception) { ToastUtil.show("启动写卡界面失败: ${e.message}") } generallibrary/src/main/java/com/dayu/general/adapter/SearchUserListAdapter.kt
@@ -107,7 +107,7 @@ val end = idCard.substring(idCard.length - 4) "$start****$end" } else { idCard ?: "无" "未录入" } } generallibrary/src/main/java/com/dayu/general/bean/net/CardInfoResult.kt
@@ -12,7 +12,7 @@ val phone: String? = null, // 手机号 val address: String? = null, // 地址 val balance: Double? = 0.0, // 余额 val status: Int? = 0, // 卡状态: 1-正常, 2-挂失, 3-锁定 val state: Int? = 0, // 卡状态: 1-正常, 2-挂失, 3-锁定 val createTime: String? = null, // 创建时间 val updateTime: String? = null // 更新时间 ) : Serializable generallibrary/src/main/res/drawable/item_bg_selector.xml
New file @@ -0,0 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape android:shape="rectangle"> <solid android:color="#f5f5f5" /> <corners android:radius="8dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <solid android:color="#fafafa" /> <corners android:radius="8dp" /> </shape> </item> </selector> generallibrary/src/main/res/layout/activity_card_cancel.xml
New file @@ -0,0 +1,365 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/base_green_bg"> <com.dayu.baselibrary.view.TitleBar android:id="@+id/titleBar" android:layout_width="match_parent" android:layout_height="@dimen/dimen_title_height" android:background="@color/title_bar_bg" android:elevation="4dp" app:centerText="销卡" app:leftImage="@mipmap/icon_back" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/titleBar" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <!-- 读卡提示区域 --> <LinearLayout android:id="@+id/card_read_LL" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:visibility="visible"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:gravity="center" android:text="销卡操作" android:textColor="@color/base_blue_bg" android:textSize="@dimen/big_text_size" android:textStyle="bold" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="20dp" android:gravity="center" android:text="请将需要销卡的卡片贴在设备上进行读取" android:textColor="#333333" android:textSize="@dimen/text_size" android:textStyle="bold" /> <ImageView android:layout_width="120dp" android:layout_height="120dp" android:layout_gravity="center" android:layout_marginBottom="20dp" android:scaleType="fitCenter" android:src="@mipmap/nfc_write" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="请保持手持机和卡片不要移动" android:textColor="#666666" android:textSize="@dimen/new_card_size" /> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> <!-- 卡片信息显示区域 --> <LinearLayout android:id="@+id/card_info_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="gone"> <!-- 卡内数据区域 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="12dp" android:gravity="center" android:text="卡片信息" android:textColor="@color/base_blue_bg" android:textSize="@dimen/big_text_size" android:textStyle="bold" /> <!-- 持卡人 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="12dp"> <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="持卡人:" android:textColor="#333333" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/tv_user_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="@dimen/text_size" /> </LinearLayout> <!-- 卡号 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:background="#FFFFFF" android:gravity="center_vertical" android:orientation="horizontal" android:padding="12dp"> <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="卡地址:" android:textColor="#333333" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/tv_card_number" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="@dimen/text_size" /> </LinearLayout> <!-- 卡片状态 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="12dp"> <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="卡片状态:" android:textColor="#333333" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/tv_card_status" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="正常" android:textColor="#4CAF50" android:textSize="@dimen/text_size" /> </LinearLayout> <!-- 卡内余额 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:background="#FFFFFF" android:gravity="center_vertical" android:orientation="horizontal" android:padding="12dp"> <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="卡余额:" android:textColor="#333333" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/tv_card_balance" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0.00元" android:textColor="#FF6B35" android:textSize="@dimen/text_size" android:textStyle="bold" /> </LinearLayout> <!-- 手机号 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:background="#F8F9FA" android:gravity="center_vertical" android:orientation="horizontal" android:padding="12dp"> <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="手机号:" android:textColor="#333333" android:textSize="@dimen/text_size" /> <TextView android:id="@+id/tv_phone" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="--" android:textColor="#666666" android:textSize="@dimen/text_size" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 销卡操作区域 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:cardCornerRadius="8dp" app:cardElevation="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:gravity="center" android:text="销卡操作" android:textColor="@color/base_blue_bg" android:textSize="@dimen/big_text_size" android:textStyle="bold" /> <!-- 退款金额输入 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="退款金额(元):" android:textColor="#333333" android:textSize="@dimen/text_size" android:textStyle="bold" /> <EditText android:id="@+id/et_refund_amount" android:layout_width="match_parent" android:layout_height="48dp" android:background="@drawable/edit_text_bg" android:hint="请输入退款金额" android:inputType="numberDecimal" android:padding="12dp" android:textColor="#333333" android:textColorHint="#999999" android:textSize="@dimen/text_size" /> </LinearLayout> <!-- 备注输入 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="备注:" android:textColor="#333333" android:textSize="@dimen/text_size" android:textStyle="bold" /> <EditText android:id="@+id/et_remarks" android:layout_width="match_parent" android:layout_height="80dp" android:background="@drawable/edit_text_bg" android:gravity="top|start" android:hint="请输入销卡备注信息" android:inputType="textMultiLine" android:padding="12dp" android:textColor="#333333" android:textColorHint="#999999" android:textSize="@dimen/text_size" /> </LinearLayout> <!-- 销卡按钮 --> <Button android:id="@+id/btn_cancel_card" android:layout_width="match_parent" android:layout_height="48dp" android:background="@drawable/button_red_bg" android:text="确认销卡" android:textColor="#FFFFFF" android:textSize="@dimen/big_text_size" android:textStyle="bold" /> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> </LinearLayout> </ScrollView> </RelativeLayout> generallibrary/src/main/res/layout/activity_card_read.xml
@@ -250,7 +250,7 @@ android:textStyle="bold" /> </LinearLayout> <!-- 用户编号 --> <!-- 卡编号 --> <LinearLayout android:id="@+id/ll_user_number" android:layout_width="match_parent" @@ -265,7 +265,7 @@ <TextView android:layout_width="105dp" android:layout_height="wrap_content" android:text="用户编号:" android:text="卡编号:" android:textColor="#333333" android:textSize="@dimen/text_size" /> generallibrary/src/main/res/values/strings.xml
New file @@ -0,0 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <!-- SmartRefreshLayout底部Footer相关文本 --> <string name="srl_footer_nothing">已到底</string> <string name="srl_footer_pulling">上拉加载更多</string> <string name="srl_footer_release">释放立即加载</string> <string name="srl_footer_loading">正在加载…</string> <string name="srl_footer_refreshing">等待头部刷新完成…</string> </resources>