| | |
| | | package com.example.firstapp.ui.dashboard |
| | | |
| | | import com.example.firstapp.R |
| | | import android.os.Bundle |
| | | import android.view.LayoutInflater |
| | | import android.view.View |
| | |
| | | import android.widget.TextView |
| | | import androidx.fragment.app.Fragment |
| | | import androidx.lifecycle.ViewModelProvider |
| | | import androidx.fragment.app.viewModels |
| | | import com.example.firstapp.databinding.FragmentDashboardBinding |
| | | import com.google.android.material.tabs.TabLayout |
| | | import androidx.recyclerview.widget.LinearLayoutManager |
| | | import com.example.firstapp.adapter.PackageAdapter |
| | | import com.example.firstapp.core.Core |
| | | import com.github.mikephil.charting.charts.BarChart |
| | | import com.github.mikephil.charting.charts.PieChart |
| | | import com.github.mikephil.charting.components.Legend |
| | | import com.github.mikephil.charting.components.XAxis |
| | | import com.github.mikephil.charting.data.* |
| | | import com.github.mikephil.charting.formatter.IndexAxisValueFormatter |
| | | import java.util.* |
| | | import java.text.SimpleDateFormat |
| | | |
| | | class DashboardFragment : Fragment() { |
| | | |
| | |
| | | // onDestroyView. |
| | | private val binding get() = _binding!! |
| | | |
| | | private val packageAdapter = PackageAdapter() |
| | | private var currentDate = Calendar.getInstance() |
| | | private var currentDateType = DateType.DAY |
| | | private lateinit var barChart: BarChart |
| | | private lateinit var pieChart: PieChart |
| | | enum class DateType { |
| | | DAY, WEEK, MONTH, YEAR |
| | | } |
| | | private val viewModel: DashboardViewModel by viewModels() |
| | | |
| | | override fun onCreateView( |
| | | inflater: LayoutInflater, |
| | | container: ViewGroup?, |
| | | savedInstanceState: Bundle? |
| | | ): View { |
| | | val dashboardViewModel = |
| | | ViewModelProvider(this).get(DashboardViewModel::class.java) |
| | | |
| | | _binding = FragmentDashboardBinding.inflate(inflater, container, false) |
| | | val root: View = binding.root |
| | | |
| | | val textView: TextView = binding.textDashboard |
| | | dashboardViewModel.text.observe(viewLifecycleOwner) { |
| | | textView.text = it |
| | | } |
| | | return root |
| | | return binding.root |
| | | } |
| | | |
| | | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| | | super.onViewCreated(view, savedInstanceState) |
| | | |
| | | setupRecyclerView() |
| | | setupTabLayout() |
| | | setupDatePicker() |
| | | updateDateDisplay() |
| | | setupWeekView(view) |
| | | loadPackages() |
| | | } |
| | | |
| | | private fun setupRecyclerView() { |
| | | binding.recyclerPackages.apply { |
| | | layoutManager = LinearLayoutManager(context) |
| | | adapter = packageAdapter |
| | | } |
| | | } |
| | | |
| | | private fun setupTabLayout() { |
| | | binding.tabDateRange.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { |
| | | override fun onTabSelected(tab: TabLayout.Tab?) { |
| | | currentDateType = when(tab?.position) { |
| | | 0 -> DateType.DAY |
| | | 1 -> DateType.WEEK |
| | | 2 -> DateType.MONTH |
| | | 3 -> DateType.YEAR |
| | | else -> DateType.DAY |
| | | } |
| | | // 切换视图 |
| | | binding.viewFlipperStats.displayedChild = when(currentDateType) { |
| | | DateType.DAY -> 0 |
| | | DateType.WEEK -> 1 |
| | | else -> 0 |
| | | } |
| | | updateDateDisplay() |
| | | //加载按天统计包裹数量和列表 |
| | | loadPackages() |
| | | observePackages() |
| | | } |
| | | override fun onTabUnselected(tab: TabLayout.Tab?) {} |
| | | override fun onTabReselected(tab: TabLayout.Tab?) {} |
| | | }) |
| | | } |
| | | |
| | | private fun setupDatePicker() { |
| | | binding.btnPreviousDate.setOnClickListener { |
| | | adjustDate(-1) |
| | | } |
| | | binding.btnNextDate.setOnClickListener { |
| | | adjustDate(1) |
| | | } |
| | | } |
| | | |
| | | private fun adjustDate(amount: Int) { |
| | | when (currentDateType) { |
| | | DateType.DAY -> currentDate.add(Calendar.DAY_OF_MONTH, amount) |
| | | DateType.WEEK -> currentDate.add(Calendar.WEEK_OF_YEAR, amount) |
| | | DateType.MONTH -> currentDate.add(Calendar.MONTH, amount) |
| | | DateType.YEAR -> currentDate.add(Calendar.YEAR, amount) |
| | | } |
| | | updateDateDisplay() |
| | | loadPackages() |
| | | } |
| | | |
| | | private fun updateDateDisplay() { |
| | | val dateFormat = when (currentDateType) { |
| | | DateType.DAY -> "yyyy年MM月dd日" |
| | | DateType.WEEK -> "yyyy年第ww周" |
| | | DateType.MONTH -> "yyyy年MM月" |
| | | DateType.YEAR -> "yyyy年" |
| | | } |
| | | binding.textCurrentDate.text = SimpleDateFormat(dateFormat, Locale.getDefault()) |
| | | .format(currentDate.time) |
| | | } |
| | | private fun setupWeekView(view: View) { |
| | | val weekStatsView = binding.layoutWeekStats.root |
| | | barChart = weekStatsView.findViewById(R.id.chart_daily_packages) |
| | | pieChart = weekStatsView.findViewById(R.id.chart_courier_distribution) |
| | | setupBarChart() |
| | | setupPieChart() |
| | | } |
| | | private fun setupBarChart() { |
| | | // 配置柱状图 |
| | | barChart.apply { |
| | | description.isEnabled = false |
| | | setDrawGridBackground(false) |
| | | legend.isEnabled = false |
| | | |
| | | // X轴设置 |
| | | xAxis.apply { |
| | | position = XAxis.XAxisPosition.BOTTOM |
| | | setDrawGridLines(false) |
| | | valueFormatter = IndexAxisValueFormatter(getDayLabels()) |
| | | } |
| | | |
| | | // Y轴设置 |
| | | axisLeft.apply { |
| | | setDrawGridLines(true) |
| | | axisMinimum = 0f |
| | | } |
| | | axisRight.isEnabled = false |
| | | } |
| | | |
| | | updateBarChartData() |
| | | } |
| | | private fun updateBarChartData() { |
| | | viewModel.getDailyStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats -> |
| | | val entries = stats.mapIndexed { index, stat -> |
| | | BarEntry(index.toFloat(), stat.count.toFloat()) |
| | | } |
| | | |
| | | val dataSet = BarDataSet(entries, "包裹数量") |
| | | dataSet.color = resources.getColor(R.color.purple_500) |
| | | |
| | | barChart.data = BarData(dataSet) |
| | | barChart.invalidate() |
| | | } |
| | | } |
| | | private fun setupPieChart() { |
| | | // 配置饼图 |
| | | pieChart.apply { |
| | | description.isEnabled = false |
| | | setUsePercentValues(true) |
| | | setDrawEntryLabels(false) |
| | | |
| | | legend.isEnabled = true |
| | | legend.verticalAlignment = Legend.LegendVerticalAlignment.CENTER |
| | | legend.horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT |
| | | legend.orientation = Legend.LegendOrientation.VERTICAL |
| | | } |
| | | |
| | | updatePieChartData() |
| | | } |
| | | private fun updatePieChartData() { |
| | | viewModel.getCourierStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats -> |
| | | val entries = stats.map { stat -> |
| | | PieEntry(stat.count.toFloat(), stat.courierName) |
| | | } |
| | | |
| | | val dataSet = PieDataSet(entries, "快递公司分布") |
| | | dataSet.colors = listOf( |
| | | resources.getColor(R.color.purple_500), |
| | | resources.getColor(R.color.teal_200) |
| | | ) |
| | | |
| | | pieChart.data = PieData(dataSet) |
| | | pieChart.invalidate() |
| | | } |
| | | } |
| | | private fun getDayLabels(): Array<String> { |
| | | return arrayOf("周一", "周二", "周三", "周四", "周五", "周六", "周日") |
| | | } |
| | | |
| | | private fun loadPackages() { |
| | | // 这里应该从数据库或网络加载数据 |
| | | // 根据当前选择的日期类型传入对应参数 |
| | | // val packages = when (currentDateType) { |
| | | // DateType.DAY -> Core.code.getPackagesByDay(currentDate.timeInMillis) |
| | | // DateType.WEEK -> Core.code.getPackagesByWeek(currentDate.timeInMillis) |
| | | // DateType.MONTH -> Core.code.getPackagesByMonth(currentDate.timeInMillis) |
| | | // DateType.YEAR -> Core.code.getPackagesByYear(currentDate.timeInMillis) |
| | | // } |
| | | val packages =Core.code.getPackagesByDay(currentDate.timeInMillis) |
| | | packageAdapter.updatePackages(packages) |
| | | binding.textPackageCount.text = "${packageAdapter.itemCount}个" |
| | | } |
| | | private fun observePackages() { |
| | | viewModel.getPackages( |
| | | currentDate.timeInMillis, |
| | | currentDateType.name |
| | | ).observe(viewLifecycleOwner) { packages -> |
| | | when (currentDateType) { |
| | | DateType.WEEK -> { |
| | | // 更新图表数据 |
| | | updateBarChartData() |
| | | updatePieChartData() |
| | | } |
| | | else -> { |
| | | packageAdapter.updatePackages(packages) |
| | | } |
| | | } |
| | | binding.textPackageCount.text = "${packages.size}个" |
| | | } |
| | | } |
| | | override fun onDestroyView() { |
| | | super.onDestroyView() |
| | | _binding = null |