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.view.ViewGroup
|
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 com.github.mikephil.charting.formatter.ValueFormatter
|
import java.util.*
|
import java.text.SimpleDateFormat
|
import android.util.Log
|
|
class DashboardFragment : Fragment() {
|
|
private var _binding: FragmentDashboardBinding? = null
|
|
// This property is only valid between onCreateView and
|
// 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 {
|
_binding = FragmentDashboardBinding.inflate(inflater, container, false)
|
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
|
|
// 增大图表高度
|
minimumHeight = (resources.displayMetrics.density * 300).toInt()
|
|
// X轴设置
|
xAxis.apply {
|
position = XAxis.XAxisPosition.BOTTOM
|
setDrawGridLines(false)
|
granularity = 1f
|
labelRotationAngle = -45f
|
textSize = 10f
|
}
|
|
// Y轴设置
|
axisLeft.apply {
|
setDrawGridLines(true)
|
axisMinimum = 0f
|
granularity = 1f
|
valueFormatter = object : ValueFormatter() {
|
override fun getFormattedValue(value: Float): String {
|
return value.toInt().toString()
|
}
|
}
|
}
|
axisRight.isEnabled = false
|
|
// 设置图表交互
|
setTouchEnabled(true)
|
isDragEnabled = true
|
setScaleEnabled(true)
|
}
|
|
updateBarChartData()
|
}
|
private fun updateBarChartData() {
|
viewModel.getDailyStats().observe(viewLifecycleOwner) { stats ->
|
// 添加调试日志
|
Log.d("DashboardFragment", "Stats size: ${stats.size}")
|
stats.forEach { stat ->
|
Log.d("DashboardFragment", "Week: ${stat.date}, Count: ${stat.count}, Start: ${stat.week_start}")
|
}
|
|
if (stats.isEmpty()) {
|
Log.d("DashboardFragment", "No data found")
|
return@observe
|
}
|
|
val entries = stats.mapIndexed { index, stat ->
|
BarEntry(index.toFloat(), stat.count.toFloat())
|
}
|
|
val dataSet = BarDataSet(entries, "包裹数量")
|
dataSet.color = resources.getColor(R.color.purple_500)
|
dataSet.valueTextSize = 12f
|
|
val barData = BarData(dataSet)
|
barChart.data = barData
|
|
// 设置X轴标签
|
barChart.xAxis.apply {
|
valueFormatter = object : ValueFormatter() {
|
override fun getFormattedValue(value: Float): String {
|
val position = value.toInt()
|
if (position >= 0 && position < stats.size) {
|
val weekNum = stats[position].date.toIntOrNull() ?: 0
|
// 获取月份信息
|
val monthDay = stats[position].week_start?.let {
|
SimpleDateFormat("MM-dd", Locale.getDefault()).format(
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).parse(it)
|
)
|
} ?: ""
|
return "${monthDay}\n第${weekNum}周"
|
}
|
return ""
|
}
|
}
|
labelCount = stats.size
|
}
|
|
barChart.notifyDataSetChanged()
|
barChart.invalidate()
|
}
|
}
|
private fun setupPieChart() {
|
pieChart.apply {
|
description.isEnabled = false
|
setUsePercentValues(false) // 改为显示实际数量
|
setDrawEntryLabels(false)
|
|
// 增大饼图尺寸
|
setExtraOffsets(20f, 10f, 80f, 10f)
|
minimumHeight = (resources.displayMetrics.density * 400).toInt() // 设置最小高度
|
|
// 配置图例
|
legend.apply {
|
isEnabled = true
|
verticalAlignment = Legend.LegendVerticalAlignment.CENTER
|
horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT
|
orientation = Legend.LegendOrientation.VERTICAL
|
setDrawInside(false)
|
xEntrySpace = 7f
|
yEntrySpace = 0f
|
yOffset = 0f
|
textSize = 12f // 增大图例文字大小
|
}
|
}
|
|
updatePieChartData()
|
}
|
private fun updatePieChartData() {
|
viewModel.getCourierStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
|
val entries = stats.map { stat ->
|
PieEntry(stat.count.toFloat(), "${stat.courierName}(${stat.count})")
|
}
|
|
val dataSet = PieDataSet(entries, "快递公司分布")
|
dataSet.colors = listOf(
|
resources.getColor(R.color.purple_500),
|
resources.getColor(R.color.teal_200),
|
resources.getColor(R.color.purple_200),
|
resources.getColor(R.color.teal_700)
|
)
|
dataSet.valueTextSize = 14f // 增大数值文字大小
|
|
val pieData = PieData(dataSet)
|
pieData.setValueFormatter(object : ValueFormatter() {
|
override fun getFormattedValue(value: Float): String {
|
return value.toInt().toString()
|
}
|
})
|
|
pieChart.data = pieData
|
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
|
}
|
}
|