左晓为主开发手持机充值管理机
zuoxiao
19 小时以前 20952db304d0f71e1ce25f3b82114bbadff1ad4a
feat(generallibrary): 补充补卡功能

- 新增 CardReplaceActivity 用于补卡操作
- 实现了读卡、获取卡片信息、选择支付方式等功能
- 优化了用户界面,增加了更多提示和错误处理
- 重构了部分代码结构,提高了可维护性
2 文件已重命名
7个文件已修改
1个文件已添加
1267 ■■■■ 已修改文件
generallibrary/src/main/AndroidManifest.xml 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/CardLossActivity.kt 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/CardReplaceActivity.kt 516 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/CardUnlossActivity.kt 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/SearchCardListActivity.kt 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/view/CardRefundDialog.kt 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/res/layout/activity_card_replace.xml 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/AndroidManifest.xml
@@ -90,7 +90,7 @@
        <!-- 写卡成功页面 -->
        <activity android:name=".activity.CardWriteSuccessActivity" />
        <!-- 挂失页面 -->
        <activity android:name=".activity.LossCardActivity" />
        <activity android:name=".activity.CardLossActivity" />
        <!-- 读卡页面 -->
        <activity
            android:name=".activity.CardReadActivity"
@@ -136,9 +136,18 @@
            </intent-filter>
        </activity>
        <activity
            android:name=".activity.UnlossCardActivity"
            android:name=".activity.CardUnlossActivity"
            android:exported="false"
            android:launchMode="singleTop"/>
        <activity android:name=".activity.CardReplaceActivity"
            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"
generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt
@@ -79,7 +79,7 @@
        // 挂失卡按钮点击事件
        binding.homeLossLL.setOnClickListener {
            // 跳转到挂失卡页面
            val intent = Intent(context, LossCardActivity::class.java)
            val intent = Intent(context, CardLossActivity::class.java)
            startActivity(intent)
        }
@@ -108,7 +108,7 @@
        }
        binding.homeReplacement.setOnClickListener {
            context?.let {
                val intent = Intent(context, UnlossCardActivity::class.java)
                val intent = Intent(context, CardUnlossActivity::class.java)
                startActivity(intent)
            }
        }
generallibrary/src/main/java/com/dayu/general/activity/CardLossActivity.kt
File was renamed from generallibrary/src/main/java/com/dayu/general/activity/LossCardActivity.kt
@@ -22,7 +22,7 @@
 * Author: zuo
 * Date: 2025/6/11
 */
