左晓为主开发手持机充值管理机
zuoxiao
7 天以前 1e2d09f0009c16ac36f199e1723bbe31dc335657
feat(generallibrary): 优化开卡流程和界面

-调整了开卡界面布局,优化了用户信息展示
- 增加了客户ID字段,用于获取客户详细信息
- 修改了金额输入框的提示文本
- 优化了支付方式列表的展示
- 调整了注册新卡的逻辑
- 修改了搜索用户列表和结果的数据结构
6个文件已修改
269 ■■■■■ 已修改文件
generallibrary/src/main/cpp/general-native-lib.cpp 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/NewCard2Activity.kt 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/SearchUserListActivity.kt 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/bean/net/SearchCardResult.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/bean/net/SearchUserResult.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/res/layout/activity_new_card_1_ge.xml 119 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/cpp/general-native-lib.cpp
@@ -96,19 +96,19 @@
        return nullptr;
    }
    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypting sector %d", sector);
    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Encrypted data: %02X %02X %02X %02X %02X %02X",
                       encrypted_data[0], encrypted_data[1], encrypted_data[2],
                       encrypted_data[3], encrypted_data[4], encrypted_data[5]);
    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Using XOR key: %02X %02X %02X %02X %02X %02X",
                       XOR_KEYS[sector][0], XOR_KEYS[sector][1], XOR_KEYS[sector][2],
                       XOR_KEYS[sector][3], XOR_KEYS[sector][4], XOR_KEYS[sector][5]);
//    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypting sector %d", sector);
//    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Encrypted data: %02X %02X %02X %02X %02X %02X",
//                       encrypted_data[0], encrypted_data[1], encrypted_data[2],
//                       encrypted_data[3], encrypted_data[4], encrypted_data[5]);
//    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Using XOR key: %02X %02X %02X %02X %02X %02X",
//                       XOR_KEYS[sector][0], XOR_KEYS[sector][1], XOR_KEYS[sector][2],
//                       XOR_KEYS[sector][3], XOR_KEYS[sector][4], XOR_KEYS[sector][5]);
    unsigned char decrypted[6];
    for (int i = 0; i < 6; i++) {
        decrypted[i] = encrypted_data[i] ^ XOR_KEYS[sector][i];
        __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Byte %d: %02X ^ %02X = %02X",
                          i, encrypted_data[i], XOR_KEYS[sector][i], decrypted[i]);
//        __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Byte %d: %02X ^ %02X = %02X",
//                          i, encrypted_data[i], XOR_KEYS[sector][i], decrypted[i]);
    }
    std::string result;
@@ -119,7 +119,7 @@
        result += hex;
    }
    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypted result: %s", result.c_str());
//    __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypted result: %s", result.c_str());
    return env->NewStringUTF(result.c_str());
}
@@ -187,7 +187,7 @@
    jobject packageInfoObject = env->CallObjectMethod(packageManagerObject, getPackageInfoId,
                                                    packNameString, 64);
    if (!packageInfoObject) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get PackageInfo");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get PackageInfo");
        return env->NewStringUTF("");
    }
@@ -195,7 +195,7 @@
    jfieldID signaturefieldID = env->GetFieldID(packageInfoClass, "signatures",
                                              "[Landroid/content/pm/Signature;");
    if (!signaturefieldID) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature field ID");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature field ID");
        return env->NewStringUTF("");
    }
@@ -203,28 +203,28 @@
    jobjectArray signatureArray = (jobjectArray) env->GetObjectField(packageInfoObject,
                                                                   signaturefieldID);
    if (!signatureArray || env->GetArrayLength(signatureArray) == 0) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "No signatures found");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "No signatures found");
        return env->NewStringUTF("");
    }
    // 获取第一个签名对象
    jobject signatureObject = env->GetObjectArrayElement(signatureArray, 0);
    if (!signatureObject) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature object");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature object");
        return env->NewStringUTF("");
    }
    // 获取签名字符串
    jstring signatureString = (jstring) env->CallObjectMethod(signatureObject, signToStringId);
    if (!signatureString) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature string");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature string");
        return env->NewStringUTF("");
    }
    // 获取签名字符串的UTF-8字符
    const char *signStrng = env->GetStringUTFChars(signatureString, 0);
    if (!signStrng) {
        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature UTF chars");
//        __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature UTF chars");
        return env->NewStringUTF("");
    }
