From 98994189864f045551f7d06f78017b5df70e1be3 Mon Sep 17 00:00:00 2001
From: zuoxiao <470321431@qq.com>
Date: 星期四, 19 六月 2025 11:03:52 +0800
Subject: [PATCH] feat(card): 添加补扣功能并优化卡片操作界面

---
 generallibrary/src/main/java/com/dayu/general/bean/net/CardReturnResult.kt         |   33 +
 generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt           |    3 
 generallibrary/src/main/java/com/dayu/general/activity/CardDeductActivity.kt       |  391 +++++++++++++++++++++++
 generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt |   16 
 generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt         |   31 +
 generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt       |   20 
 generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt   |   10 
 generallibrary/src/main/AndroidManifest.xml                                        |    9 
 generallibrary/src/main/java/com/dayu/general/bean/net/CardCancelResult.kt         |   13 
 generallibrary/src/main/res/layout/activity_card_deduct.xml                        |  412 ++++++++++++++++++++++++
 generallibrary/src/main/java/com/dayu/general/bean/net/CardDeductResult.kt         |   33 +
 generallibrary/src/main/res/drawable/button_green_bg.xml                           |    6 
 generallibrary/src/main/java/com/dayu/general/bean/net/RechargeResult.kt           |    3 
 13 files changed, 962 insertions(+), 18 deletions(-)

diff --git a/generallibrary/src/main/AndroidManifest.xml b/generallibrary/src/main/AndroidManifest.xml
index 019d8dc..e873d53 100644
--- a/generallibrary/src/main/AndroidManifest.xml
+++ b/generallibrary/src/main/AndroidManifest.xml
@@ -126,6 +126,15 @@
                 <data android:mimeType="text/plain" />
             </intent-filter>
         </activity>
+        <activity android:name=".activity.CardDeductActivity"
+            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"
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt b/generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt
index 7cd9a2e..db849ff 100644
--- a/generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt
+++ b/generallibrary/src/main/java/com/dayu/general/activity/BSCardFragment.kt
@@ -60,6 +60,9 @@
         binding.homeCancelCard.setOnClickListener {
             context?.let { CardCancelActivity.start(it) }
         }
+        binding.homeDeduction.setOnClickListener {
+            context?.let { CardDeductActivity.start(it) }
+        }
     }
 }
 
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt b/generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt
index 4d29030..06c3b3f 100644
--- a/generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt
+++ b/generallibrary/src/main/java/com/dayu/general/activity/CardCancelActivity.kt
@@ -244,12 +244,20 @@
             binding.tvUserName.text = info.userName ?: "鏈煡"
             binding.tvPhone.text = info.phone ?: "鏈粦瀹�"
 