class LossCardActivity : BaseActivity() {
class CardLossActivity : BaseActivity() {
    var binding: ActivityCardListBinding? = null
    private var cardAdapter: CardListAdapter? = null
@@ -82,7 +82,7 @@
    private fun setupRecyclerView() {
        cardAdapter = CardListAdapter(this)
        binding?.recyclerView?.apply {
            layoutManager = LinearLayoutManager(this@LossCardActivity)
            layoutManager = LinearLayoutManager(this@CardLossActivity)
            adapter = cardAdapter
        }
@@ -96,13 +96,11 @@
                card.cardNum.toString(),
                card.money.toString()
            )
            refundDialog.setOnConfirmListener {  refundAmount, remark ->
                // TODO: 处理退款逻辑
                lossPost(card.idCard.toString())
            refundDialog.setOnConfirmListener { _username, cardNumber, balance, refundAmount, remark ->
                // 调用挂失接口
                lossPost(cardNumber, balance, refundAmount, remark)
            }
        }
    }
    private fun setupRefreshLayout() {
@@ -247,38 +245,56 @@
        )
    }
    private fun lossPost(cardNumber: String) {
    /**
     * 执行挂失操作
     * @param cardNumber 卡号
     * @param balance 余额
     * @param refundAmount 退款金额
     * @param remark 备注
     */
    private fun lossPost(cardNumber: String, balance: String, refundAmount: String, remark: String) {
        val map = mutableMapOf<String, Any>()
        map["cardNum"] = cardNumber
        // 处理余额格式,去除千位分隔符逗号和"元"字符
        val balanceValue = balance.replace("元", "").replace(",", "").toFloatOrNull() ?: 0f
        map["money"] = balanceValue
        map["refund"] = refundAmount.toFloatOrNull() ?: 0f
        map["remarks"] = remark.ifEmpty { "挂失" }
        map["operator"] = BaseApplication.userId
        ApiManager.getInstance().requestGetLoading(
        ApiManager.getInstance().requestPostLoading(
            this,
            "/sell/card/loss",
            SearchCardResult::class.java,
            "terminal/card/termReportLoss",
            ReportLossResult::class.java,
            map,
            object : SubscriberListener<BaseResponse<SearchCardResult>>() {
                override fun onNext(t: BaseResponse<SearchCardResult>) {
                    if (t.success) {
            object : SubscriberListener<BaseResponse<ReportLossResult>>() {
                override fun onNext(t: BaseResponse<ReportLossResult>) {
                    if (t.success && t.code == "0001") {
                        ToastUtil.show("挂失成功")
                        // 刷新列表数据
                        searchCards(currentFarmerId, currentFarmerName, currentCardNumber, true)
                    } else {
                        // 处理搜索失败的情况
                        ToastUtil.show(t.msg)
                        ToastUtil.show(t.msg ?: "挂失失败")
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    // 完成刷新或加载动作
                    ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}")
                    ToastUtil.show("挂失失败: ${e?.message ?: "网络错误"}")
                }
            }
        )
    }
    /**
     * 挂失接口返回结果
     */
    data class ReportLossResult(
        val content: Boolean? = null
    )
    /**
     * 完成刷新或加载操作
generallibrary/src/main/java/com/dayu/general/activity/CardReplaceActivity.kt
New file
@@ -0,0 +1,516 @@
package com.dayu.general.activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.RadioButton
import android.widget.Toast
import com.dayu.baselibrary.net.subscribers.SubscriberListener
import com.dayu.baselibrary.utils.MornyUtil
import com.dayu.baselibrary.utils.ToastUtil
import com.dayu.baselibrary.view.TipDialog
import com.dayu.baselibrary.view.TitleBar
import com.dayu.general.BaseApplication
import com.dayu.general.R
import com.dayu.general.bean.card.UserCard
import com.dayu.general.bean.net.CardInfoResult
import com.dayu.general.bean.net.CardReplaceResult
import com.dayu.general.bean.net.PaymentMethod
import com.dayu.general.bean.net.PaymentMethodResponse
import com.dayu.general.databinding.ActivityCardReplaceBinding
import com.dayu.general.net.ApiManager
import com.dayu.general.net.BaseResponse
import com.dayu.general.tool.CardCommon
import com.dayu.general.tool.CardOperationType
import com.dayu.general.tool.NfcReadHelper
/**
 * @author: zuo
 * @desc: 补卡Activity
 * @since: 2025/6/17
 */
class CardReplaceActivity : BaseNfcActivity() {
    private lateinit var binding: ActivityCardReplaceBinding
    private var cardNumber: String? = null
    private var cardInfo: CardInfoResult? = null
    private var userCard: UserCard? = null
    // 支付方式相关属性
    private var paymentMethod: String = "现金"
    private var paymentId: Long = 0
    private var paymentMethodList: List<PaymentMethod> = listOf()
    companion object {
        /**
         * 启动补卡Activity
         */
        fun start(context: Context) {
            val intent = Intent(context, CardReplaceActivity::class.java)
            context.startActivity(intent)
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityCardReplaceBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initView()
        // 获取支付方式
        getPaymentMethods()
    }
    private fun initView() {
        // 设置TitleBar的返回按钮点击事件
        binding.titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) {
            finish()
        }
        // 设置补卡按钮点击事件
        binding.btnReplace.setOnClickListener {
            performCardReplace()
        }
    }
    /**
     * 获取支付方式列表
     */
    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
                }
            }
        }
    }
    /**
     * 重置到读卡状态
     */
    private fun resetToReadingState() {
        binding.scrollReadCard.visibility = android.view.View.VISIBLE
        binding.cardInfoContainer.visibility = android.view.View.GONE
        binding.bottomButtonContainer.visibility = android.view.View.GONE
        cardNumber = null
        cardInfo = null
        binding.etCardCost.setText("")
        binding.etReturnAmount.setText("0")
    }
    /**
     * 显示确认对话框
     */
    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 -> {
                    // 用户卡:解析卡内数据并调用接口
                    showConfirmDialog("该卡片类型不支持补卡操作") {
                        resetToReadingState()
                    }
                }
                else -> {
                    // 管理类卡不支持补卡
                    handleUserCard(cardNumber, cardType, nfcAdapter)
                }
            }
        } 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("CardReplaceActivity", "=== 用户卡信息 ===")
        android.util.Log.d("CardReplaceActivity", "卡号: $cardNumber")
        android.util.Log.d("CardReplaceActivity", "卡片类型: $cardType")
        android.util.Log.d("CardReplaceActivity", "卡内余额: ${userCard.balance}")
        android.util.Log.d("CardReplaceActivity", "==================")
        this.userCard = userCard
        // 根据卡号获取卡片详细信息
        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.scrollReadCard.visibility = android.view.View.GONE
        binding.cardInfoContainer.visibility = android.view.View.VISIBLE
        binding.bottomButtonContainer.visibility = android.view.View.VISIBLE
        this.cardInfo = cardInfo
        // 显示当前卡地址
        binding.tvCurrentCardAddress.text = cardNumber
        // 显示服务器数据
        cardInfo?.let { info ->
            binding.tvUserName.text = info.userName ?: "未知"
            binding.tvPhone.text = info.phone ?: "未绑定"
            // 根据state字段显示状态
            val (statusText, statusColor) = when (info.state) {
                1 -> Pair("正常", android.graphics.Color.parseColor("#4CAF50")) // 绿色
                2 -> Pair("已注销", android.graphics.Color.parseColor("#FF5722")) // 深橙色
                3 -> Pair("已挂失", android.graphics.Color.parseColor("#FF9800")) // 橙色
                4 -> Pair("无效卡片", android.graphics.Color.parseColor("#F44336")) // 红色
                else -> Pair("未知状态", android.graphics.Color.parseColor("#9E9E9E")) // 灰色
            }
            binding.tvCardStatus.text = statusText
            binding.tvCardStatus.setTextColor(statusColor)
        }
        userCard.let { card ->
            // 余额转换为元(原始数据可能是分)
            binding.tvCardBalance.text = MornyUtil.changeF2Y(card.balance) + "元"
        }
    }
    /**
     * 处理卡信息获取错误
     */
    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 performCardReplace() {
        // 验证输入
        val cardCostStr = binding.etCardCost.text.toString().trim()
        val returnAmountStr = binding.etReturnAmount.text.toString().trim()
        // 工本费验证(必填)
        if (cardCostStr.isEmpty()) {
            ToastUtil.show("请输入工本费")
            return
        }
        val cardCost = try {
            val cost = cardCostStr.toDouble()
            if (cost < 0) {
                ToastUtil.show("工本费不能为负数")
                return
            }
            cost
        } catch (e: NumberFormatException) {
            ToastUtil.show("请输入有效的工本费")
            return
        }
        // 返回金额验证(必填)
        if (returnAmountStr.isEmpty()) {
            ToastUtil.show("请输入返回金额")
            return
        }
        val returnAmount = try {
            val amount = returnAmountStr.toDouble()
            if (amount < 0) {
                ToastUtil.show("返回金额不能为负数")
                return
            }
            amount
        } catch (e: NumberFormatException) {
            ToastUtil.show("请输入有效的返回金额")
            return
        }
        callReplaceCardApi(cardCost, returnAmount)
    }
    /**
     * 调用补卡API接口
     */
    private fun callReplaceCardApi(cardCost: Double, returnAmount: Double) {
        if (cardNumber.isNullOrBlank()) {
            ToastUtil.show("卡号信息异常,请重新刷卡")
            return
        }
        val map = mutableMapOf<String, Any>()
        map["cardAddr"] = cardNumber!!
        map["cardNum"] = cardInfo?.cardNum.toString()
        map["cardCost"] = cardCost
        map["returnAmount"] = returnAmount  // 使用返回金额
        map["paymentId"] = paymentId // 使用选中的支付方式ID
        map["paymentMethod"] = paymentMethod // 添加支付方式名称
        map["remarks"] = "补卡操作"  // 固定备注
        map["operator"] = BaseApplication.userId
        ApiManager.getInstance().requestPostLoading(
            this,
            "terminal/card/termReissue",
            CardReplaceResult::class.java,
            map,
            object : SubscriberListener<BaseResponse<CardReplaceResult>>() {
                override fun onNext(t: BaseResponse<CardReplaceResult>) {
                    if (t.success && t.content != null) {
                        // 补卡成功,跳转到写卡界面
                        startWriteCardActivity(t.content!!, cardCost, returnAmount, userCard!!)
                    } else {
                        // 补卡失败
                        val errorMsg = if (t.msg.isNullOrBlank()) "补卡失败,请重试" else t.msg
                        showConfirmDialog("补卡失败:$errorMsg") {
                        }
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    showConfirmDialog("补卡请求失败: ${e?.message ?: "网络异常,请检查网络连接"}") {
                    }
                }
            }
        )
    }
    /**
     * 跳转到写卡界面进行卡内容更新
     */
    private fun startWriteCardActivity(
        replaceResult: CardReplaceResult,
        cardCost: Double,
        returnAmount: Double,
        userCard: UserCard
    ) {
        // 创建更新后的用户卡数据
        val updatedUserCard = UserCard().apply {
            // 复制原有属性
            cardType = userCard.cardType
            areaNumber = userCard.areaNumber
            userCode = userCard.userCode
            userCodeNumber = userCard.userCodeNumber
            phoneNumber = userCard.phoneNumber
            projectCode = userCard.projectCode
            surplusWater = userCard.surplusWater
            waterPrice = userCard.waterPrice
            electricPrice = userCard.electricPrice
            rechargeDate = userCard.rechargeDate
            // 使用返回的新余额
            balance = MornyUtil.changeY2F(replaceResult.balance.toString())
        }
        val intent = Intent(this, NfcWreatActivity::class.java).apply {
            putExtra("cardAddr", cardNumber)
            putExtra("operationTypeCode", CardOperationType.ReplaceCard.code) // 使用补卡类型进行写卡
            putExtra("orderNumber", replaceResult.orderNo)
            putExtra("cardCost", cardCost)
            putExtra("returnAmount", returnAmount)  // 传递返回金额
            putExtra("paymentMethod", paymentMethod) // 传递支付方式
            putExtra("paymentId", paymentId) // 传递支付方式ID
            putExtra("userCard", updatedUserCard as java.io.Serializable)
        }
        startActivity(intent)
        finish()
    }
}
generallibrary/src/main/java/com/dayu/general/activity/CardUnlossActivity.kt
File was renamed from generallibrary/src/main/java/com/dayu/general/activity/UnlossCardActivity.kt
@@ -22,7 +22,7 @@
 * Author: zuo
 * Date: 2025/6/11
 */