@@ -240,11 +240,11 @@
        // 解密并转换每个扇区密钥
        for (size_t i = 0; i < numKeys; i++) {
           __android_log_print(ANDROID_LOG_DEBUG, "M1Card", "处理扇区 %zu 的密钥", i);
//           __android_log_print(ANDROID_LOG_DEBUG, "M1Card", "处理扇区 %zu 的密钥", i);
            
            // 确保不会越界访问
            if (i * 12 + 6 > sizeof(ENCRYPTED_SECTOR_KEYS)) {
                __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Index out of bounds");
//                __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Index out of bounds");
                break;
            }
            
@@ -252,7 +252,7 @@
            jstring decrypted_str = decrypt_key(env, ENCRYPTED_SECTOR_KEYS + (i * 12), 6);
            
            if (!decrypted_str) {
               __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to decrypt key for sector %zu", i);
//               __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to decrypt key for sector %zu", i);
                continue;
            }
            
generallibrary/src/main/java/com/dayu/general/activity/NewCard2Activity.kt
@@ -47,6 +47,9 @@
    // 用户ID
    private var userId: String = ""
    // 客户ID
    private var clientId: String = ""
    companion object {
        private const val TAG = "NewCard2Activity"
@@ -68,18 +71,40 @@
        val pageSize: Any?,
        val pageTotal: Any?
    )
    // 用户信息数据类
    data class ClientInfo(
        val clientId: String,
        val clientNum: String,
        val name: String,
        val districtNum: String,
        val phone: String,
        val idCard: String,
        val villageName: String,
        val address: String,
        val cardCount: Int,
        val operateDt: String
    )
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityNewCard1GeBinding.inflate(layoutInflater)
        setContentView(binding.root)
        // 获取传递的clientId参数
        clientId = intent.getStringExtra("clientId") ?: ""
        initView()
        // 如果有clientId,获取客户信息
        if (clientId.isNotEmpty()) {
            getClientInfo(clientId)
        }
        // 获取支付方式
        getPaymentMethods()
        initListener()
    }
    private fun initView() {
        // 初始化标题栏返回按钮
@@ -90,21 +115,66 @@
        // 初始化NFC读卡容器,初始隐藏
        binding.nfcContainer.visibility = View.VISIBLE
        // 从Intent中获取用户信息(如果有)
        val userName = intent.getStringExtra("userName") ?: ""
        val rawIdCard = intent.getStringExtra("idCard")
        val idCard = if (rawIdCard.isNullOrBlank()) "无" else rawIdCard
        val farmerCode = intent.getStringExtra("farmerCode") ?: ""
        userId = intent.getStringExtra("userId") ?: ""
        // 设置用户信息
        binding.newCardUserName.text = userName
        binding.newCardIdCard.text = idCard
        binding.newCardFarmerCode.text = farmerCode
        // 设置金额输入限制为两位小数
        binding.newCardRechargeAmount.addTextChangedListener(createDecimalTextWatcher())
        binding.newCardCardFee.addTextChangedListener(createDecimalTextWatcher())
    }
    /**
     * 获取客户详细信息
     */
    private fun getClientInfo(clientId: String) {
        ApiManager.getInstance().requestGetLoading(
            this,
            "terminal/client/getTermOne/$clientId",
            ClientInfo::class.java,
            null,
            object : SubscriberListener<BaseResponse<ClientInfo>>() {
                override fun onNext(response: BaseResponse<ClientInfo>) {
                    if (response.success) {
                        val clientInfo = response.content
                        if (clientInfo != null) {
                            // 显示客户信息到界面
                            displayClientInfo(clientInfo)
                        } else {
                            Toast.makeText(
                                this@NewCard2Activity,
                                "获取客户信息失败: 返回数据为空",
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                    } else {
                        Toast.makeText(
                            this@NewCard2Activity,
                            "获取客户信息失败: ${response.msg}",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    Toast.makeText(
                        this@NewCard2Activity,
                        "获取客户信息失败: ${e?.message ?: "网络异常"}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        )
    }
    /**
     * 显示客户信息到界面
     */
    private fun displayClientInfo(clientInfo: ClientInfo) {
        // 保存用户ID供后续使用
        userId = clientInfo.clientId
        // 显示用户基本信息
        binding.newCardUserName.text = clientInfo.name
        binding.newCardIdCard.text = if (clientInfo.idCard.isBlank()) "无" else clientInfo.idCard
        binding.newCardFarmerCode.text = clientInfo.clientNum
    }
    /**
@@ -244,6 +314,9 @@
        }
    }
    /**
     * 注册新卡
     */
    private fun registerNewCard() {
        // 获取充值金额
        val rechargeAmountStr = binding.newCardRechargeAmount.text.toString()
generallibrary/src/main/java/com/dayu/general/activity/SearchUserListActivity.kt
@@ -86,10 +86,7 @@
            // 处理用户点击事件
            // 传递用户信息到开卡界面
            val intent = Intent(this, NewCard2Activity::class.java)
            intent.putExtra("userName", user.name)
            intent.putExtra("idCard", user.idCard)
            intent.putExtra("farmerCode", user.clientNum)
            intent.putExtra("userId", user.id)
            intent.putExtra("clientId", user.clientId)
            startActivity(intent)
        }
generallibrary/src/main/java/com/dayu/general/bean/net/SearchCardResult.kt
@@ -24,6 +24,7 @@
        val idCard: String? = null,        // 身份证号
        val money: String? = null,         // 卡余额
        val phone: String? = null,         // 电话号码
        val stateName: String? = null      // 状态名称
        val stateName: String? = null,     // 状态名称
        val clientId: String? = null       // 客户ID
    )
generallibrary/src/main/java/com/dayu/general/bean/net/SearchUserResult.kt
@@ -17,7 +17,7 @@
    /**
     * 用户信息
     */
    data class UserInfo (
    data class UserInfo(
        val address: String? = null,   // 地址
        val cardCount: Int? = null,    // 卡数量
        val clientNum: String? = null, // 客户编号
@@ -25,6 +25,7 @@
        val idCard: String? = null,    // 身份证
        val name: String? = null,      // 姓名
        val operateDt: String? = null, // 操作日期
        val phone: String? = null      // 电话
        val phone: String? = null,      // 电话
        val clientId: String? = null       // 客户ID
    )
}
generallibrary/src/main/res/layout/activity_new_card_1_ge.xml
@@ -24,7 +24,7 @@
        android:layout_marginTop="24dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="24dp"
        android:visibility="visible"
        android:visibility="gone"
        app:cardBackgroundColor="@android:color/white"
        app:cardCornerRadius="12dp"
        app:cardElevation="4dp"
@@ -85,8 +85,8 @@
        android:layout_height="0dp"
        android:fillViewport="true"
        android:scrollbars="none"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        android:visibility="visible"
        app:layout_constraintBottom_toTopOf="@+id/newCard_registBtn"
        app:layout_constraintTop_toBottomOf="@+id/titleBar">
        <LinearLayout
@@ -236,7 +236,51 @@
                        android:textColor="#333333"
                        android:textSize="18sp"
                        android:textStyle="bold" />
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="12dp"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">
                        <TextView
                            android:layout_width="105dp"
                            android:layout_height="wrap_content"
                            android:text="工本费:"
                            android:textColor="#666666"
                            android:textSize="@dimen/new_card_size" />
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="@drawable/edit_text_bg_selector"
                            android:orientation="horizontal"
                            android:gravity="center_vertical"
                            android:paddingStart="10dp"
                            android:paddingEnd="10dp"
                            android:paddingTop="8dp"
                            android:paddingBottom="8dp">
                            <EditText
                                android:id="@+id/newCard_cardFee"
                                android:layout_width="0dp"
                                android:layout_weight="1"
                                android:layout_height="wrap_content"
                                android:background="@null"
                                android:hint="请输入工本费(选填)"
                                android:inputType="numberDecimal"
                                android:textColor="#333333"
                                android:textColorHint="#BBBBBB"
                                android:textSize="@dimen/new_card_size" />
                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="元"
                                android:textColor="#666666"
                                android:textSize="@dimen/new_card_size" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
@@ -283,51 +327,7 @@
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="12dp"
                        android:gravity="center_vertical"
                        android:orientation="horizontal">
                        <TextView
                            android:layout_width="105dp"
                            android:layout_height="wrap_content"
                            android:text="工本费:"
                            android:textColor="#666666"
                            android:textSize="@dimen/new_card_size" />
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="@drawable/edit_text_bg_selector"
                            android:orientation="horizontal"
                            android:gravity="center_vertical"
                            android:paddingStart="10dp"
                            android:paddingEnd="10dp"
                            android:paddingTop="8dp"
                            android:paddingBottom="8dp">
                            <EditText
                                android:id="@+id/newCard_cardFee"
                                android:layout_width="0dp"
                                android:layout_weight="1"
                                android:layout_height="wrap_content"
                                android:background="@null"
                                android:hint="请输入工本费(选填)"
                                android:inputType="numberDecimal"
                                android:textColor="#333333"
                                android:textColorHint="#BBBBBB"
                                android:textSize="@dimen/new_card_size" />
                            <TextView
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:text="元"
                                android:textColor="#666666"
                                android:textSize="@dimen/new_card_size" />
                        </LinearLayout>
                    </LinearLayout>
                    <LinearLayout
                        android:layout_width="match_parent"
@@ -397,18 +397,21 @@
                    </RadioGroup>
                </LinearLayout>
            </androidx.cardview.widget.CardView>
            <TextView
                android:id="@+id/newCard_registBtn"
                android:layout_width="match_parent"
                android:layout_height="56dp"
                android:layout_marginTop="15dp"
                android:background="@color/bottom_color"
                android:visibility="visible"
                android:gravity="center"
                android:text="确认开卡"
                android:textColor="#FFFFFF"
                android:textSize="16sp" />
        </LinearLayout>
    </ScrollView>
    <TextView
        android:id="@+id/newCard_registBtn"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:background="@color/bottom_color"
        android:gravity="center"
        android:text="确认开卡"
        android:textColor="#FFFFFF"
        android:textSize="16sp"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>