cloudroam
2025-03-18 2c0177d2bfc2ed89b2fdffc7ccb84dc685cdf524
fix: 财务统计逻辑
已修改8个文件
已添加5个文件
648 ■■■■ 文件已修改
app/src/main/java/com/example/firstapp/adapter/FinanceAdapter.kt 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/entity/Rule.kt 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/model/FinanceGroup.kt 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/receiver/SmsReceiver.kt 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_phone_login.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/fragment_home.xml 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/item_finance.xml 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/item_finance_group.xml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/item_finance_package_home.xml 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/colors.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/values/themes.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/adapter/FinanceAdapter.kt
对比新文件
@@ -0,0 +1,175 @@
package com.example.firstapp.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.firstapp.R
import com.example.firstapp.databinding.ItemFinanceBinding
import com.example.firstapp.databinding.ItemFinanceGroupBinding
import com.example.firstapp.databinding.ItemFinancePackageHomeBinding
import com.example.firstapp.model.FinanceGroup
import com.example.firstapp.model.FinancePackage
class FinanceAdapter :
    ListAdapter<FinanceGroup, FinanceAdapter.ViewHolder>(FinanceGroupDiffCallback()) {
    private var onPackageClickListener: (FinanceGroup, FinancePackage) -> Unit = { _, _ -> }
    fun setOnPackageClickListener(listener: (FinanceGroup, FinancePackage) -> Unit) {
        onPackageClickListener = listener
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemFinanceGroupBinding.inflate(
            LayoutInflater.from(parent.context), parent, false
        )
        return ViewHolder(binding)
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val group = getItem(position)
        holder.bind(group)
        holder.setOnPackageClickListener(onPackageClickListener)
    }
    inner class ViewHolder(private val binding: ItemFinanceGroupBinding) :
        RecyclerView.ViewHolder(binding.root) {
        private val packagesAdapter = FinancePackageHomeAdapter { pack ->
            currentGroup?.let { group ->
                onPackageClickListener(group, pack)
            }
        }
        private var currentGroup: FinanceGroup? = null
        init {
            binding.rvPackages.apply {
                layoutManager = LinearLayoutManager(context)
                adapter = packagesAdapter
            }
        }
        fun bind(group: FinanceGroup) {
            currentGroup = group
            binding.tvStationName.text = group.stationName
            binding.tvPackageCount.text = "共${group.packages.size}笔账单"
            packagesAdapter.submitList(group.packages)
        }
        fun setOnPackageClickListener(listener: (FinanceGroup, FinancePackage) -> Unit) {
            // 这个方法可以移除,因为我们在构造 ExpressPackageHomeAdapter 时已经处理了点击事件
            // 或者保留这个方法但不做任何操作
        }
    }
}
// 首页使用的包裹适配器 - 简化版本
class FinancePackageHomeAdapter(private val onPackageClick: (FinancePackage) -> Unit) :
    ListAdapter<FinancePackage, FinancePackageHomeAdapter.ViewHolder>(FinancePackageDiffCallback()) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemFinancePackageHomeBinding.inflate(
            LayoutInflater.from(parent.context), parent, false
        )
        return ViewHolder(binding)
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val pack = getItem(position)
        holder.bind(pack)
    }
    inner class ViewHolder(private val binding: ItemFinancePackageHomeBinding) :
        RecyclerView.ViewHolder(binding.root) {
        init {
            binding.root.setOnClickListener {
                val pack = getItem(adapterPosition)
                onPackageClick(pack)
            }
        }
        fun bind(pack: FinancePackage) {
            binding.tvCompany.text = pack.company
            binding.tvCreateTime.text = pack.createTime
            binding.tvTrackingNumber.text = pack.trackingNumber
        }
    }
}
// 取件页面使用的包裹适配器
class FinancePackageAdapter(private val onPackagePickup: (FinancePackage) -> Unit = { _ -> }) :
    ListAdapter<FinancePackage, FinancePackageAdapter.ViewHolder>(FinancePackageDiffCallback()) {
    private var onPackageClickListener: (FinancePackage) -> Unit = {}
    private var stationName: String = ""
    fun setStationInfo(station: String) {
        stationName = station
    }
    fun setOnPackageClickListener(listener: (FinancePackage) -> Unit) {
        onPackageClickListener = listener
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemFinanceBinding.inflate(
            LayoutInflater.from(parent.context), parent, false
        )
        return ViewHolder(binding)
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val pack = getItem(position)
        holder.bind(pack)
    }
    inner class ViewHolder(private val binding: ItemFinanceBinding) :
        RecyclerView.ViewHolder(binding.root) {
        init {
            binding.ivPackageStatus.setOnClickListener {
                val pack = getItem(adapterPosition)
                onPackagePickup(pack)
            }
            binding.root.setOnClickListener(null)
        }
        fun bind(pack: FinancePackage) {
            binding.tvPackageId.text = pack.id.toString()
            binding.tvCompany.text = pack.company
            binding.tvCreateTime.text = pack.createTime
            binding.tvTrackingNumber.text = pack.trackingNumber
            binding.ivPackageStatus.setImageResource(
//                if (pack.isPickedUp) R.drawable.circle_checked
//                else R.drawable.circle
                R.drawable.circle
            )
        }
    }
}
private class FinanceGroupDiffCallback : DiffUtil.ItemCallback<FinanceGroup>() {
    override fun areItemsTheSame(oldItem: FinanceGroup, newItem: FinanceGroup): Boolean {
        return oldItem.stationName == newItem.stationName
    }
    override fun areContentsTheSame(oldItem: FinanceGroup, newItem: FinanceGroup): Boolean {
        return oldItem == newItem
    }
}
private class FinancePackageDiffCallback : DiffUtil.ItemCallback<FinancePackage>() {
    override fun areItemsTheSame(oldItem: FinancePackage, newItem: FinancePackage): Boolean {
        return oldItem.trackingNumber == newItem.trackingNumber
    }
    override fun areContentsTheSame(oldItem: FinancePackage, newItem: FinancePackage): Boolean {
        return oldItem == newItem
    }
}
app/src/main/java/com/example/firstapp/entity/Rule.kt
@@ -1,17 +1,77 @@
package com.example.firstapp.entity
data class Rule(var type: String,var content: String ,var reg: String) {
import java.time.LocalDateTime
    // 在 Rule 类中定义提取方法
    fun extractCodeFromMessage(message: String): String? {
        // 如果 message 包含 content
        if (message.contains(content)) {
            // 使用 reg 作为正则表达式进行匹配
            val regex = reg.toRegex()
            val matchResult = regex.find(message)
            return matchResult?.value  // 如果找到匹配的内容,则返回
        }
        return null  // 如果不匹配,返回 null
class Rule(
    val type: String,
    val content: String,
    val pattern: String
) {
    // 添加伴生对象存储多个正则表达式模式
    companion object {
        private val BANK_PATTERNS = mapOf(
            "招商银行" to listOf(
                // 第一种格式:账单¥xxx,还款日MM月dd日
                "账单[¥¥](\\d+\\.?\\d*).*还款日(\\d{2})月(\\d{2})日",
                // 第二种格式:账单金额xxx,还款日MM月dd日
                "账单金额[::](\\d+\\.?\\d*).*还款日[::](\\d{2})月(\\d{2})日",
                // 可以继续添加其他格式...
            ),
            "中国银行" to listOf(
                "账单金额[::](\\d+\\.?\\d*).*还款日[::](\\d{1,2})日",
                // 可以添加其他格式...
            ),
            // 其他银行的模式...
        )
    }
    fun extractCodeFromMessage(message: String): String? {
        if (type == "财务") {
            // 获取该银行的所有正则表达式模式
            val patterns = BANK_PATTERNS[content] ?: listOf(pattern)
            // 尝试每一个正则表达式
            for (pat in patterns) {
                val regex = pat.toRegex()
                val matchResult = regex.find(message)
                matchResult?.let {
                    if (it.groupValues.size > 1) {
                        return it.groupValues[1].replace("[¥¥]".toRegex(), "")
                    }
                }
            }
            return null
        } else {
            // 非财务类型的处理保持不变
            val regex = pattern.toRegex()
            val matchResult = regex.find(message)
            return matchResult?.value
        }
    }
    fun extractDueDate(message: String): String? {
        if (type != "财务") return null
        val patterns = BANK_PATTERNS[content] ?: listOf(pattern)
        for (pat in patterns) {
            val regex = pat.toRegex()
            val matchResult = regex.find(message)
            matchResult?.let {
                when {
                    content == "招商银行" && it.groupValues.size > 3 -> {
                        return "${it.groupValues[2]}月${it.groupValues[3]}日"
                    }
                    it.groupValues.size > 2 -> {
                        return it.groupValues[2] + "日"
                    }
                    else -> {}
                }
            }
        }
        return null
    }
}
app/src/main/java/com/example/firstapp/model/FinanceGroup.kt
对比新文件
@@ -0,0 +1,13 @@
package com.example.firstapp.model
data class FinanceGroup(
    val stationName: String,
    val packages: List<FinancePackage>
)
data class FinancePackage(
    var id: Long,
    val company: String,
    val trackingNumber: String,
    val createTime: String
)
app/src/main/java/com/example/firstapp/receiver/SmsReceiver.kt
@@ -44,17 +44,19 @@
                    messages[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
                    messageBody.append(messages[i]?.messageBody)
                }
                // 输出短信内容到控制台
                Log.d("SmsReceiver", "Received SMS: ${messageBody.toString()}")
                val msg = Msg(0, "1111", "111111", messageBody.toString(),1, "111", 1, 1)
                val msgId = Core.msg.insert(msg)
                Log.d("SmsReceiver", "Received SMS msgId: ${msgId}")
                // 这里我要写个数组,并创建个对象存放一些内容,如这个对象的属性有匹配内容,正则表达式,并循环遍历
                val ruleList = mutableListOf(
                    Rule("快递","京东","\\d{6}"),
                    Rule("快递","菜鸟驿站","\\d{1,2}-\\d{1,2}-\\d{4}")
                    Rule("快递","菜鸟驿站","\\d{1,2}-\\d{1,2}-\\d{4}"),
                    // 银行规则使用默认正则,实际匹配时会使用 BANK_PATTERNS 中的模式
                    Rule("财务", "中国银行", "账单金额[::](\\d+\\.?\\d*).*还款日[::](\\d{1,2})日"),
                    Rule("财务", "工商银行", "账单金额[::](\\d+\\.?\\d*).*还款日[::](\\d{1,2})日"),
                    Rule("财务", "建设银行", "账单金额[::](\\d+\\.?\\d*).*还款日[::](\\d{1,2})日"),
                    Rule("财务", "信用卡", "账单[¥¥](\\d+\\.?\\d*).*还款日(\\d{2})月(\\d{2})日"),
                    Rule("财务", "花呗", "本月花呗账单(\\d+\\.?\\d*)元.*还款日[期是::](\\d{1,2})[日号]")
                )
                CoroutineScope(Dispatchers.IO).launch {
@@ -74,19 +76,49 @@
                    Log.d("RuleList", ruleList.toString())
                    for (rule in ruleList) {
                        val code = rule.extractCodeFromMessage(messageBody.toString())
                        if (code!==null) {
                            // 转换为 Date 对象
                        val code = if (rule.type == "财务") {
                            // 对信用卡账单使用特殊的提取逻辑
                            val regex = rule.pattern.toRegex()
                            val matchResult = regex.find(messageBody.toString())
                            matchResult?.let {
                                val amount = it.groupValues[1]  // 账单金额
                                amount
                            }
                        } else {
                            rule.extractCodeFromMessage(messageBody.toString())
                        }
                        if (code !== null) {
                            val currentTime = LocalDateTime.now()
                            // 将 LocalDateTime 转换为 Date
                            val date = Date.from(currentTime.atZone(ZoneId.systemDefault()).toInstant())
                            // 如果需要格式化显示
                            val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                            val createtime = sdf.format(date)
                            // 对于信用卡账单,使用还款日作为time字段
                            val time = if (rule.type == "财务") {
                                rule.extractDueDate(messageBody.toString()) ?: createtime
                            } else {
                                createtime
                            }
                            val existingCode = Core.code.queryByTypeAndCodeAndDate(rule.content, code, createtime)
                            if (existingCode == null) {
                                val code = Code(0, rule.type, 1, rule.content, 1, 1, msgId, code, createtime, "中通",0,"","")
                                Core.code.insert(code)
                                val codeEntity = Code(
                                    0,
                                    rule.type,
                                    1,
                                    rule.content,
                                    1,
                                    1,
                                    msgId,
                                    code,
                                    createtime,
                                    rule.content,  // 银行名称作为name
                                    0,
                                    time,  // 还款日期
                                    ""
                                )
                                Core.code.insert(codeEntity)
                                Log.d("SMS_DEBUG", "新短信已保存到数据库")
                                // 发送广播通知数据已更新
app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt
@@ -17,6 +17,7 @@
import com.example.firstapp.R
import com.example.firstapp.activity.PickupActivity
import com.example.firstapp.adapter.ExpressAdapter
import com.example.firstapp.adapter.FinanceAdapter
import com.example.firstapp.core.Core
import com.example.firstapp.databinding.FragmentHomeBinding
@@ -30,7 +31,7 @@
    private lateinit var homeViewModel: HomeViewModel
    private lateinit var expressAdapter: ExpressAdapter
    //    private lateinit var financeAdapter: FinanceAdapter
    private lateinit var financeAdapter: FinanceAdapter
//    private lateinit var memorialAdapter: MemorialAdapter
    private lateinit var dataUpdateReceiver: BroadcastReceiver
@@ -88,12 +89,25 @@
            }
        }
//        // 财务列表
//        binding.financeRecycler.apply {
//            layoutManager = LinearLayoutManager(context)
//            financeAdapter = FinanceAdapter()
//            adapter = financeAdapter
//        }
        // 财务列表
        binding.financeRecycler.apply {
            layoutManager = LinearLayoutManager(context)
            financeAdapter = FinanceAdapter()
            adapter = financeAdapter
            // 设置初始状态 - 添加这行
            binding.financeContent.visibility = View.GONE
            // 设置点击监听
            financeAdapter.setOnPackageClickListener { group, pack ->
                // 跳转到取件页面
                val intent = Intent(requireContext(), PickupActivity::class.java).apply {
                    putExtra("station_name", group.stationName)
                    putExtra("company", pack.company)
                }
                startActivity(intent)
            }
        }
//
//        // 纪念日列表
//        binding.memorialRecycler.apply {
@@ -132,6 +146,9 @@
                tabExpress.textSize = 14f
                tabFinance.textSize = 16f
                others.textSize = 14f
                // 在切换到财务标签时加载数据 - 添加这行
                homeViewModel.loadFinanceData()
            }
            // 其他标签点击事件
@@ -156,9 +173,9 @@
            expressAdapter.submitList(items)
        }
//        homeViewModel.financeItems.observe(viewLifecycleOwner) { items ->
//            financeAdapter.submitList(items)
//        }
        homeViewModel.financeItems.observe(viewLifecycleOwner) { items ->
            financeAdapter.submitList(items)
        }
//
//        homeViewModel.memorialItems.observe(viewLifecycleOwner) { items ->
//            memorialAdapter.submitList(items)
app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt
@@ -8,44 +8,29 @@
import com.example.firstapp.database.entity.Code
import com.example.firstapp.model.ExpressGroup
import com.example.firstapp.model.ExpressPackage
import com.example.firstapp.model.FinanceGroup
import com.example.firstapp.model.FinancePackage
import kotlinx.coroutines.launch
class HomeViewModel : ViewModel() {
//    private val _text = MutableLiveData<String>().apply {
//        value = "短信主页面"
//    }
//    val text: LiveData<String> = _text
//
//    private val _codeList = MutableLiveData<List<Code>>()
//
//    val codeList: LiveData<List<Code>> get() = _codeList
    private val _expressItems = MutableLiveData<List<ExpressGroup>>()
    private val _financeItems = MutableLiveData<List<FinanceGroup>>()
    val expressItems: LiveData<List<ExpressGroup>> = _expressItems
    val financeItems: LiveData<List<FinanceGroup>> = _financeItems
    init {
        // 初始化时加载数据
      //  loadData()
        // 初始化时加载包裹列表数据
        loadExpressData()
        // 初始化时不加载财务列表数据 0317
        //  loadFinanceData()
    }
    // 加载数据的方法
//    fun loadData() {
//        // 获取数据,并更新 LiveData
//        _codeList.value = Core.code.getAllDesc() // 假设这是获取最新的 data 的方法
//    }
//
//    // 如果需要手动更新数据,可以调用这个方法
//    fun updateData() {
//        _codeList.value = Core.code.getAllDesc() // 重新获取并更新数据
//    }
    fun loadExpressData() {
        viewModelScope.launch {
            // 1. 获取所有驿站类型的提醒设置
            val stations = Core.reminder.getByType("驿站")
            // 2. 按驿站分组获取包裹信息
            val groups = stations.map { station ->
                val packages = Core.code.getByKeyword(station.nickname).map { code ->
@@ -57,13 +42,36 @@
                    )
                }
                ExpressGroup(
                    stationName = station.nickname,
                    packages = packages
                    stationName = station.nickname, packages = packages
                )
            }
            _expressItems.postValue(groups)
        }
    }
    fun loadFinanceData() {
        viewModelScope.launch {
            // 1. 获取所有驿站类型的提醒设置
            val stations = Core.reminder.getByType("财务")
            // 2. 按驿站分组获取包裹信息
            val groups = stations.map { station ->
                val packages = Core.code.getByKeyword(station.nickname).map { code ->
                    FinancePackage(
                        id = code.id, //ID
                        company = code.name, //快递公司
                        trackingNumber = code.code, // 取件码
                        createTime = code.createtime  //快递时间
                    )
                }
                FinanceGroup(
                    stationName = station.nickname, packages = packages
                )
            }
            _financeItems.postValue(groups)
        }
    }
}
app/src/main/res/layout/activity_phone_login.xml
@@ -67,7 +67,7 @@
                android:layout_weight="1"
                android:background="@null"
                android:hint="请输入验证码"
                android:text="123456"
                android:text="888888"
                android:inputType="number"
                android:maxLength="6"
                android:textSize="16sp"
app/src/main/res/layout/fragment_home.xml
@@ -106,64 +106,6 @@
                    android:layout_height="wrap_content"
                    android:padding="8dp"/>
                <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:text="花呗"
                        android:textSize="16sp"
                        android:textStyle="bold"
                        android:layout_marginBottom="8dp"/>
                    <TextView
                        android:id="@+id/huabeiAmount"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="230,721 元"
                        android:textSize="24sp"
                        android:textColor="#FF5722"
                        android:layout_marginBottom="4dp"/>
                    <TextView
                        android:id="@+id/huabeiDueDate"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="提醒您2025.01.14 还款"
                        android:textSize="14sp"
                        android:layout_marginBottom="16dp"/>
                    <!-- 信用卡还款 -->
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="中国银行信用卡"
                        android:textSize="16sp"
                        android:textStyle="bold"
                        android:layout_marginBottom="8dp"/>
                    <TextView
                        android:id="@+id/creditCardAmount"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="310,621 元"
                        android:textSize="24sp"
                        android:textColor="#FF5722"
                        android:layout_marginBottom="4dp"/>
                    <TextView
                        android:id="@+id/creditCardDueDate"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="提醒您2025.02.10 还款"
                        android:textSize="14sp"/>
                </LinearLayout>
            </androidx.cardview.widget.CardView>
        </FrameLayout>
app/src/main/res/layout/item_finance.xml
对比新文件
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="12dp"
    android:gravity="center_vertical">
    <ImageView
        android:id="@+id/iv_package_status"
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:src="@drawable/circle"/>
    <TextView
        android:id="@+id/tv_package_id"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:visibility="gone"/>
    <ImageView
        android:id="@+id/iv_company_logo"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginEnd="6dp"/>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_company"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textColor="#333333"
            android:textStyle="bold"/>
        <TextView
            android:id="@+id/tv_create_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textColor="#666666"
            android:layout_marginTop="4dp"/>
    </LinearLayout>
    <TextView
        android:id="@+id/tv_tracking_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:textColor="#333333"
        android:layout_marginStart="12dp"
        android:textStyle="bold"/>
</LinearLayout>
app/src/main/res/layout/item_finance_group.xml
对比新文件
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
    android:layout_marginHorizontal="12dp"
    android:layout_marginVertical="6dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="2dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">
        <!-- 驿站名称和包裹数量 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginBottom="12dp">
            <ImageView
                android:id="@+id/iv_station_icon"
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_gravity="center_vertical"
                android:src="@drawable/location"/>
            <TextView
                android:id="@+id/tv_station_name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginStart="8dp"
                android:textSize="16sp"
                android:textColor="#333333"/>
            <TextView
                android:id="@+id/tv_package_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:textColor="#666666"/>
        </LinearLayout>
        <!-- 包裹列表 -->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_packages"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>
app/src/main/res/layout/item_finance_package_home.xml
对比新文件
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="12dp"
    android:gravity="center_vertical">
    <ImageView
        android:id="@+id/iv_company_logo"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginEnd="6dp"/>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_company"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textColor="#333333"
            android:textStyle="bold"/>
        <TextView
            android:id="@+id/tv_create_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp"
            android:textColor="#666666"
            android:layout_marginTop="4dp"/>
    </LinearLayout>
    <TextView
        android:id="@+id/tv_tracking_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:textColor="#333333"
        android:layout_marginStart="12dp"
        android:textStyle="bold"/>
</LinearLayout>
app/src/main/res/values/colors.xml
@@ -15,4 +15,5 @@
    <color name="gray">#757575</color>
    <color name="light_blue_50">#E1F5FE</color>
    <color name="tab_selected">#FF039BE5</color>
    <color name="light_blue_new">#02A7F0</color>
</resources>
app/src/main/res/values/themes.xml
@@ -3,8 +3,8 @@
    <!--    <style name="Theme.FirstApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">-->
    <style name="Theme.FirstApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorPrimary">@color/light_blue_new</item>
        <item name="colorPrimaryVariant">@color/light_blue_new</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>