class UnlossCardActivity : BaseActivity() {
class CardUnlossActivity : BaseActivity() {
    var binding: ActivityCardListBinding? = null
    private var cardAdapter: UnlossCardListAdapter? = null
@@ -88,7 +88,7 @@
    private fun setupRecyclerView() {
        cardAdapter = UnlossCardListAdapter(this)
        binding?.recyclerView?.apply {
            layoutManager = LinearLayoutManager(this@UnlossCardActivity)
            layoutManager = LinearLayoutManager(this@CardUnlossActivity)
            adapter = cardAdapter
        }
@@ -99,7 +99,8 @@
        // 设置补卡按钮点击事件  
        cardAdapter?.setOnReplaceClickListener { card ->
            showReplaceConfirmDialog(card)
            CardReplaceActivity.start(this)
        }
    }
@@ -263,26 +264,7 @@
        confirmDialog.show()
    }
    /**
     * 显示补卡确认对话框
     */
    private fun showReplaceConfirmDialog(card: SearchCardResult.CardInfo) {
        val confirmMessage = "确认要补办新卡吗?\n\n" +
                "卡号:${card.cardNum ?: "无"}\n" +
                "持卡人:${card.clientName ?: "未知"}\n" +
                "余额:${card.money ?: "0.00"}元\n\n" +
                "补卡后将生成新的卡片,原卡作废!"
        val confirmDialog = ConfirmDialog(
            this,
            "补卡确认",
            confirmMessage
        ) {
            // 用户点击确认后执行补卡操作
            replaceCard(card)
        }
        confirmDialog.show()
    }
    /**
     * 解除挂失
@@ -315,41 +297,6 @@
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    ToastUtil.show("解除挂失失败: ${e?.message ?: "未知错误"}")
                }
            }
        )
    }
    /**
     * 补卡
     */
    private fun replaceCard(card: SearchCardResult.CardInfo) {
        val map = mutableMapOf<String, Any>()
        map["cardNum"] = card.cardNum.toString()
        map["operator"] = BaseApplication.userId
        ApiManager.getInstance().requestGetLoading(
            this,
            "/sell/card/replace",
            SearchCardResult::class.java,
            map,
            object : SubscriberListener<BaseResponse<SearchCardResult>>() {
                override fun onNext(t: BaseResponse<SearchCardResult>) {
                    if (t.success) {
                        ToastUtil.show("补卡成功")
                        // 刷新列表
                        currentPage = 1
                        hasMoreData = true
                        binding?.refreshLayout?.resetNoMoreData()
                        searchCards(currentFarmerId, currentFarmerName, currentCardNumber, true)
                    } else {
                        ToastUtil.show(t.msg)
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    ToastUtil.show("补卡失败: ${e?.message ?: "未知错误"}")
                }
            }
        )
generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
@@ -85,6 +85,22 @@
                binding.successMessage.text = message
            }
            CardOperationType.ReplaceCard -> {
                // 设置标题
                binding.titleBar.setCenterText("补卡成功")
                // 设置成功信息
                binding.successTitle.text = "补卡成功"
                // 设置详细信息
                val message = if (cardNumber.isNullOrBlank()) {
                    "补卡操作已成功完成\n新卡已写入数据,可正常使用"
                } else {
                    "补卡操作已成功完成\n卡号:$cardNumber\n新卡已写入数据,可正常使用"
                }
                binding.successMessage.text = message
            }
            CardOperationType.Recharge -> {
                binding.titleBar.setCenterText("写卡成功")
                binding.successTitle.text = "写卡成功"
generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -44,6 +44,10 @@
    // 补扣相关信息
    private var deductAmount = 0.0
    // 补卡相关信息
    private var cardCost = 0.0
    private var reissueAmount = 0.0
    //订单编号
    var orderNumber = ""
    private lateinit var userCard: UserCard
@@ -80,6 +84,10 @@
        // 获取补扣相关信息
        deductAmount = intent?.getDoubleExtra("deductAmount", 0.0) ?: 0.0
        // 获取补卡相关信息
        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
@@ -185,8 +193,20 @@
                    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 -> TODO()
                CardOperationType.ReplaceCard -> TODO()
                null -> TODO()
            }
        }
@@ -297,8 +317,22 @@
                    })
                }
                CardOperationType.ReplaceCard -> {
                    nfcWreatHelper.writeUserDataAsync(userCard, object : NFCCallBack {
                        override fun isSusses(flag: Boolean, msg: String?) {
                            // 确保Toast在主线程中调用
                            runOnUiThread {
                                if (flag) {
                                    postCardData(cardAddr)
                                } else {
                                    ToastUtil.show("补卡写卡失败: ${msg ?: "未知错误"}")
                                }
                            }
                        }
                    })
                }
                CardOperationType.CheckCard -> TODO()
                CardOperationType.ReplaceCard -> TODO()
                null -> TODO()
            }
        } else {
generallibrary/src/main/java/com/dayu/general/activity/SearchCardListActivity.kt
@@ -90,9 +90,9 @@
                card.cardNum.toString(),
                card.money.toString()
            )
            refundDialog.setOnConfirmListener {  refundAmount, remark ->
                // TODO: 处理退款逻辑
                lossPost(card.idCard.toString())
            refundDialog.setOnConfirmListener { _username, cardNumber, balance, refundAmount, remark ->
                // 调用挂失接口
                lossPost(cardNumber, balance, refundAmount, remark)
            }
        }
