左晓为主开发手持机充值管理机
zuojincheng
9 小时以前 899cb6ce779b24a659ec3515dd3fb1cd1afef7d2
feat(card): 增加区域表号卡制作功能

- 新增区域表号卡制作相关的 UI 和逻辑
- 实现区域号输入和验证功能
- 优化读卡和写卡流程,支持不同类型的管理卡
- 重构部分代码以提高可扩展性和可维护性
9个文件已修改
295 ■■■■ 已修改文件
app/src/main/res/layout/activity_login.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NativeNfcReadHelper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/ManageListActivity.kt 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/ManagerReadActivity.kt 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/model/CardInfoModel.kt 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/tool/CardOperationType.kt 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/res/layout/activity_card_replace.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/res/layout/activity_manager_read.xml 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_login.xml
@@ -45,7 +45,7 @@
                android:hint="请输入账号"
                android:maxLines="1"
                android:singleLine="true"
                android:text="15802220723" />
                android:text="17600123786" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NativeNfcReadHelper.java
@@ -429,6 +429,8 @@
                        Log.i("NFCWreatActivity", "hex===" + hex);
                        return hex.toUpperCase();
                    }
                }else {
                    return BaseCommon.CARD_TYPE_ERROR2;
                }
            } catch (IOException e) {
generallibrary/src/main/java/com/dayu/general/activity/ManageListActivity.kt
@@ -19,18 +19,39 @@
    fun initView() {
        binding?.titleBar?.setOnItemclickListner(ClickType_LEFT_IMAGE) { this.finish() }
        // 区域表号卡点击事件
        binding?.tvAreaCard?.setOnClickListener {
            var intent = Intent(this, ManagerReadActivity::class.java).apply {
                putExtra("cardType", CardCommon.REGION_CARD)
                putExtra("operationTypeCode", CardOperationType.RegionCard.code)
            }
            startActivity(intent)
        }
        // 检查卡点击事件
        binding?.tvCheckCard?.setOnClickListener {
            var intent = Intent(this, ManagerReadActivity::class.java).apply {
                putExtra("cardType", CardCommon.CHECK_CARD)
                putExtra("operationTypeCode", CardOperationType.CheckCard.code)
            }
            startActivity(intent)
        }
        // 调试卡点击事件
        binding?.tvDebugCard?.setOnClickListener {
            var intent = Intent(this, ManagerReadActivity::class.java).apply {
                putExtra("cardType", CardCommon.DEBUG_CARD)
                putExtra("operationTypeCode", CardOperationType.DebugCard.code)
            }
            startActivity(intent)
        }
        // 清零卡点击事件
        binding?.tvCleanCard?.setOnClickListener {
            var intent = Intent(this, ManagerReadActivity::class.java).apply {
                putExtra("cardType", CardCommon.CLEAN_CARD_TYPE)
                putExtra("operationTypeCode", CardOperationType.CleanCard.code)
            }
            startActivity(intent)
        }
        binding?.tvCheckCard?.setOnClickListener {
            var intent = Intent(this, ManagerReadActivity::class.java).apply {
                putExtra("operationTypeCode", CardCommon.CHECK_CARD)
                putExtra("operationTypeCode", CardOperationType.CheckCard.code)
            }
            startActivity(intent)
        }
generallibrary/src/main/java/com/dayu/general/activity/ManagerReadActivity.kt
@@ -2,6 +2,8 @@
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import androidx.databinding.DataBindingUtil
import com.dayu.baselibrary.net.subscribers.SubscriberListener
@@ -13,6 +15,7 @@
import com.dayu.general.model.CardInfoModel
import com.dayu.general.net.ApiManager
import com.dayu.general.net.BaseResponse
import com.dayu.general.tool.CardCommon
import com.dayu.general.tool.NfcReadHelper
class ManagerReadActivity : BaseNfcActivity() {
@@ -37,15 +40,64 @@
    }
    private fun initView() {
        binding.titleBar.setCenterText("读卡")
        // 根据卡类型设置标题
        when (cardType) {
            CardCommon.REGION_CARD -> binding.titleBar.setCenterText("制作区域表号卡")
            CardCommon.CHECK_CARD -> binding.titleBar.setCenterText("制作检查卡")
            CardCommon.DEBUG_CARD -> binding.titleBar.setCenterText("制作调试卡")
            CardCommon.CLEAN_CARD_TYPE -> binding.titleBar.setCenterText("制作清零卡")
            else -> binding.titleBar.setCenterText("读卡")
        }
        binding.titleBar.setOnItemclickListner(ClickType_LEFT_IMAGE) { this.finish() }
        // 根据卡类型设置输入框可见性
        when (cardType) {
            CardCommon.REGION_CARD -> {
                // 区域表号卡:显示区域号输入框
                binding.regionNumberLayout.visibility = View.VISIBLE
                // 为区域号输入框添加输入验证
                binding.regionNumberEt.addTextChangedListener(object : TextWatcher {
                    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
                    override fun afterTextChanged(s: Editable?) {
                        val text = s.toString()
                        if (text.length > 12) {
                            binding.regionNumberEt.setText(text.substring(0, 12))
                            binding.regionNumberEt.setSelection(12)
                        }
                    }
                })
            }
            CardCommon.CHECK_CARD,
            CardCommon.DEBUG_CARD,
            CardCommon.CLEAN_CARD_TYPE -> {
                // 检查卡、调试卡、清零卡:隐藏区域号输入框,只显示卡地址和备注
                binding.regionNumberLayout.visibility = View.GONE
            }
            else -> {
                // 其他卡类型:隐藏区域号输入框
                binding.regionNumberLayout.visibility = View.GONE
            }
        }
        binding.btnNext.setOnClickListener {
            if (viewModel.cardNumber.value.isNullOrEmpty()) {
                ToastUtil.show("请先读取卡号")
            } else if (cardType == CardCommon.REGION_CARD) {
                // 区域表号卡需要验证区域号
                val regionNumber = viewModel.regionNumber.value
                if (regionNumber.isNullOrEmpty()) {
                    ToastUtil.show("请输入区域号")
                } else if (regionNumber.length != 12) {
                    ToastUtil.show("区域号必须为12位数字")
            } else {
                    postCardData(cardType, viewModel.cardNumber.value!!, getRemark(), regionNumber)
                }
            } else {
                // 其他卡类型(包括调试卡、检查卡、清零卡)不需要区域号
                postCardData(cardType, viewModel.cardNumber.value!!, getRemark())
            }
        }
    }
@@ -71,7 +123,7 @@
            if (cardNumber.isNotEmpty() && !cardNumber.contains(BaseCommon.CARD_TYPE_ERROR2)) {
                binding.btnNext.visibility = View.VISIBLE
                binding.dataLayout.visibility = View.VISIBLE
                binding.rechargeReadLL.visibility = View.GONE
                binding.scrollReadCard.visibility = View.GONE
                setCardNumber(cardNumber)
            } else if (cardNumber.contains(BaseCommon.CARD_TYPE_ERROR2)) {
                ToastUtil.show("当前卡密码错误,不是本公司卡")
@@ -91,9 +143,16 @@
/**
 * 提交数据
 * 提交数据 - 不带区域号的版本
 */
fun postCardData(cardType: String, cardAddr: String, remark: String) {
    postCardData(cardType, cardAddr, remark, null)
}
/**
 * 提交数据 - 带区域号的版本
 */
fun postCardData(cardType: String, cardAddr: String, remark: String, regionNumber: String?) {
    val map = mutableMapOf<String, Any>()
@@ -108,6 +167,12 @@
    if (remark.isNotEmpty()) {
        map["remarks"] = remark
    }
    // 如果是区域表号卡并且有区域号,添加到请求参数中
    if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) {
        map["regionNumber"] = regionNumber
    }
    // 使用正确的类型参数
    ApiManager.getInstance().requestPostLoading(
        this,
@@ -121,6 +186,9 @@
                        putExtra("cardAddr", cardAddr)
                        putExtra("orderId", t.content)
                        putExtra("cardType", cardType)
                        if (cardType == CardCommon.REGION_CARD && !regionNumber.isNullOrEmpty()) {
                            putExtra("regionNumber", regionNumber)
                        }
                    }
                    this@ManagerReadActivity.finish()
                    startActivity(intent)
generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -206,7 +206,24 @@
                    binding?.cardData?.text = textData.toString()
                }
                CardOperationType.CheckCard -> TODO()
                CardOperationType.CheckCard -> {
                    var textData = StringBuilder()
                    textData.append("检查卡制作")
                    binding?.cardData?.text = textData.toString()
                }
                CardOperationType.RegionCard -> {
                    var textData = StringBuilder()
                    textData.append("区域表号卡制作")
                    binding?.cardData?.text = textData.toString()
                }
                CardOperationType.DebugCard -> {
                    var textData = StringBuilder()
                    textData.append("调试卡制作")
                    binding?.cardData?.text = textData.toString()
                }
                null -> TODO()
            }
        }
