| | |
| | | import android.view.View |
| | | import android.view.ViewGroup |
| | | import android.widget.TextView |
| | | import android.widget.Toast |
| | | import androidx.core.content.ContextCompat |
| | | import androidx.fragment.app.Fragment |
| | | import androidx.lifecycle.ViewModelProvider |
| | | import androidx.lifecycle.lifecycleScope |
| | | import androidx.recyclerview.widget.LinearLayoutManager |
| | | import androidx.recyclerview.widget.RecyclerView |
| | | import com.example.firstapp.R |
| | | import com.example.firstapp.activity.PickupActivity |
| | | import com.example.firstapp.activity.VipActivity |
| | | import com.example.firstapp.adapter.ExpressAdapter |
| | | import com.example.firstapp.adapter.FinanceAdapter |
| | | import com.example.firstapp.core.Core |
| | | import com.example.firstapp.adapter.CategorySelectorAdapter |
| | | import com.example.firstapp.adapter.IncomeAdapter |
| | | import com.example.firstapp.database.service.RetrofitClient |
| | | import com.example.firstapp.databinding.FragmentHomeBinding |
| | | import com.example.firstapp.databinding.DialogCategorySelectorBinding |
| | | import com.example.firstapp.model.CategoryConfig |
| | | import com.example.firstapp.utils.PreferencesManager |
| | | import com.google.android.material.bottomsheet.BottomSheetDialog |
| | | import kotlinx.coroutines.launch |
| | | import com.example.firstapp.view.UnderlineTextView |
| | | import com.example.firstapp.activity.ReminderListActivity |
| | | import android.graphics.Color |
| | | import android.view.Gravity |
| | | import android.widget.FrameLayout |
| | | |
| | | class HomeFragment : Fragment() { |
| | | |
| | | private var _binding: FragmentHomeBinding? = null |
| | | |
| | | // This property is only valid between onCreateView and |
| | | // onDestroyView. |
| | | private val binding get() = _binding!! |
| | | |
| | | private lateinit var homeViewModel: HomeViewModel |
| | | private lateinit var expressAdapter: ExpressAdapter |
| | | private lateinit var financeAdapter: FinanceAdapter |
| | | // private lateinit var memorialAdapter: MemorialAdapter |
| | | private lateinit var incomeAdapter: IncomeAdapter |
| | | private lateinit var flightAdapter: FinanceAdapter |
| | | private lateinit var trainAdapter: FinanceAdapter |
| | | private lateinit var dataUpdateReceiver: BroadcastReceiver |
| | | private lateinit var reminderUpdateReceiver: BroadcastReceiver |
| | | private var reminderBadge: TextView? = null |
| | | |
| | | //onCreateView这个方法创建后被调用,通常是初始化视图组件和观察者 |
| | | override fun onCreateView( |
| | |
| | | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| | | super.onViewCreated(view, savedInstanceState) |
| | | |
| | | //通过 ViewModelProvider 获取 HomeViewModel 的实例,以便在视图中使用。 |
| | | homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java) |
| | | val userId = "123456" |
| | | homeViewModel.initialize(requireContext(), userId) |
| | | |
| | | //调用这个方法来设置 RecyclerView用于设置 RecyclerView 的布局和适配器。 |
| | | setupRecyclerViews() |
| | | // 检查是否是首次安装 |
| | | val isFirstInstall = PreferencesManager.isFirstInstall() |
| | | if (isFirstInstall) { |
| | | // 首次安装,设置默认显示快递和还款 |
| | | val defaultCategories = listOf( |
| | | CategoryConfig( |
| | | id = 1, |
| | | name = "快递", |
| | | order = 1, |
| | | isEnabled = true |
| | | ), |
| | | CategoryConfig( |
| | | id = 2, |
| | | name = "还款", |
| | | order = 2, |
| | | isEnabled = true |
| | | ) |
| | | ) |
| | | homeViewModel.saveCategories(defaultCategories) |
| | | // 标记为非首次安装 |
| | | PreferencesManager.setFirstInstall(false) |
| | | } |
| | | |
| | | setupAdapters() |
| | | setupTabSwitching() |
| | | //调用这个方法来观察 ViewModel 中的数据变化 |
| | | observeViewModelData() |
| | | setupObservers() |
| | | setupCategorySelector() |
| | | setupUnreadBadge() |
| | | } |
| | | |
| | | override fun onCreate(savedInstanceState: Bundle?) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 创建提醒更新广播接收器 |
| | | reminderUpdateReceiver = object : BroadcastReceiver() { |
| | | override fun onReceive(context: Context, intent: Intent) { |
| | | if (intent.action == "com.example.firstapp.REMINDER_UPDATED") { |
| | | // 收到提醒更新广播时重新检查未读提醒数量 |
| | | homeViewModel.checkUnreadReminders() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private fun setupRecyclerViews() { |
| | | private fun setupAdapters() { |
| | | binding.expressRecycler.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | expressAdapter = ExpressAdapter() |
| | |
| | | val intent = Intent(requireContext(), PickupActivity::class.java).apply { |
| | | putExtra("station_name", group.stationName) |
| | | putExtra("company", pack.company) |
| | | putExtra("page_type", PickupActivity.TYPE_EXPRESS) |
| | | } |
| | | startActivity(intent) |
| | | } |
| | |
| | | adapter = financeAdapter |
| | | |
| | | // 设置初始状态 - 添加这行 |
| | | binding.financeContent.visibility = View.GONE |
| | | binding.financeRecycler.visibility = View.GONE |
| | | |
| | | // 设置点击监听 |
| | | financeAdapter.setOnPackageClickListener { group, pack -> |
| | |
| | | val intent = Intent(requireContext(), PickupActivity::class.java).apply { |
| | | putExtra("station_name", group.stationName) |
| | | putExtra("company", pack.company) |
| | | putExtra("page_type", PickupActivity.TYPE_REPAYMENT) |
| | | |
| | | } |
| | | startActivity(intent) |
| | | } |
| | | } |
| | | // |
| | | // // 纪念日列表 |
| | | // binding.memorialRecycler.apply { |
| | | // layoutManager = LinearLayoutManager(context) |
| | | // memorialAdapter = MemorialAdapter() |
| | | // adapter = memorialAdapter |
| | | // } |
| | | |
| | | // 添加新的 RecyclerView |
| | | binding.incomeRecycler.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | incomeAdapter = IncomeAdapter() |
| | | adapter = incomeAdapter |
| | | |
| | | // 设置初始状态 - 添加这行 |
| | | binding.incomeRecycler.visibility = View.GONE |
| | | |
| | | // 设置点击监听 |
| | | incomeAdapter.setOnPackageClickListener { group, pack -> |
| | | // 跳转到取件页面 |
| | | val intent = Intent(requireContext(), PickupActivity::class.java).apply { |
| | | putExtra("station_name", group.stationName) |
| | | putExtra("company", pack.company) |
| | | putExtra("page_type", PickupActivity.TYPE_INCOME) |
| | | } |
| | | startActivity(intent) |
| | | } |
| | | } |
| | | |
| | | binding.flightRecycler.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | flightAdapter = FinanceAdapter() |
| | | adapter = flightAdapter |
| | | visibility = View.GONE |
| | | } |
| | | |
| | | binding.trainRecycler.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | trainAdapter = FinanceAdapter() |
| | | adapter = trainAdapter |
| | | visibility = View.GONE |
| | | } |
| | | } |
| | | |
| | | private fun setupTabSwitching() { |
| | |
| | | // 设置初始状态 |
| | | tabExpress.setTextColor(ContextCompat.getColor(requireContext(), R.color.tab_selected)) |
| | | tabFinance.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | others.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | |
| | | |
| | | // 快递标签点击事件 |
| | | tabExpress.setOnClickListener { |
| | | expressContent.visibility = View.VISIBLE |
| | | financeContent.visibility = View.GONE |
| | | tabExpress.setTextColor(ContextCompat.getColor(requireContext(), R.color.tab_selected)) |
| | | tabFinance.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | others.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | tabExpress.textSize = 16f |
| | | tabFinance.textSize = 14f |
| | | others.textSize = 14f |
| | | hideAllRecyclers() |
| | | expressRecycler.visibility = View.VISIBLE |
| | | updateTabStyles(tabExpress) |
| | | homeViewModel.loadExpressData() |
| | | } |
| | | |
| | | // 财务标签点击事件 |
| | | tabFinance.setOnClickListener { |
| | | expressContent.visibility = View.GONE |
| | | financeContent.visibility = View.VISIBLE |
| | | tabExpress.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | tabFinance.setTextColor(ContextCompat.getColor(requireContext(), R.color.tab_selected)) |
| | | others.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | tabExpress.textSize = 14f |
| | | tabFinance.textSize = 16f |
| | | others.textSize = 14f |
| | | |
| | | // 在切换到财务标签时加载数据 - 添加这行 |
| | | // 还款标签点击事件 - 非会员也可以使用 |
| | | tabFinance.setOnClickListener { |
| | | hideAllRecyclers() |
| | | financeRecycler.visibility = View.VISIBLE |
| | | updateTabStyles(tabFinance) |
| | | homeViewModel.loadFinanceData() |
| | | } |
| | | |
| | | // 其他标签点击事件 |
| | | others.setOnClickListener { |
| | | expressContent.visibility = View.GONE |
| | | financeContent.visibility = View.GONE |
| | | tabExpress.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | tabFinance.setTextColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | others.setTextColor(ContextCompat.getColor(requireContext(), R.color.tab_selected)) |
| | | tabExpress.textSize = 14f |
| | | tabFinance.textSize = 14f |
| | | others.textSize = 16f |
| | | // 其他标签点击事件需要检查会员状态 |
| | | val memberOnlyTabs = mapOf( |
| | | tabIncome to { homeViewModel.loadIncomeData() }, |
| | | tabFlight to { homeViewModel.loadFlightData() }, |
| | | tabTrain to { homeViewModel.loadTrainData() } |
| | | ) |
| | | |
| | | memberOnlyTabs.forEach { (tab, loadAction) -> |
| | | tab.setOnClickListener { |
| | | checkMembershipAndExecute(tab) { |
| | | hideAllRecyclers() |
| | | when (tab) { |
| | | tabIncome -> incomeRecycler.visibility = View.VISIBLE |
| | | tabFlight -> flightRecycler.visibility = View.VISIBLE |
| | | tabTrain -> trainRecycler.visibility = View.VISIBLE |
| | | } |
| | | updateTabStyles(tab) |
| | | loadAction() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | //这个方法用于观察 homeViewModel 中的 expressItems 数据。 |
| | | private fun observeViewModelData() { |
| | | private fun checkMembershipAndExecute(tab: TextView, action: () -> Unit) { |
| | | // 从本地获取保存的手机号 |
| | | val savedPhone = PreferencesManager.getPhone() |
| | | if (savedPhone.isNullOrEmpty()) { |
| | | Toast.makeText(requireContext(), "请先登录", Toast.LENGTH_SHORT).show() |
| | | return |
| | | } |
| | | |
| | | // 使用协程检查会员状态 |
| | | lifecycleScope.launch { |
| | | try { |
| | | val response = RetrofitClient.apiService.getUserInfo(savedPhone) |
| | | if (response.code == "0" && response.data != null) { |
| | | if (response.data.isMember) { |
| | | action() |
| | | } else { |
| | | Toast.makeText(requireContext(), "该功能仅对会员开放", Toast.LENGTH_SHORT).show() |
| | | // 切回快递标签 |
| | | binding.tabExpress.performClick() |
| | | } |
| | | } else { |
| | | Toast.makeText(requireContext(), "获取用户信息失败", Toast.LENGTH_SHORT).show() |
| | | binding.tabExpress.performClick() |
| | | } |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | Toast.makeText(requireContext(), "网络错误,请稍后重试", Toast.LENGTH_SHORT).show() |
| | | binding.tabExpress.performClick() |
| | | } |
| | | } |
| | | } |
| | | |
| | | private fun hideAllRecyclers() { |
| | | binding.apply { |
| | | expressRecycler.visibility = View.GONE |
| | | financeRecycler.visibility = View.GONE |
| | | incomeRecycler.visibility = View.GONE |
| | | flightRecycler.visibility = View.GONE |
| | | trainRecycler.visibility = View.GONE |
| | | } |
| | | } |
| | | |
| | | private fun updateTabStyles(selectedTab: UnderlineTextView) { |
| | | binding.apply { |
| | | val tabs = listOf(tabExpress, tabFinance, tabIncome, tabFlight, tabTrain) |
| | | tabs.forEach { tab -> |
| | | // 设置文字颜色为黑色或灰色 |
| | | tab.setTextColor(ContextCompat.getColor(requireContext(), |
| | | if (tab == selectedTab) android.R.color.black else R.color.gray)) |
| | | // 设置文字大小 |
| | | tab.textSize = if (tab == selectedTab) 16f else 14f |
| | | // 设置下划线 |
| | | tab.setUnderlineVisible(tab == selectedTab) |
| | | } |
| | | } |
| | | } |
| | | |
| | | private fun setupObservers() { |
| | | //当 expressItems 数据发生变化时,更新 RecyclerView 的数据。 |
| | | homeViewModel.expressItems.observe(viewLifecycleOwner) { items -> |
| | | //将新的数据列表提交给适配器,以更新 RecyclerView 的显示内容。 |
| | |
| | | homeViewModel.financeItems.observe(viewLifecycleOwner) { items -> |
| | | financeAdapter.submitList(items) |
| | | } |
| | | // |
| | | // homeViewModel.memorialItems.observe(viewLifecycleOwner) { items -> |
| | | // memorialAdapter.submitList(items) |
| | | // } |
| | | |
| | | // 观察收入数据变化 |
| | | homeViewModel.incomeItems.observe(viewLifecycleOwner) { items -> |
| | | incomeAdapter.submitList(items) |
| | | } |
| | | |
| | | homeViewModel.flightItems.observe(viewLifecycleOwner) { items -> |
| | | flightAdapter.submitList(items) |
| | | } |
| | | |
| | | homeViewModel.trainItems.observe(viewLifecycleOwner) { items -> |
| | | trainAdapter.submitList(items) |
| | | } |
| | | |
| | | // 观察未读提醒数量变化 |
| | | homeViewModel.unreadReminderCount.observe(viewLifecycleOwner) { unreadCount -> |
| | | updateReminderBadge(unreadCount) |
| | | } |
| | | |
| | | // 观察可见分类的变化 |
| | | homeViewModel.visibleCategories.observe(viewLifecycleOwner) { categories: List<CategoryConfig> -> |
| | | binding.apply { |
| | | // 隐藏所有标签 |
| | | tabExpress.visibility = View.GONE |
| | | tabFinance.visibility = View.GONE |
| | | tabIncome.visibility = View.GONE |
| | | tabFlight.visibility = View.GONE |
| | | tabTrain.visibility = View.GONE |
| | | |
| | | // 获取用户信息判断是否是会员 |
| | | val savedPhone = PreferencesManager.getPhone() |
| | | lifecycleScope.launch { |
| | | try { |
| | | val response = RetrofitClient.apiService.getUserInfo(savedPhone ?: "") |
| | | val isMember = response.code == "0" && response.data?.isMember == true |
| | | |
| | | if (!isMember) { |
| | | // 非会员只显示快递和还款 |
| | | tabExpress.visibility = View.VISIBLE |
| | | tabFinance.visibility = View.VISIBLE |
| | | if (categories.firstOrNull()?.name == "快递") { |
| | | tabExpress.performClick() |
| | | } else { |
| | | tabFinance.performClick() |
| | | } |
| | | } else { |
| | | // 会员显示所有选中的分类 |
| | | categories.forEach { category -> |
| | | when (category.name) { |
| | | "快递" -> { |
| | | tabExpress.visibility = if (category.isEnabled) View.VISIBLE else View.GONE |
| | | if (categories.indexOf(category) == 0 && category.isEnabled) tabExpress.performClick() |
| | | } |
| | | "还款" -> { |
| | | tabFinance.visibility = if (category.isEnabled) View.VISIBLE else View.GONE |
| | | if (categories.indexOf(category) == 0 && category.isEnabled) tabFinance.performClick() |
| | | } |
| | | "收入" -> { |
| | | tabIncome.visibility = if (category.isEnabled) View.VISIBLE else View.GONE |
| | | if (categories.indexOf(category) == 0 && category.isEnabled) tabIncome.performClick() |
| | | } |
| | | "航班" -> { |
| | | tabFlight.visibility = if (category.isEnabled) View.VISIBLE else View.GONE |
| | | if (categories.indexOf(category) == 0 && category.isEnabled) tabFlight.performClick() |
| | | } |
| | | "火车票" -> { |
| | | tabTrain.visibility = if (category.isEnabled) View.VISIBLE else View.GONE |
| | | if (categories.indexOf(category) == 0 && category.isEnabled) tabTrain.performClick() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | // 发生错误时默认显示快递和还款 |
| | | tabExpress.visibility = View.VISIBLE |
| | | tabFinance.visibility = View.VISIBLE |
| | | tabExpress.performClick() |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | override fun onResume() { |
| | |
| | | IntentFilter("com.example.firstapp.DATA_UPDATED"), |
| | | ContextCompat.RECEIVER_NOT_EXPORTED |
| | | ) |
| | | |
| | | // 注册提醒更新广播接收器 |
| | | ContextCompat.registerReceiver( |
| | | requireContext(), |
| | | reminderUpdateReceiver, |
| | | IntentFilter("com.example.firstapp.REMINDER_UPDATED"), |
| | | ContextCompat.RECEIVER_NOT_EXPORTED |
| | | ) |
| | | |
| | | // 加载数据 |
| | | homeViewModel.loadExpressData() |
| | | // 检查未读提醒数量 |
| | | homeViewModel.checkUnreadReminders() |
| | | } |
| | | |
| | | override fun onPause() { |
| | |
| | | try { |
| | | // 取消注册广播接收器 |
| | | requireContext().unregisterReceiver(dataUpdateReceiver) |
| | | requireContext().unregisterReceiver(reminderUpdateReceiver) |
| | | } catch (e: Exception) { |
| | | // 处理可能的异常 |
| | | e.printStackTrace() |
| | |
| | | super.onDestroyView() |
| | | _binding = null |
| | | } |
| | | |
| | | // private fun loadAdvertisements() { |
| | | // // 使用 Glide 加载网络图片 |
| | | // Glide.with(this) |
| | | // .load("http://192.168.1.235:9999/advertisement/up.png") |
| | | // .into(binding.adBanner) |
| | | // |
| | | // Glide.with(this) |
| | | // .load("http://192.168.1.235:9999/advertisement/down.png") |
| | | // .into(binding.bottomAdBanner) |
| | | // } |
| | | |
| | | // 设置分类选择器 检查会员状态 |
| | | private fun setupCategorySelector() { |
| | | binding.categoryButton.setOnClickListener { |
| | | // 从本地获取保存的手机号 |
| | | val savedPhone = PreferencesManager.getPhone() |
| | | if (savedPhone.isNullOrEmpty()) { |
| | | Toast.makeText(requireContext(), "请先登录", Toast.LENGTH_SHORT).show() |
| | | return@setOnClickListener |
| | | } |
| | | |
| | | // 使用协程检查会员状态 |
| | | lifecycleScope.launch { |
| | | try { |
| | | val response = RetrofitClient.apiService.getUserInfo(savedPhone) |
| | | if (response.code == "0" && response.data != null) { |
| | | if (response.data.isMember) { |
| | | showCategorySelectorDialog() |
| | | } else { |
| | | // 非会员跳转到VIP开通页面 |
| | | val intent = Intent(requireContext(), VipActivity::class.java) |
| | | startActivity(intent) |
| | | } |
| | | } else { |
| | | Toast.makeText(requireContext(), "获取用户信息失败", Toast.LENGTH_SHORT).show() |
| | | } |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | Toast.makeText(requireContext(), "网络错误,请稍后重试", Toast.LENGTH_SHORT).show() |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 添加提醒按钮点击事件 |
| | | binding.reminderButton.setOnClickListener { |
| | | // 跳转到提醒列表页面 |
| | | startActivity(Intent(requireContext(), ReminderListActivity::class.java)) |
| | | // 重新检查未读提醒数量 |
| | | homeViewModel.checkUnreadReminders() |
| | | } |
| | | } |
| | | |
| | | private fun showCategorySelectorDialog() { |
| | | val dialog = BottomSheetDialog(requireContext()) |
| | | val dialogBinding = DialogCategorySelectorBinding.inflate(layoutInflater) |
| | | dialog.setContentView(dialogBinding.root) |
| | | |
| | | val adapter = CategorySelectorAdapter() |
| | | dialogBinding.categoryRecyclerView.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | this.adapter = adapter |
| | | } |
| | | |
| | | // 加载所有分类 |
| | | homeViewModel.categories.observe(viewLifecycleOwner) { categories -> |
| | | // 如果是会员,显示所有分类供选择 |
| | | lifecycleScope.launch { |
| | | try { |
| | | val savedPhone = PreferencesManager.getPhone() |
| | | val response = RetrofitClient.apiService.getUserInfo(savedPhone ?: "") |
| | | val isMember = response.code == "0" && response.data?.isMember == true |
| | | |
| | | if (isMember) { |
| | | // 会员可以看到所有分类 |
| | | adapter.setCategories(categories) |
| | | } else { |
| | | // 非会员只能看到快递和还款 |
| | | val limitedCategories = categories.filter { |
| | | it.name == "快递" || it.name == "还款" |
| | | } |
| | | adapter.setCategories(limitedCategories) |
| | | } |
| | | } catch (e: Exception) { |
| | | // 发生错误时只显示基础分类 |
| | | val limitedCategories = categories.filter { |
| | | it.name == "快递" || it.name == "还款" |
| | | } |
| | | adapter.setCategories(limitedCategories) |
| | | } |
| | | } |
| | | } |
| | | |
| | | dialogBinding.saveButton.setOnClickListener { |
| | | homeViewModel.saveCategories(adapter.getCategories()) |
| | | dialog.dismiss() |
| | | } |
| | | |
| | | dialog.show() |
| | | } |
| | | |
| | | // 添加设置未读提醒徽章的方法 |
| | | private fun setupUnreadBadge() { |
| | | // 直接使用布局中定义的小红点 |
| | | reminderBadge = binding.reminderBadge |
| | | } |
| | | |
| | | // 更新未读提醒徽章 |
| | | private fun updateReminderBadge(unreadCount: Int) { |
| | | reminderBadge?.apply { |
| | | if (unreadCount > 0) { |
| | | text = if (unreadCount > 99) "99+" else unreadCount.toString() |
| | | visibility = View.VISIBLE |
| | | } else { |
| | | visibility = View.GONE |
| | | } |
| | | } |
| | | } |
| | | } |