@@ -217,38 +217,56 @@
        )
    }
    private fun lossPost(cardNumber: String) {
    /**
     * 执行挂失操作
     * @param cardNumber 卡号
     * @param balance 余额
     * @param refundAmount 退款金额
     * @param remark 备注
     */
    private fun lossPost(cardNumber: String, balance: String, refundAmount: String, remark: String) {
        val map = mutableMapOf<String, Any>()
        map["cardNum"] = cardNumber
        // 处理余额格式,去除千位分隔符逗号和"元"字符
        val balanceValue = balance.replace("元", "").replace(",", "").toFloatOrNull() ?: 0f
        map["money"] = balanceValue
        map["refund"] = refundAmount.toFloatOrNull() ?: 0f
        map["remarks"] = remark.ifEmpty { "挂失" }
        map["operator"] = BaseApplication.userId
        ApiManager.getInstance().requestGetLoading(
        ApiManager.getInstance().requestPostLoading(
            this,
            "/sell/card/loss",
            SearchCardResult::class.java,
            "sell/card/loss",
            ReportLossResult::class.java,
            map,
            object : SubscriberListener<BaseResponse<SearchCardResult>>() {
                override fun onNext(t: BaseResponse<SearchCardResult>) {
                    if (t.success) {
            object : SubscriberListener<BaseResponse<ReportLossResult>>() {
                override fun onNext(t: BaseResponse<ReportLossResult>) {
                    if (t.success && t.code == "0001") {
                        ToastUtil.show("挂失成功")
                        // 刷新列表数据
                        searchCards(currentFarmerId, currentFarmerName, currentCardNumber, true)
                    } else {
                        // 处理搜索失败的情况
                        ToastUtil.show(t.msg)
                        ToastUtil.show(t.msg ?: "挂失失败")
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    // 完成刷新或加载动作
                    ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}")
                    ToastUtil.show("挂失失败: ${e?.message ?: "网络错误"}")
                }
            }
        )
    }
    /**
     * 挂失接口返回结果
     */
    data class ReportLossResult(
        val content: Boolean? = null
    )
    /**
     * 完成刷新或加载操作
generallibrary/src/main/java/com/dayu/general/view/CardRefundDialog.kt
@@ -5,21 +5,15 @@
import android.os.Bundle
import android.view.Gravity
import android.view.WindowManager
import com.dayu.baselibrary.net.subscribers.SubscriberListener
import com.dayu.baselibrary.utils.ToastUtil
import com.dayu.general.BaseApplication
import com.dayu.general.R
import com.dayu.general.databinding.DialogCardRefundBinding
import com.dayu.general.net.ApiManager
import com.dayu.general.net.BaseResponse
/**
 *卡片挂失对话框
 */
class CardRefundDialog(context: Context) : Dialog(context) {
    private var binding: DialogCardRefundBinding? = null
    private var onConfirmListener: ((String, String) -> Unit)? = null
    private var onSuccessListener: (() -> Unit)? = null
    private var onConfirmListener: ((String, String, String, String, String) -> Unit)? = null
    private var username: String? = null
    private var cardNumber: String? = null
    private var balance: String? = null
@@ -47,8 +41,15 @@
            val refundAmount = binding?.etRefundAmount?.text.toString()
            val remark = binding?.etRemark?.text.toString()
            // 调用挂失接口
            callReportLossApi(refundAmount, remark)
            // 通过回调将数据传递给Activity处理
            username?.let { username ->
                cardNumber?.let { cardNumber ->
                    balance?.let { balance ->
                        onConfirmListener?.invoke(username, cardNumber, balance, refundAmount, remark)
                        dismiss()
                    }
                }
            }
        }
        // 如果有预设的用户信息,设置它们
@@ -80,58 +81,11 @@
        }
    }
    fun setOnConfirmListener(listener: (String, String) -> Unit) {
    /**
     * 设置确认监听器
     * @param listener 回调函数,参数为:用户名、卡号、余额、退款金额、备注
     */
    fun setOnConfirmListener(listener: (String, String, String, String, String) -> Unit) {
        onConfirmListener = listener
    }
    fun setOnSuccessListener(listener: () -> Unit) {
        onSuccessListener = listener
    }
    /**
     * 调用挂失接口
     */
    private fun callReportLossApi(refundAmount: String, remark: String) {
        val params = mutableMapOf<String, Any>()
        params["cardNum"] = cardNumber ?: ""
        // 处理余额格式,去除千位分隔符逗号和"元"字符
        val balanceValue = balance?.replace("元", "")?.replace(",", "")?.toFloatOrNull() ?: 0f
        params["money"] = balanceValue
        params["refund"] = refundAmount.toFloatOrNull() ?: 0f
        params["remarks"] = remark.ifEmpty { "挂失" }
        params["operator"] = BaseApplication.userId
        ApiManager.getInstance().requestPostLoading(
            context,
            "terminal/card/termReportLoss",
            ReportLossResult::class.java,
            params,
            object : SubscriberListener<BaseResponse<ReportLossResult>>() {
                override fun onNext(response: BaseResponse<ReportLossResult>) {
                    if (response.success && response.code == "0001") {
                        ToastUtil.show("挂失成功")
                        onConfirmListener?.invoke(refundAmount, remark)
                        onSuccessListener?.invoke()
                        dismiss()
                    } else {
                        ToastUtil.show(response.msg ?: "挂失失败")
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    ToastUtil.show("挂失失败: ${e?.message ?: "网络错误"}")
                }
            }
        )
    }
    /**
     * 挂失接口返回结果
     */
    data class ReportLossResult(
        val content: Boolean? = null
    )
generallibrary/src/main/res/layout/activity_card_replace.xml
@@ -1,49 +1,424 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<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/white"
    android:orientation="vertical">
    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"
        app:centerText="补卡" />
        android:background="@color/title_bar_bg"
        android:elevation="4dp"
        app:centerText="补卡"
        app:leftImage="@mipmap/icon_back" />
    <FrameLayout
    <!-- 读卡提示区域 - 全屏显示 -->
    <ScrollView
        android:id="@+id/scroll_read_card"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        android:layout_height="match_parent"
        android:layout_below="@+id/titleBar"
        android:fillViewport="true"
        android:visibility="visible">
        <com.scwang.smart.refresh.layout.SmartRefreshLayout
            android:id="@+id/refreshLayout"
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/titleBar">
            android:orientation="vertical"
            android:padding="16dp">
            <com.scwang.smart.refresh.header.ClassicsHeader
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
            <LinearLayout
                android:id="@+id/card_read_LL"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/base_list_bg"
                android:overScrollMode="never"
                android:padding="10dp" />
                android:gravity="center"
                android:orientation="vertical">
            <com.scwang.smart.refresh.footer.ClassicsFooter
                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginBottom="16dp"
                    app:cardCornerRadius="8dp"
                    app:cardElevation="2dp">
                    <RelativeLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:padding="16dp">
                        <TextView
                            android:id="@+id/tv_title"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="100dp"
                            android:gravity="center"
                            android:text="补卡操作"
                            android:layout_marginTop="20dp"
                            android:textColor="@color/base_blue_bg"
                            android:textSize="@dimen/big_text_size"
                            android:textStyle="bold" />
                        <TextView
                            android:id="@+id/tv_subtitle"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_below="@+id/tv_title"
                            android:layout_marginBottom="20dp"
                            android:gravity="center"
                            android:text="请将需要补办的卡片贴在设备上进行读取"
                            android:textColor="#333333"
                            android:textSize="@dimen/text_size"
                            android:textStyle="bold" />
                        <ImageView
                            android:id="@+id/iv_nfc"
                            android:layout_width="120dp"
                            android:layout_height="120dp"
                            android:layout_below="@+id/tv_subtitle"
                            android:layout_centerHorizontal="true"
                            android:layout_marginBottom="20dp"
                            android:scaleType="fitCenter"
                            android:src="@mipmap/nfc_write" />
                        <TextView
                            android:id="@+id/tv_tip"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_below="@+id/iv_nfc"
                            android:gravity="center"
                            android:text="请保持手持机和卡片不要移动"
                            android:textColor="#666666"
                            android:textSize="@dimen/new_card_size" />
                    </RelativeLayout>
                </androidx.cardview.widget.CardView>
            </LinearLayout>
        </LinearLayout>
    </ScrollView>
    <!-- 卡片信息显示区域 - 带固定底部按钮 -->
    <LinearLayout
        android:id="@+id/card_info_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottom_button_container"
        android:layout_below="@+id/titleBar"
        android:orientation="vertical"
        android:visibility="gone">
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:fillViewport="true"
            android:padding="12dp">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.scwang.smart.refresh.layout.SmartRefreshLayout>
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <!-- 当前卡地址显示区域 -->
                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="12dp"
                    app:cardCornerRadius="8dp"
                    app:cardElevation="2dp">
    </FrameLayout>
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:padding="16dp">
</LinearLayout>
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="12dp"
                            android:text="当前卡地址"
                            android:textColor="@color/base_blue_bg"
                            android:textSize="18sp"
                            android:textStyle="bold" />
                        <TextView
                            android:id="@+id/tv_current_card_address"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="#F5F5F5"
                            android:padding="12dp"
                            android:text="--"
                            android:textColor="#333333"
                            android:textSize="16sp"
                            android:textIsSelectable="true" />
                    </LinearLayout>
                </androidx.cardview.widget.CardView>
                <!-- 旧卡信息区域 -->
                <androidx.cardview.widget.CardView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    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:text="旧卡信息"
                            android:textColor="@color/base_blue_bg"
                            android:textSize="18sp"
                            android:textStyle="bold" />
                        <!-- 持卡人 -->
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="1dp"
                            android:background="#F8F9FA"
                            android:gravity="center_vertical"
                            android:orientation="horizontal"
                            android:padding="12dp">
                            <TextView
                                android:layout_width="100dp"
                                android:layout_height="wrap_content"
                                android:text="持卡人:"
                                android:textColor="#333333"
                                android:textSize="16sp"
                                android:textStyle="bold" />
                            <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="16sp" />
                        </LinearLayout>
                        <!-- 卡片状态 -->
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="1dp"
                            android:background="#FFFFFF"
                            android:gravity="center_vertical"
                            android:orientation="horizontal"
                            android:padding="12dp">
                            <TextView
                                android:layout_width="100dp"
                                android:layout_height="wrap_content"
                                android:text="卡片状态:"
                                android:textColor="#333333"
                                android:textSize="16sp"
                                android:textStyle="bold" />
                            <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="16sp" />
                        </LinearLayout>
                        <!-- 卡内余额 -->
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="1dp"
                            android:background="#F8F9FA"
                            android:gravity="center_vertical"
                            android:orientation="horizontal"
                            android:padding="12dp">
                            <TextView
                                android:layout_width="100dp"
                                android:layout_height="wrap_content"
                                android:text="卡内余额:"
                                android:textColor="#333333"
                                android:textSize="16sp"
                                android:textStyle="bold" />
                            <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="16sp"
                                android:textStyle="bold" />
                        </LinearLayout>
                        <!-- 手机号 -->
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="#FFFFFF"
                            android:gravity="center_vertical"
                            android:orientation="horizontal"
                            android:padding="12dp">
                            <TextView
                                android:layout_width="100dp"
                                android:layout_height="wrap_content"
                                android:text="手机号:"
                                android:textColor="#333333"
                                android:textSize="16sp"
                                android:textStyle="bold" />
                            <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="16sp" />
                        </LinearLayout>
                    </LinearLayout>
                </androidx.cardview.widget.CardView>
            </LinearLayout>
        </ScrollView>
    </LinearLayout>
    <!-- 底部操作区域 -->
    <LinearLayout
        android:id="@+id/bottom_button_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        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>
        <!-- 工本费和返回金额输入区域 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="16dp">
            <!-- 工本费输入 -->
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginEnd="8dp"
                android:orientation="vertical">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="6dp"
                    android:text="工本费(元)"
                    android:textColor="#333333"
                    android:textSize="14sp"
                    android:textStyle="bold" />
                <EditText
                    android:id="@+id/et_card_cost"
                    android:layout_width="match_parent"
                    android:layout_height="48dp"
                    android:background="@drawable/edit_text_bg"
                    android:hint="工本费"
                    android:inputType="numberDecimal"
                    android:padding="12dp"
                    android:text=""
                    android:textColor="#333333"
                    android:textColorHint="#999999"
                    android:textSize="16sp" />
            </LinearLayout>
            <!-- 返回金额输入 -->
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginStart="8dp"
                android:orientation="vertical">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="6dp"
                    android:text="返回金额(元)"
                    android:textColor="#333333"
                    android:textSize="14sp"
                    android:textStyle="bold" />
                <EditText
                    android:id="@+id/et_return_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:text="0"
                    android:textColor="#333333"
                    android:textColorHint="#999999"
                    android:textSize="16sp" />
            </LinearLayout>
        </LinearLayout>
        <!-- 补卡按钮 -->
        <Button
            android:id="@+id/btn_replace"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="@drawable/button_blue_bg"
            android:text="确认补卡"
            android:textColor="#FFFFFF"
            android:textSize="@dimen/big_text_size"
            android:textStyle="bold" />
    </LinearLayout>
</RelativeLayout>