-            // 鏍规嵁status瀛楁鏄剧ず鐘舵��
-            val statusText = when (info.state) {
-                1 -> "姝e父"
-                2 -> "鎸傚け"
-                3 -> "閿佸畾"
-                else -> "鏈煡"
+            // 鏍规嵁state瀛楁鏄剧ず鐘舵��
+            val (statusText, statusColor) = when (info.state) {
+                1 -> Pair("姝e父", 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)
+            if (info.state == 3) {
+                binding.btnCancelCard.visibility = android.view.View.GONE
+            } else {
+                binding.btnCancelCard.visibility = android.view.View.VISIBLE
             }
         }
     }
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/CardDeductActivity.kt b/generallibrary/src/main/java/com/dayu/general/activity/CardDeductActivity.kt
new file mode 100644
index 0000000..4351298
--- /dev/null
+++ b/generallibrary/src/main/java/com/dayu/general/activity/CardDeductActivity.kt
@@ -0,0 +1,391 @@
+package com.dayu.general.activity
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+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.bean.card.UserCard
+import com.dayu.general.bean.net.CardInfoResult
+import com.dayu.general.bean.net.CardDeductResult
+import com.dayu.general.databinding.ActivityCardDeductBinding
+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: AI Assistant
+ * @desc: 琛ユ墸Activity
+ * @since: 2025/6/17
+ */
+class CardDeductActivity : BaseNfcActivity() {
+    private lateinit var binding: ActivityCardDeductBinding
+    private var cardNumber: String? = null
+    private var cardInfo: CardInfoResult? = null
+    private var userCard: UserCard? = null
+
+    companion object {
+        /**
+         * 鍚姩琛ユ墸Activity
+         */
+        fun start(context: Context) {
+            val intent = Intent(context, CardDeductActivity::class.java)
+            context.startActivity(intent)
+        }
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        binding = ActivityCardDeductBinding.inflate(layoutInflater)
+        setContentView(binding.root)
+
+        initView()
+    }
+
+    private fun initView() {
+        // 璁剧疆TitleBar鐨勮繑鍥炴寜閽偣鍑讳簨浠�
+        binding.titleBar.setOnItemclickListner(TitleBar.ClickType_LEFT_IMAGE) {
+            finish()
+        }
+
+        // 璁剧疆琛ユ墸鎸夐挳鐐瑰嚮浜嬩欢
+        binding.btnDeduct.setOnClickListener {
+            performCardDeduct()
+        }
+    }
+
+    /**
+     * 閲嶇疆鍒拌鍗$姸鎬�
+     */
+    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.etDeductAmount.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 {
+            // 澶勭悊姝e父鐨勮鍗℃搷浣�
+            handleNfcIntent(it)
+        } ?: run {
+            showConfirmDialog("NFC鏁版嵁寮傚父锛岃閲嶆柊鍒峰崱") {
+            }
+        }
+    }
+
+    /**
+     * 澶勭悊NFC鍒峰崱淇℃伅
+     */
+    private fun handleNfcIntent(intent: Intent) {
+        try {
+            // 妫�鏌ntent涓槸鍚﹀寘鍚玁FC 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 -> {
+                    // 鐢ㄦ埛鍗★細瑙f瀽鍗″唴鏁版嵁骞惰皟鐢ㄦ帴鍙�
+                    handleUserCard(cardNumber, cardType, nfcAdapter)
+                }
+
+                else -> {
+                    // 绠$悊绫诲崱涓嶆敮鎸佽ˉ鎵�
+                    showConfirmDialog("璇ュ崱鐗囩被鍨嬩笉鏀寔琛ユ墸鎿嶄綔") {
+                        resetToReadingState()
+                    }
+                }
+            }
+        } catch (e: Exception) {
+            showConfirmDialog("璇诲崱寮傚父锛�${e.message}") {
+            }
+            e.printStackTrace()
+        }
+    }
+
+    /**
+     * 澶勭悊鐢ㄦ埛鍗�
+     */
+    private fun handleUserCard(cardNumber: String, cardType: String, nfcAdapter: NfcReadHelper) {
+        // 瑙f瀽鐢ㄦ埛鍗℃暟鎹�
+        val userCard = nfcAdapter.getUserCardData()
+        if (userCard == null) {
+            showConfirmDialog("瑙f瀽鍗$墖鏁版嵁澶辫触锛岃閲嶆柊鍒峰崱") {
+            }
+            return
+        }
+
+        // 杈撳嚭鐢ㄦ埛鍗″唴鎵�鏈変俊鎭埌鏃ュ織
+        android.util.Log.d("CardDeductActivity", "=== 鐢ㄦ埛鍗′俊鎭� ===")
+        android.util.Log.d("CardDeductActivity", "鍗″彿: $cardNumber")
+        android.util.Log.d("CardDeductActivity", "鍗$墖绫诲瀷: $cardType")
+        android.util.Log.d("CardDeductActivity", "鍗″唴浣欓: ${userCard.balance}")
+        android.util.Log.d("CardDeductActivity", "==================")
+        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.tvCardNumber.text = cardNumber
+
+        userCard.let { card ->
+            // 浣欓杞崲涓哄厓锛堝師濮嬫暟鎹彲鑳芥槸鍒嗭級
+            binding.tvCardBalance.text = MornyUtil.changeF2Y(card.balance) + "鍏�"
+        }
+
+        // 鏄剧ず鏈嶅姟鍣ㄦ暟鎹�
+        cardInfo?.let { info ->
+            binding.tvUserName.text = info.userName ?: "鏈煡"
+            binding.tvPhone.text = info.phone ?: "鏈粦瀹�"
+
+            // 鏍规嵁state瀛楁鏄剧ず鐘舵��
+            val (statusText, statusColor) = when (info.state) {
+                1 -> Pair("姝e父", 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)
+        }
+    }
+
+    /**
+     * 澶勭悊鍗′俊鎭幏鍙栭敊璇�
+     */
+    private fun handleCardInfoError(code: String?, msg: String?) {
+        val errorMessage: String = when (code) {
+            "1001" -> {
+                "璇ュ崱鐗囨湭鍦ㄧ郴缁熶腑娉ㄥ唽锛屾棤娉曡繘琛岃ˉ鎵f搷浣溿��"
+            }
+
+            else -> {
+                when {
+                    msg.isNullOrBlank() -> "鑾峰彇鍗′俊鎭け璐ワ紝璇烽噸鏂板埛鍗¢噸璇曘��"
+                    msg.contains("鏁版嵁涓嶅瓨鍦�") -> "璇ュ崱鐗囨湭鍦ㄧ郴缁熶腑娉ㄥ唽锛屾棤娉曡繘琛岃ˉ鎵f搷浣溿��"
+                    msg.contains("缃戠粶") -> "缃戠粶杩炴帴寮傚父锛岃妫�鏌ョ綉缁滆繛鎺ュ悗閲嶆柊鍒峰崱銆�"
+                    msg.contains("瓒呮椂") -> "缃戠粶璇锋眰瓒呮椂锛岃閲嶆柊鍒峰崱閲嶈瘯銆�"
+                    else -> "鑾峰彇鍗′俊鎭け璐ワ細$msg\n\n璇烽噸鏂板埛鍗¢噸璇曘��"
+                }
+            }
+        }
+
+        // 鏄剧ず閿欒淇℃伅鐨勫璇濇
+        showConfirmDialog(errorMessage) {
+            resetToReadingState()
+        }
+    }
+
+    /**
+     * 鎵ц琛ユ墸鎿嶄綔
+     */
+    private fun performCardDeduct() {
+        // 楠岃瘉杈撳叆
+        val deductAmountStr = binding.etDeductAmount.text.toString().trim()
+        val remarks = binding.etRemarks.text.toString().trim()
+
+        // 琛ユ墸閲戦楠岃瘉锛堝繀濉級
+        if (deductAmountStr.isEmpty()) {
+            ToastUtil.show("璇疯緭鍏ヨˉ鎵i噾棰�")
+            return
+        }
+
+        val deductAmount = try {
+            val amount = deductAmountStr.toDouble()
+            if (amount <= 0) {
+                ToastUtil.show("琛ユ墸閲戦蹇呴』澶т簬0")
+                return
+            }
+            amount
+        } catch (e: NumberFormatException) {
+            ToastUtil.show("璇疯緭鍏ユ湁鏁堢殑琛ユ墸閲戦")
+            return
+        }
+
+        // 澶囨敞澶勭悊锛堥潪蹇呭~锛�
+        val finalRemarks = if (remarks.isEmpty()) {
+            "琛ユ墸" // 濡傛灉鏈緭鍏ュ娉紝浣跨敤榛樿鍊�
+        } else {
+            remarks
+        }
+
+        callDeductCardApi(deductAmount, finalRemarks)
+    }
+
+    /**
+     * 璋冪敤琛ユ墸API鎺ュ彛
+     */
+    private fun callDeductCardApi(deductAmount: Double, finalRemarks: String) {
+        if (cardNumber.isNullOrBlank()) {
+            ToastUtil.show("鍗″彿淇℃伅寮傚父锛岃閲嶆柊鍒峰崱")
+            return
+        }
+
+        // 鑾峰彇褰撳墠鍗″唴浣欓锛堜互鍒嗕负鍗曚綅锛�
+        val currentBalance = userCard?.balance?.let { MornyUtil.changeF2Y(it) } ?: 0
+
+        val map = mutableMapOf<String, Any>()
+        map["cardNum"] = cardInfo?.cardNum.toString()
+        map["repayMorny"] = deductAmount.toString()
+        map["balance"] = currentBalance.toString()
+        map["remarks"] = finalRemarks
+        map["operator"] = BaseApplication.userId
+
+        ApiManager.getInstance().requestPostLoading(
+            this,
+            "terminal/card/termRepay",
+            CardDeductResult::class.java,
+            map,
+            object : SubscriberListener<BaseResponse<CardDeductResult>>() {
+                override fun onNext(t: BaseResponse<CardDeductResult>) {
+                    if (t.success && t.content != null) {
+                        // 琛ユ墸鎴愬姛锛岃烦杞埌鍐欏崱鐣岄潰
+                        startWriteCardActivity(t.content!!, deductAmount, 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(
+        deductResult: CardDeductResult,
+        deductAmount: 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(deductResult.balance.toString())
+        }
+
+        val intent = Intent(this, NfcWreatActivity::class.java).apply {
+            putExtra("cardAddr", cardNumber)
+            putExtra("operationTypeCode", CardOperationType.DeductCard.code) // 浣跨敤琛ユ墸绫诲瀷杩涜鍐欏崱
+            putExtra("orderNumber", deductResult.orderNo)
+            putExtra("deductAmount", deductAmount)
+            putExtra("userCard", updatedUserCard as java.io.Serializable)
+        }
+        startActivity(intent)
+        finish()
+    }
+} 
\ No newline at end of file
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt b/generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
index 7023d35..0f7accc 100644
--- a/generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
+++ b/generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
@@ -64,6 +64,22 @@
                 binding.successMessage.text = message
             }
             
+            CardOperationType.DeductCard -> {
+                // 璁剧疆鏍囬
+                binding.titleBar.setCenterText("琛ユ墸鎴愬姛")
+                
+                // 璁剧疆鎴愬姛淇℃伅
+                binding.successTitle.text = "琛ユ墸鎴愬姛"
+                
+                // 璁剧疆璇︾粏淇℃伅
+                val message = if (cardNumber.isNullOrBlank()) {
+                    "鍗$墖琛ユ墸鎿嶄綔宸叉垚鍔熷畬鎴怽n鍗″唴浣欓宸叉洿鏂�"
+                } else {
+                    "鍗$墖琛ユ墸鎿嶄綔宸叉垚鍔熷畬鎴怽n鍗″彿锛�$cardNumber\n鍗″唴浣欓宸叉洿鏂�"
+                }
+                binding.successMessage.text = message
+            }
+            
             else -> {
                 // 榛樿鏄剧ず鍐欏崱鎴愬姛
                 binding.titleBar.setCenterText("鍐欏崱鎴愬姛")
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt b/generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
index af6c1dc..d4f57d4 100644
--- a/generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
+++ b/generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -41,6 +41,9 @@
     // 杩旇繕鐩稿叧淇℃伅
     private var returnAmount = 0.0
 
+    // 琛ユ墸鐩稿叧淇℃伅
+    private var deductAmount = 0.0
+
     //璁㈠崟缂栧彿
     var orderNumber = ""
     private lateinit var userCard: UserCard
@@ -74,6 +77,9 @@
 
         // 鑾峰彇杩旇繕鐩稿叧淇℃伅
         returnAmount = intent?.getDoubleExtra("returnAmount", 0.0) ?: 0.0
+
+        // 鑾峰彇琛ユ墸鐩稿叧淇℃伅
+        deductAmount = intent?.getDoubleExtra("deductAmount", 0.0) ?: 0.0
 
         if (intent?.hasExtra("cardFee") == true) {
             cardFee = intent?.getIntExtra("cardFee", 0) ?: 0
@@ -174,8 +180,15 @@
                     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.CheckCard -> TODO()
-                CardOperationType.DeductCard -> TODO()
                 CardOperationType.ReplaceCard -> TODO()
                 null -> TODO()
             }
@@ -272,8 +285,22 @@
                     })
                 }
 
+                CardOperationType.DeductCard -> {
+                    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.DeductCard -> TODO()
                 CardOperationType.ReplaceCard -> TODO()
                 null -> TODO()
             }
diff --git a/generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt b/generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
index f460d84..65a9a42 100644
--- a/generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
+++ b/generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
@@ -405,15 +405,7 @@
             val userCard = UserCard().apply {
                 // 璁剧疆鐢ㄦ埛鍗′俊鎭�
                 cardInfo?.let { info ->
-                    userCode = info.cardNum ?: ""
-
-                    // 璁$畻鏂颁綑棰濓細鍘熸湁浣欓 + 鍏呭�奸噾棰� + 璧犻�侀噾棰�
-                    val originalBalance =
-                        this@RechargeDetailActivity.userCard?.balance ?: 0 // 鍘熸湁浣欓锛堝垎锛�
-                    val rechargeAmountInCents = (rechargeAmount * 100).toInt() // 鍏呭�奸噾棰濊浆鍒�
-                    val bonusAmountInCents = (bonusAmount * 100).toInt() // 璧犻�侀噾棰濊浆鍒�
-
-                    balance = originalBalance + rechargeAmountInCents + bonusAmountInCents
+                    balance = MornyUtil.changeY2F(rechargeResult.balance)
                 }
 
                 // 璁剧疆鍏朵粬蹇呰淇℃伅
diff --git a/generallibrary/src/main/java/com/dayu/general/bean/net/CardCancelResult.kt b/generallibrary/src/main/java/com/dayu/general/bean/net/CardCancelResult.kt
new file mode 100644
index 0000000..6dad537
--- /dev/null
+++ b/generallibrary/src/main/java/com/dayu/general/bean/net/CardCancelResult.kt
@@ -0,0 +1,13 @@
+package com.dayu.general.bean.net
+
+/**
+ * 閿�鍗$粨鏋滄暟鎹被
+ * @author: zuo
+ * @date: 2025/01/17
+ * @description: 閿�鍗℃帴鍙h繑鍥炴暟鎹�
+ */
+data class CardCancelResult(
+    val projectNo: Int,     // 椤圭洰缂栧彿
+    val cardNum: String,    // 鍗″彿
+    val orderNo: String     // 璁㈠崟鍙�
+) 
\ No newline at end of file
diff --git a/generallibrary/src/main/java/com/dayu/general/bean/net/CardDeductResult.kt b/generallibrary/src/main/java/com/dayu/general/bean/net/CardDeductResult.kt
new file mode 100644
index 0000000..b7939d9
--- /dev/null
+++ b/generallibrary/src/main/java/com/dayu/general/bean/net/CardDeductResult.kt
@@ -0,0 +1,33 @@
+/**
+ * @author: AI Assistant
+ * @desc: 琛ユ墸鎺ュ彛杩斿洖缁撴灉
+ * @since: 2025/6/17
+ */
+package com.dayu.general.bean.net
+
+import java.io.Serializable
+
+/**
+ * 琛ユ墸鎿嶄綔鐨凙PI杩斿洖缁撴灉
+ */
+data class CardDeductResult(
+    /**
+     * 琛ユ墸鍚庣殑浣欓
+     */
+    val balance: Float = 0f,
+
+    /**
+     * 姘翠环
+     */
+    val waterPrice: Double = 0.0,
+
+    /**
+     * 鏃堕棿
+     */
+    val time: String = "",
+
+    /**
+     * 璁㈠崟鍙�
+     */
+    val orderNo: String = ""
+) : Serializable 
\ No newline at end of file
diff --git a/generallibrary/src/main/java/com/dayu/general/bean/net/CardReturnResult.kt b/generallibrary/src/main/java/com/dayu/general/bean/net/CardReturnResult.kt
new file mode 100644
index 0000000..b18a885
--- /dev/null
+++ b/generallibrary/src/main/java/com/dayu/general/bean/net/CardReturnResult.kt
@@ -0,0 +1,33 @@
+/**
+ * @author: zuo
+ * @desc: 杩旇繕鎺ュ彛杩斿洖缁撴灉
+ * @since: 2025/6/17
+ */
+package com.dayu.general.bean.net
+
+import java.io.Serializable
+
+/**
+ * 杩旇繕鎿嶄綔鐨凙PI杩斿洖缁撴灉
+ */
+data class CardReturnResult(
+    /**
+     * 杩旇繕鍚庣殑浣欓
+     */
+    val balance: Float = 0f,
+
+    /**
+     * 姘翠环
+     */
+    val waterPrice: Double = 0.0,
+
+    /**
+     * 鏃堕棿
+     */
+    val time: String = "",
+
+    /**
+     * 璁㈠崟鍙�
+     */
+    val orderNo: String = ""
+) : Serializable 
\ No newline at end of file
diff --git a/generallibrary/src/main/java/com/dayu/general/bean/net/RechargeResult.kt b/generallibrary/src/main/java/com/dayu/general/bean/net/RechargeResult.kt
index d6507a3..9cd6c07 100644
--- a/generallibrary/src/main/java/com/dayu/general/bean/net/RechargeResult.kt
+++ b/generallibrary/src/main/java/com/dayu/general/bean/net/RechargeResult.kt
@@ -10,5 +10,6 @@
     val cardNum: String,             // 鍗″彿
     val orderNo: String,             // 璁㈠崟鍙�
     val waterPrice: Double,          // 姘翠环
-    val time: String                 // 鏃堕棿
+    val time: String,                // 鏃堕棿
+    val balance: String              // 浣欓
 ) : Serializable 
\ No newline at end of file
diff --git a/generallibrary/src/main/res/drawable/button_green_bg.xml b/generallibrary/src/main/res/drawable/button_green_bg.xml
new file mode 100644
index 0000000..6ae265a
--- /dev/null
+++ b/generallibrary/src/main/res/drawable/button_green_bg.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/button_select_text_color" />
+    <corners android:radius="6dp" />
+</shape> 
\ No newline at end of file
diff --git a/generallibrary/src/main/res/layout/activity_card_deduct.xml b/generallibrary/src/main/res/layout/activity_card_deduct.xml
new file mode 100644
index 0000000..cea2102
--- /dev/null
+++ b/generallibrary/src/main/res/layout/activity_card_deduct.xml
@@ -0,0 +1,412 @@
+<?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:id="@+id/scroll_read_card"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_below="@+id/titleBar"
+        android:fillViewport="true"
+        android:visibility="visible">
+
+        <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">
+
+                <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="璇峰皢闇�瑕佽ˉ鎵g殑鍗$墖璐村湪璁惧涓婅繘琛岃鍙�"
+                            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"
+                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">
+
+                    <LinearLayout
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:orientation="vertical"
+                        android:padding="12dp">
+
+                        <TextView
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="8dp"
+                            android:gravity=""
+                            android:text="鍗$墖淇℃伅"
+                            android:textColor="@color/base_blue_bg"
+                            android:textSize="16sp"
+                            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="8dp">
+
+                            <TextView
+                                android:layout_width="80dp"
+                                android:layout_height="wrap_content"
+                                android:text="鎸佸崱浜猴細"
+                                android:textColor="#333333"
+                                android:textSize="14sp" />
+
+                            <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="14sp" />
+                        </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="8dp">
+
+                            <TextView
+                                android:layout_width="80dp"
+                                android:layout_height="wrap_content"
+                                android:text="鍗″湴鍧�锛�"
+                                android:textColor="#333333"
+                                android:textSize="14sp" />
+
+                            <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="14sp" />
+                        </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="8dp">
+
+                            <TextView
+                                android:layout_width="80dp"
+                                android:layout_height="wrap_content"
+                                android:text="鍗$墖鐘舵�侊細"
+                                android:textColor="#333333"
+                                android:textSize="14sp" />
+
+                            <TextView
+                                android:id="@+id/tv_card_status"
+                                android:layout_width="0dp"
+                                android:layout_height="wrap_content"
+                                android:layout_weight="1"
+                                android:text="姝e父"
+                                android:textColor="#4CAF50"
+                                android:textSize="14sp" />
+                        </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="8dp">
+
+                            <TextView
+                                android:layout_width="80dp"
+                                android:layout_height="wrap_content"
+                                android:text="鍗″唴浣欓锛�"
+                                android:textColor="#333333"
+                                android:textSize="14sp" />
+
+                            <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="14sp"
+                                android:textStyle="bold" />
+                        </LinearLayout>
+
+                        <!-- 鎵嬫満鍙� -->
+                        <LinearLayout
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:background="#F8F9FA"
+                            android:gravity="center_vertical"
+                            android:orientation="horizontal"
+                            android:padding="8dp">
+
+                            <TextView
+                                android:layout_width="80dp"
+                                android:layout_height="wrap_content"
+                                android:text="鎵嬫満鍙凤細"
+                                android:textColor="#333333"
+                                android:textSize="14sp" />
+
+                            <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="14sp" />
+                        </LinearLayout>
+
+                    </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="12dp">
+
+                        <TextView
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="12dp"
+                            android:gravity=""
+                            android:text="琛ユ墸鎿嶄綔"
+                            android:textColor="@color/base_blue_bg"
+                            android:textSize="16sp"
+                            android:textStyle="bold" />
+
+                        <!-- 琛ユ墸閲戦鍜屽娉ㄥ苟鎺掓樉绀� -->
+                        <LinearLayout
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:orientation="vertical">
+
+                            <!-- 琛ユ墸閲戦杈撳叆 -->
+                            <LinearLayout
+                                android:layout_width="match_parent"
+                                android:layout_height="wrap_content"
+                                android:layout_marginEnd="6dp"
+                                android:layout_weight="1"
+                                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_deduct_amount"
+                                    android:layout_width="match_parent"
+                                    android:layout_height="40dp"
+                                    android:layout_marginTop="5dp"
+                                    android:background="@drawable/edit_text_bg"
+                                    android:hint="璇疯緭鍏ヨˉ鎵i噾棰�"
+                                    android:inputType="numberDecimal"
+                                    android:padding="8dp"
+                                    android:textColor="#333333"
+                                    android:textColorHint="#999999"
+                                    android:textSize="14sp" />
+                            </LinearLayout>
+
+                            <!-- 澶囨敞杈撳叆 -->
+                            <LinearLayout
+                                android:layout_width="match_parent"
+                                android:layout_height="wrap_content"
+                                android:layout_marginTop="5dp"
+                                android:layout_weight="1"
+                                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_remarks"
+                                    android:layout_width="match_parent"
+                                    android:layout_height="80dp"
+                                    android:layout_marginTop="5dp"
+                                    android:background="@drawable/edit_text_bg"
+                                    android:hint="璇疯緭鍏ヨˉ鎵e娉�"
+                                    android:inputType="text"
+                                    android:minLines="2"
+                                    android:padding="8dp"
+                                    android:textColor="#333333"
+                                    android:textColorHint="#999999"
+                                    android:textSize="14sp" />
+                            </LinearLayout>
+
+                        </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">
+
+        <!-- 琛ユ墸鎸夐挳 -->
+        <Button
+            android:id="@+id/btn_deduct"
+            android:layout_width="match_parent"
+            android:layout_height="48dp"
+            android:background="@drawable/button_green_bg"
+            android:text="纭琛ユ墸"
+            android:textColor="#FFFFFF"
+            android:textSize="@dimen/big_text_size"
+            android:textStyle="bold" />
+
+    </LinearLayout>
+
+</RelativeLayout> 
\ No newline at end of file

--
Gitblit v1.8.0