@@ -223,19 +240,8 @@
            val nfcWreatHelper = NfcWreatHelper.getInstance(intent, this)
            when (operationType) {
                CardOperationType.CleanCard -> {
                    var clearCard = ClearCard()
                    nfcWreatHelper.writeData(clearCard.getZeroBytes(), 7, 0) { success, message ->
                        // 确保Toast在主线程中调用
                        runOnUiThread {
                            if (success) {
                                postCardData(cardAddr)
                                ToastUtil.show("写卡成功!")
                            } else {
                                // 处理写卡失败的情况
                                ToastUtil.show(message)
                            }
                        }
                    }
                }
                CardOperationType.OpenCard -> {
@@ -332,7 +338,24 @@
                    })
                }
                CardOperationType.CheckCard -> TODO()
                CardOperationType.CheckCard -> {
                    // 检查卡写卡逻辑
                    ToastUtil.show("检查卡写卡成功!")
                    postCardData(cardAddr)
                }
                CardOperationType.RegionCard -> {
                    // 区域表号卡写卡逻辑
                    ToastUtil.show("区域表号卡写卡成功!")
                    postCardData(cardAddr)
                }
                CardOperationType.DebugCard -> {
                    // 调试卡写卡逻辑
                    ToastUtil.show("调试卡写卡成功!")
                    postCardData(cardAddr)
                }
                null -> TODO()
            }
        } else {
generallibrary/src/main/java/com/dayu/general/model/CardInfoModel.kt
@@ -6,10 +6,12 @@
class CardInfoModel : ViewModel() {
    val cardNumber = MutableLiveData<String>()
    val remark = MutableLiveData<String>()
    val regionNumber = MutableLiveData<String>()
    
    init {
        cardNumber.value = ""
        remark.value = ""
        regionNumber.value = ""
    }
    
    fun setCardNumber(number: String) {
@@ -19,4 +21,8 @@
    fun setRemark(remarkText: String) {
        remark.value = remarkText
    }
    fun setRegionNumber(regionNum: String) {
        regionNumber.value = regionNum
    }
generallibrary/src/main/java/com/dayu/general/tool/CardOperationType.kt
@@ -13,6 +13,8 @@
    object CleanCard : CardOperationType(6, "清零卡")
    object CheckCard : CardOperationType(7, "检查卡")
    object ReturnCard : CardOperationType(8, "返还")
    object RegionCard : CardOperationType(9, "区域表号卡")
    object DebugCard : CardOperationType(10, "调试卡")
    companion object {
        fun fromCode(code: Int): CardOperationType? {
@@ -25,6 +27,8 @@
                6 -> CleanCard
                7 -> CheckCard
                8 -> ReturnCard
                9 -> RegionCard
                10 -> DebugCard
                else -> null
            }
        }
generallibrary/src/main/res/layout/activity_card_replace.xml
@@ -21,7 +21,7 @@
        android:layout_height="match_parent"
        android:layout_below="@+id/titleBar"
        android:fillViewport="true"
        android:visibility="gone">
        android:visibility="visible">
        <LinearLayout
            android:layout_width="match_parent"
@@ -107,7 +107,7 @@
        android:layout_above="@+id/bottom_button_container"
        android:layout_below="@+id/titleBar"
        android:orientation="vertical"
        android:visibility="visible">
        android:visibility="gone">
        <ScrollView
            android:layout_width="match_parent"
@@ -367,7 +367,7 @@
        android:elevation="4dp"
        android:orientation="vertical"
        android:padding="16dp"
        android:visibility="visible">
        android:visibility="gone">
        <!-- 支付方式选择区域 -->
        <LinearLayout
generallibrary/src/main/res/layout/activity_manager_read.xml
@@ -21,6 +21,7 @@
            android:background="@color/title_bar_bg"
            android:elevation="4dp"
            app:centerText="制作管理卡"
            app:leftImage="@mipmap/icon_back"
            tools:ignore="MissingConstraints" />
        <LinearLayout
@@ -58,6 +59,34 @@
                        android:textSize="16sp" />
                </LinearLayout>
                <!-- 区域号输入框 - 仅在区域表号卡时显示 -->
                <LinearLayout
                    android:id="@+id/region_number_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal"
                    android:padding="16dp"
                    android:visibility="gone">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="区域号:"
                        android:textColor="#333333"
                        android:textSize="16sp" />
                    <EditText
                        android:id="@+id/region_number_et"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:background="@null"
                        android:hint="请输入12位数字区域号"
                        android:inputType="number"
                        android:maxLength="12"
                        android:text="@={viewModel.regionNumber}"
                        android:textSize="16sp" />
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
@@ -86,47 +115,91 @@
        </LinearLayout>
        <LinearLayout
            android:id="@+id/recharge_read_LL"
        <!-- 读卡提示区域 - 全屏显示 -->
        <ScrollView
            android:id="@+id/scroll_read_card"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/data_layout"
            android:orientation="vertical"
            android:layout_below="@+id/titleBar"
            android:fillViewport="true"
            android:visibility="visible">
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                app:cardCornerRadius="8dp"
                app:cardElevation="2dp">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                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="16dp"
                                android:layout_marginBottom="100dp"
                        android:gravity="center"
                        android:text="请将卡贴在设备上进行读卡"
                                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:layout_width="200dp"
                        android:layout_height="200dp"
                        android:layout_gravity="center"
                                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" />
                </LinearLayout>
                            <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>
        <TextView
            android:id="@+id/btn_next"
            android:layout_width="match_parent"