From acb5be78c07b8499d0a38515b05a4982207c1c9a Mon Sep 17 00:00:00 2001
From: zhujie <leon.zhu@cloudroam.com.cn>
Date: 星期五, 18 四月 2025 15:24:16 +0800
Subject: [PATCH] Merge branch 'master' of http://47.96.225.205:8888/r/FirstApp2
---
app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt | 1375 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 1,310 insertions(+), 65 deletions(-)
diff --git a/app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt b/app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt
index f0e308a..5aa4f28 100644
--- a/app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt
+++ b/app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt
@@ -1,45 +1,65 @@
package com.example.firstapp.ui.dashboard
-import com.example.firstapp.R
+import android.graphics.Color
import android.os.Bundle
+import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.webkit.WebView
+import android.widget.GridLayout
+import android.widget.HorizontalScrollView
+import android.widget.LinearLayout
import android.widget.TextView
+import android.widget.Toast
+import androidx.cardview.widget.CardView
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.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
+import com.example.firstapp.R
import com.example.firstapp.adapter.PackageAdapter
-import com.example.firstapp.core.Core
+import com.example.firstapp.database.response.UserInfo
+import com.example.firstapp.database.service.RetrofitClient
+import com.example.firstapp.databinding.FragmentDashboardBinding
+import com.example.firstapp.model.DailyStat
+import com.example.firstapp.utils.PreferencesManager
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 com.github.mikephil.charting.formatter.ValueFormatter
+import com.google.android.material.tabs.TabLayout
+import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
+import java.util.*
+
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
+ private lateinit var chartCourierDistriBution:CardView
+ private lateinit var heatmapView: View
+ private var currentUserInfo: UserInfo? = null // 确保使用你的实际数据类
+
+ private var startDateCur:String = ""
+ private var endDateCur:String = ""
+ private lateinit var bar_title:TextView
+ private lateinit var pie_title:TextView
+
+
enum class DateType {
DAY, WEEK, MONTH, YEAR
}
private val viewModel: DashboardViewModel by viewModels()
+
override fun onCreateView(
inflater: LayoutInflater,
@@ -50,16 +70,57 @@
return binding.root
}
+ override fun onResume() {
+ super.onResume()
+ // 重新加载用户信息
+ loadUserInfo()
+ }
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+// val webView: WebView = binding.layoutWeekStats.webView
+// val webSettings = webView.settings
+// webSettings.javaScriptEnabled = true // 启用 JavaScript
+//
+//
+// // 加载本地的 HTML 文件
+// webView.loadUrl("file:///android_asset/calendar-heatmap.html")
+
+ //渲染包裹列表
setupRecyclerView()
+ //初始化tab内容和数据
setupTabLayout()
+ //日期调整
setupDatePicker()
+ setupView(view)
updateDateDisplay()
- setupWeekView(view)
loadPackages()
+
+ // 遮罩层
+ loadUserInfo()
+
+ // 遮罩层点击时间
+ binding.overlayContent.setOnClickListener {
+ // 跳转到vipActivity
+ val intent = android.content.Intent(requireContext(), com.example.firstapp.activity.VipActivity::class.java)
+ startActivity(intent)
+ }
}
+
+ private fun showOverlay() {
+ binding.viewOverlay.visibility = View.VISIBLE
+ binding.overlayContent.visibility = View.VISIBLE
+
+ }
+
+ private fun hiddleOverlay() {
+ binding.viewOverlay.visibility = View.GONE
+ binding.overlayContent.visibility = View.GONE
+
+
+ }
+
private fun setupRecyclerView() {
binding.recyclerPackages.apply {
@@ -69,8 +130,14 @@
}
private fun setupTabLayout() {
+ val weekStatsView = binding.layoutWeekStats.root
+ bar_title = weekStatsView.findViewById(R.id.bar_title)
+ pie_title = weekStatsView.findViewById(R.id.pie_title)
+
binding.tabDateRange.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
+ currentDate = Calendar.getInstance()
+
currentDateType = when(tab?.position) {
0 -> DateType.DAY
1 -> DateType.WEEK
@@ -78,16 +145,43 @@
3 -> DateType.YEAR
else -> DateType.DAY
}
- // 切换视图
- binding.viewFlipperStats.displayedChild = when(currentDateType) {
- DateType.DAY -> 0
- DateType.WEEK -> 1
- else -> 0
+
+ when (currentDateType) {
+ DateType.DAY -> {
+ binding.cardPackageStatsTitleText.text = "本日收到包裹总数"
+ binding.layoutYearStatsTitleText.text = "包裹取件码记录"
+
+ binding.cardPackageStatsTitleText.visibility = View.VISIBLE
+ binding.layoutYearStatsTitleText.visibility = View.VISIBLE
+ }
+ DateType.WEEK -> {
+ binding.cardPackageStatsTitleText.text = "本周收到包裹总数"
+ bar_title.text = "本周收到包裹数分布 ->"
+ pie_title.text = "本周包裹物流公司分布 ->"
+ binding.cardPackageStatsTitleText.visibility = View.VISIBLE
+ binding.layoutYearStatsTitleText.visibility = View.GONE
+
+ }
+ DateType.MONTH -> {
+ binding.cardPackageStatsTitleText.text = "本月收到包裹总数"
+ bar_title.text = "本月收到包裹数分布 ->"
+ pie_title.text = "本月包裹物流公司分布 ->"
+ binding.cardPackageStatsTitleText.visibility = View.VISIBLE
+ binding.layoutYearStatsTitleText.visibility = View.GONE
+ }
+ DateType.YEAR -> {
+ bar_title.text = "本年收到包裹数分布 ->"
+ pie_title.text = "本年包裹物流公司分布 ->"
+ binding.cardPackageStatsTitleText.visibility = View.GONE
+ binding.layoutYearStatsTitleText.visibility = View.GONE
+ }
}
+
+
+
updateDateDisplay()
- //加载按天统计包裹数量和列表
+ updateCharts()
loadPackages()
- observePackages()
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
@@ -111,131 +205,1282 @@
DateType.YEAR -> currentDate.add(Calendar.YEAR, amount)
}
updateDateDisplay()
+ updateCharts()
loadPackages()
}
private fun updateDateDisplay() {
val dateFormat = when (currentDateType) {
+ DateType.DAY -> {
+ // 获取当天的起始和结束时间
+ val calendar = currentDate.clone() as Calendar
+ // 设置为当天的 00:00:00
+ calendar.set(Calendar.HOUR_OF_DAY, 0)
+ calendar.set(Calendar.MINUTE, 0)
+ calendar.set(Calendar.SECOND, 0)
+ calendar.set(Calendar.MILLISECOND, 0)
+ startDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ // 设置为当天的 23:59:59
+ calendar.set(Calendar.HOUR_OF_DAY, 23)
+ calendar.set(Calendar.MINUTE, 59)
+ calendar.set(Calendar.SECOND, 59)
+ calendar.set(Calendar.MILLISECOND, 999)
+ endDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ // 返回当天的日期格式
+ SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault()).format(currentDate.time)
+ }
+ DateType.WEEK -> {
+ // 获取本周的起始和结束日期
+ val calendar = currentDate.clone() as Calendar
+ calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
+ val startDate = SimpleDateFormat("MM月dd日", Locale.getDefault()).format(calendar.time)
+ startDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ calendar.add(Calendar.DAY_OF_WEEK, 6)
+ val endDate = SimpleDateFormat("MM月dd日", Locale.getDefault()).format(calendar.time)
+ endDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ "$startDate-$endDate"
+ }
+ DateType.MONTH -> {
+ // 获取本月的起始和结束日期
+ val calendar = currentDate.clone() as Calendar
+ calendar.set(Calendar.DAY_OF_MONTH, 1)
+ startDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ calendar.add(Calendar.MONTH, 1)
+ calendar.set(Calendar.DAY_OF_MONTH, 0)
+ endDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ "yyyy年MM月"
+ }
+ DateType.YEAR -> {
+ // 获取当前年的起始和结束日期
+ val calendar = currentDate.clone() as Calendar
+
+ // 设置为当前年份的 1 月 1 日
+ calendar.set(Calendar.MONTH, Calendar.JANUARY)
+ calendar.set(Calendar.DAY_OF_MONTH, 1)
+ startDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ // 设置为当前年份的 12 月 31 日
+ calendar.set(Calendar.MONTH, Calendar.DECEMBER)
+ calendar.set(Calendar.DAY_OF_MONTH, 31)
+ endDateCur = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+
+ "yyyy年"
+ }
+ }
+
+ // 更新界面显示
+ if (currentDateType == DateType.WEEK) {
+ binding.textCurrentDate.text = dateFormat
+ } else {
+ binding.textCurrentDate.text = SimpleDateFormat(dateFormat, Locale.getDefault())
+ .format(currentDate.time)
+ }
+ }
+
+ private fun updateDateDisplay_bak() {
+ val dateFormat = when (currentDateType) {
DateType.DAY -> "yyyy年MM月dd日"
- DateType.WEEK -> "yyyy年第ww周"
+ DateType.WEEK -> {
+ // 获取本周的起始和结束日期
+ val calendar = currentDate.clone() as Calendar
+ calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
+ val startDate = SimpleDateFormat("MM月dd日", Locale.getDefault()).format(calendar.time)
+ startDateCur=SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+ calendar.add(Calendar.DAY_OF_WEEK, 6)
+ val endDate = SimpleDateFormat("MM月dd日", Locale.getDefault()).format(calendar.time)
+ endDateCur=SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(calendar.time)
+
+
+ "$startDate-$endDate"
+ }
DateType.MONTH -> "yyyy年MM月"
DateType.YEAR -> "yyyy年"
}
- binding.textCurrentDate.text = SimpleDateFormat(dateFormat, Locale.getDefault())
- .format(currentDate.time)
+
+ if (currentDateType == DateType.WEEK) {
+ binding.textCurrentDate.text = dateFormat
+ } else {
+ binding.textCurrentDate.text = SimpleDateFormat(dateFormat, Locale.getDefault())
+ .format(currentDate.time)
+ }
}
- private fun setupWeekView(view: View) {
+ private fun setupView(view: View) {
+
val weekStatsView = binding.layoutWeekStats.root
barChart = weekStatsView.findViewById(R.id.chart_daily_packages)
+ chartCourierDistriBution=weekStatsView.findViewById(R.id.chart_courier_card_view)
pieChart = weekStatsView.findViewById(R.id.chart_courier_distribution)
+ heatmapView = weekStatsView.findViewById(R.id.heatmap_yearly)
+
+ barChart.setViewPortOffsets(100f, 100f, 100f, 200f)
+
+// barChart.invalidate()
+
+ // 初始化时隐藏统计视图
+ weekStatsView.visibility = View.GONE
+
setupBarChart()
setupPieChart()
+ setupHeatmap()
+ updateCharts()
+
}
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)
- valueFormatter = IndexAxisValueFormatter(getDayLabels())
+ granularity = 1f
+ labelRotationAngle = 0f
+ textSize = 10f //标签字体
+ setExtraLeftOffset(5f) // 减少左侧留白
+ setExtraBottomOffset(15f)
}
// Y轴设置
axisLeft.apply {
setDrawGridLines(true)
axisMinimum = 0f
+ granularity = 1f
+ valueFormatter = object : ValueFormatter() {
+ override fun getFormattedValue(value: Float): String {
+ return if (value > 0) value.toInt().toString() else ""
+ }
+ }
}
axisRight.isEnabled = false
+
+ // 设置图表交互
+ setTouchEnabled(true)
+ isDragEnabled = true
+ setScaleEnabled(true)
+
+ // 设置边距
+ setExtraOffsets(10f, 10f, 10f, 20f)
}
+
+
updateBarChartData()
}
private fun updateBarChartData() {
- viewModel.getDailyStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ val statsFlow = when (currentDateType) {
+ DateType.WEEK -> {
+// viewModel.getWeeklyStats(currentDate.timeInMillis, 6)
+ viewModel.getWeeklyStatsChart(startDateCur,endDateCur)
+ }
+ DateType.MONTH -> {
+ viewModel.getYearMonthlyStats(currentDate.timeInMillis)
+ }
+ else -> return
+ }
+
+ statsFlow.observe(viewLifecycleOwner) { stats ->
+ if (stats.isEmpty()) return@observe
+
val entries = stats.mapIndexed { index, stat ->
- BarEntry(index.toFloat(), stat.count.toFloat())
+ val entry = BarEntry(index.toFloat(), stat.count.toFloat())
+ if (stat.count == 0) {
+ entry.data = "hide_label"
+ }
+ entry
}
val dataSet = BarDataSet(entries, "包裹数量")
- dataSet.color = resources.getColor(R.color.purple_500)
+ dataSet.apply {
+ color = resources.getColor(R.color.purple_500)
+ valueTextSize = 12f
+ valueFormatter = object : ValueFormatter() {
+ override fun getFormattedValue(value: Float): String {
+ return if (value > 0) value.toInt().toString() else ""
+ }
+ }
+ }
- barChart.data = BarData(dataSet)
+ 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) {
+ return when(currentDateType) {
+ DateType.WEEK -> {
+ val weekStat = stats[position]
+ try {
+ // 解析日期字符串
+ val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+ val date = sdf.parse(weekStat.date)
+ val calendar = Calendar.getInstance()
+ calendar.time = date
+
+ // 获取年份和周数
+ val weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR)
+ val year = calendar.get(Calendar.YEAR)
+
+ // 显示格式:第X周
+// "第${weekOfYear}周"
+ "${weekOfYear}"
+ } catch (e: Exception) {
+ weekStat.date
+ }
+ }
+// DateType.MONTH -> "${stats[position].date}月"
+ DateType.MONTH -> {
+ stats[position].date.replaceFirst("^0+".toRegex(), "")
+ }
+ else -> ""
+ }
+ }
+ return ""
+ }
+ }
+ labelCount = stats.size
+ setAvoidFirstLastClipping(true)
+ labelRotationAngle = 0f
+
+ // 增加标签间距
+// setExtraBottomOffset(20f)
+ textSize = 11f // 稍微调小字体
+ }
+
+ // 高亮显示
+ if (currentDateType == DateType.MONTH) {
+ val currentMonth = currentDate.get(Calendar.MONTH)
+ dataSet.setColors(List(stats.size) { index ->
+ if (index == currentMonth) resources.getColor(R.color.purple_500)
+ else resources.getColor(R.color.purple_200)
+ })
+ } else if (currentDateType == DateType.WEEK) {
+ val highlightIndex = 3 // 当前周在第4个位置
+ dataSet.setColors(List(stats.size) { index ->
+ if (index == highlightIndex) resources.getColor(R.color.purple_500)
+ else resources.getColor(R.color.purple_200)
+ })
+ }
+
+ // 刷新图表
+ barChart.notifyDataSetChanged()
barChart.invalidate()
}
}
private fun setupPieChart() {
- // 配置饼图
pieChart.apply {
+ // 隐藏图表描述(右下角默认文字)
description.isEnabled = false
- setUsePercentValues(true)
+ // 显示实际值而非百分比
+ setUsePercentValues(false)
+ // 隐藏饼图区块上的标签(如数值或名称)
setDrawEntryLabels(false)
- legend.isEnabled = true
- legend.verticalAlignment = Legend.LegendVerticalAlignment.CENTER
- legend.horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT
- legend.orientation = Legend.LegendOrientation.VERTICAL
+ // 设置饼图与容器的边距,参数顺序:左、上、右、下
+ // 右侧留出 80f 空间,可能为图例腾出位置
+ setExtraOffsets(20f, 20f, 20f, 20f)
+
+
+
+ // 配置图例
+ legend.apply {
+ isEnabled = true // 启用图例
+ verticalAlignment = Legend.LegendVerticalAlignment.CENTER // 垂直居中
+ horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT // 水平靠右对齐
+ orientation = Legend.LegendOrientation.VERTICAL // 图例项垂直排列
+ setDrawInside(false) // 图例绘制在图表外部(而非覆盖在图上)
+ xEntrySpace = 10f // 图例项水平间距
+ yEntrySpace = 5f // 图例项垂直间距
+ yOffset = 0f // 图例整体 Y 轴无偏移
+ textSize = 12f // 图例文字大小
+ }
+
+ // 调整中心空白区域大小
+ holeRadius = 20f // 中间空心圆的半径(占饼图比例)
+ transparentCircleRadius = 25f // 透明圆圈的半径(可能用于边框效果)
+
}
updatePieChartData()
}
private fun updatePieChartData() {
- viewModel.getCourierStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ viewModel.getCourierStats(
+ currentDate.timeInMillis,
+ currentDateType.name
+ ).observe(viewLifecycleOwner) { stats ->
val entries = stats.map { stat ->
- PieEntry(stat.count.toFloat(), stat.courierName)
+ 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)
- )
+ if (entries.isNotEmpty()) {
+ val dataSet = PieDataSet(entries, "快递公司分布")
+ dataSet.colors = listOf(
+ resources.getColor(R.color.light_blue_600_1),
+ resources.getColor(R.color.sunflower),
+ resources.getColor(R.color.light_blue),
+ resources.getColor(R.color.vermillion),
+ resources.getColor(R.color.fish_belly_white),
+ resources.getColor(R.color.light_green),
+ resources.getColor(R.color.crimson),
+ resources.getColor(R.color.sky_blue),
+ resources.getColor(R.color.gold),
+ resources.getColor(R.color.light_purple),
+ resources.getColor(R.color.yellow),
+ resources.getColor(R.color.canary_yellow),
+ resources.getColor(R.color.red_purple),
+ resources.getColor(R.color.light_cyan),
+ resources.getColor(R.color.orange),
+ resources.getColor(R.color.magenta),
+ resources.getColor(R.color.light_purple_2),
+ resources.getColor(R.color.bright_yellow),
+ resources.getColor(R.color.emerald_green),
+ resources.getColor(R.color.turmeric),
+ resources.getColor(R.color.red_gold),
+ resources.getColor(R.color.off_white),
+ resources.getColor(R.color.tangerine),
+ resources.getColor(R.color.aqua_blue),
+ resources.getColor(R.color.frost),
+ resources.getColor(R.color.wisteria),
+ resources.getColor(R.color.cyan)
+ )
+ dataSet.valueTextSize = 14f // 增大数值文字大小
- pieChart.data = PieData(dataSet)
- pieChart.invalidate()
+ val pieData = PieData(dataSet)
+ pieData.setValueFormatter(object : ValueFormatter() {
+ override fun getFormattedValue(value: Float): String {
+ return value.toInt().toString()
+ }
+ })
+
+ pieChart.data = pieData
+ pieChart.invalidate()
+
+ pieChart.visibility = View.VISIBLE // 例如:隐藏 PieChart
+
+ pie_title.visibility = View.VISIBLE
+
+ chartCourierDistriBution.visibility =View.VISIBLE
+
+ } else {
+ // 如果 entries 为空,可以选择隐藏图表或设置一个默认显示
+ pieChart.visibility = View.GONE // 例如:隐藏 PieChart
+
+ pie_title.visibility = View.GONE
+
+ chartCourierDistriBution.visibility =View.GONE
+
+ }
+
+
+// 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 loadPackages(){
+
+
+
+// 根据日、周、月、年 获取统计数字
+ when (currentDateType) {
+ DateType.DAY -> {
+
+ viewModel.getCurrentDayStatsByType(startDateCur,endDateCur,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+
+ // 获取取件记录
+ viewModel.getPackagesReaded(currentDate.timeInMillis,
+ currentDateType.name)
+ .observe(viewLifecycleOwner) { unpackages->
+ // 只读取未取件的包裹
+ packageAdapter.updatePackages(unpackages)
+ }
+
+
+ }
+ DateType.WEEK -> {
+
+ viewModel.getCurrentDayStatsByType(startDateCur,endDateCur,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+ }
+ DateType.MONTH -> {
+
+ viewModel.getCurrentDayStatsByType(startDateCur,endDateCur,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+ }
+ DateType.YEAR -> {
+
+ viewModel.getCurrentDayStatsByType(startDateCur,endDateCur,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.layoutYearStats.textTotalPackages.text = "${stats}个"
+ }
+ }
+ }
}
- private fun observePackages() {
+
+ private fun loadPackages_bak2(){
+
+ val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+
+// 根据日、周、月、年 获取统计数字
+ when (currentDateType) {
+ DateType.DAY -> {
+ val today = Calendar.getInstance()
+ val tmpCurDateStart = formatter.format(currentDate.time)
+ val tmpCurDateEnd = formatter.format(currentDate.time)
+ viewModel.getCurrentDayStatsByType(tmpCurDateStart,tmpCurDateEnd,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+
+ // 获取本周统计
+ viewModel.getPackagesReaded(currentDate.timeInMillis,
+ currentDateType.name)
+ .observe(viewLifecycleOwner) { unpackages->
+ // 只读取未取件的包裹
+ packageAdapter.updatePackages(unpackages)
+ }
+
+
+ }
+ DateType.WEEK -> {
+ val today = Calendar.getInstance()
+
+ // 获取本周的周一(第一天)
+ today.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
+ val firstDayOfWeek = formatter.format(today.time)
+ // 获取本周的周日(最后一天)
+ today.add(Calendar.DATE, 6) // 加6天
+ val lastDayOfWeek = formatter.format(today.time)
+ viewModel.getCurrentDayStatsByType(firstDayOfWeek,lastDayOfWeek,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+ }
+ DateType.MONTH -> {
+ val today = Calendar.getInstance()
+ today.set(Calendar.DAY_OF_MONTH, 1) // 设置为本月第一天
+ val firstDayOfMonth = formatter.format(today.time)
+
+ today.add(Calendar.MONTH, 1) // 移动到下个月
+ today.set(Calendar.DAY_OF_MONTH, 0) // 设置为下个月的最后一天
+ val lastDayOfMonth = formatter.format(today.time)
+ viewModel.getCurrentDayStatsByType(firstDayOfMonth,lastDayOfMonth,"快递") .observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+ }
+ DateType.YEAR -> {
+ val today = Calendar.getInstance()
+ today.set(Calendar.MONTH, Calendar.JANUARY) // 设置为第一月
+ today.set(Calendar.DAY_OF_MONTH, 1) // 设置为第一天
+ val firstDayOfYear = formatter.format(today.time)
+
+ today.add(Calendar.YEAR, 1) // 移动到下一年
+ today.set(Calendar.MONTH, Calendar.DECEMBER) // 设置为最后一月
+ today.set(Calendar.DAY_OF_MONTH, 31) // 设置为最后一天
+ val lastDayOfYear = formatter.format(today.time)
+ viewModel.getCurrentDayStatsByType(firstDayOfYear,lastDayOfYear,"快递") .observe(viewLifecycleOwner) { stats ->
+// binding.textPackageCount.text = "${stats}个"
+ binding.layoutYearStats.textTotalPackages.text = "${stats}个"
+ }
+ }
+ }
+ }
+ private fun loadPackages_bak() {
viewModel.getPackages(
currentDate.timeInMillis,
currentDateType.name
).observe(viewLifecycleOwner) { packages ->
when (currentDateType) {
- DateType.WEEK -> {
- // 更新图表数据
- updateBarChartData()
- updatePieChartData()
+ DateType.DAY -> {
+ binding.textPackageCount.text = "${packages.size}个"
+
+ // 获取本周统计
+ viewModel.getPackagesReaded(currentDate.timeInMillis,
+ currentDateType.name)
+ .observe(viewLifecycleOwner) { unpackages->
+ // 只读取未取件的包裹
+ packageAdapter.updatePackages(unpackages)
+ }
+
}
- else -> {
- packageAdapter.updatePackages(packages)
+ DateType.WEEK -> {
+ // 获取本周统计
+ viewModel.getCurrentWeekStats2(startDateCur,endDateCur).observe(viewLifecycleOwner) { stats ->
+ binding.textPackageCount.text = "${stats}个"
+ }
+// viewModel.getCurrentWeekStats(currentDate.timeInMillis)
+// .observe(viewLifecycleOwner) { stats ->
+// val weekTotal = stats.sumOf { it.count }
+// binding.textPackageCount.text = "${weekTotal}个"
+// }
+ }
+ DateType.MONTH -> {
+ // 获取本月统计
+ viewModel.getMonthlyStats(currentDate.timeInMillis)
+ .observe(viewLifecycleOwner) { stats ->
+ val monthTotal = stats.sumOf { it.count }
+ binding.textPackageCount.text = "${monthTotal}个"
+ }
+ }
+ DateType.YEAR -> {
+ // 获取本年统计
+ viewModel.getCurrentYearStats(currentDate.timeInMillis)
+ .observe(viewLifecycleOwner) { stats ->
+ val yearTotal = stats.sumOf { it.count }
+ binding.textPackageCount.text = "${yearTotal}个"
+ }
+ }
}
- }
- binding.textPackageCount.text = "${packages.size}个"
+
+// packageAdapter.updatePackages(packages)
+// binding.textPackageCount.text = "${packages.size}个"
}
}
+ private fun setupHeatmap() {
+ heatmapView.visibility = View.GONE
+ }
+
+
+
+ // 用于创建图例
+ private fun createLegend(): LinearLayout {
+ val legendLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.END or Gravity.CENTER_VERTICAL
+ setPadding(8, 16, 8, 0)
+ }
+
+ val labelLow = TextView(context).apply {
+ text = "少"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+ legendLayout.addView(labelLow)
+
+ val legendLevels = listOf(0, 5, 10, 15, 20)
+ legendLevels.forEach { level ->
+ val colorBox = View(context).apply {
+ setBackgroundColor(getHeatmapColor(level))
+ val size = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ layoutParams = LinearLayout.LayoutParams(size, size).apply {
+ marginEnd = 4
+ }
+ }
+
+ val label = TextView(context).apply {
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+
+ legendLayout.addView(colorBox)
+ legendLayout.addView(label)
+ }
+
+ val labelHigh = TextView(context).apply {
+ text = "多"
+ textSize = 10f
+ setPadding(8, 0, 0, 0)
+ }
+ legendLayout.addView(labelHigh)
+
+ return legendLayout
+ }
+
+ private fun updateHeatmapData() {
+ viewModel.getYearlyHeatmap(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ if (stats.isEmpty()) return@observe
+
+ val heatmapMatrix = Array(7) { IntArray(52) }
+ stats.forEach { stat ->
+ val week = stat.weekOfYear - 1
+ val dayOfWeek = stat.dayOfWeek - 1
+ if (week in 0..51 && dayOfWeek in 0..6) {
+ heatmapMatrix[dayOfWeek][week] = stat.count
+ }
+ }
+
+ binding.layoutWeekStats.heatmapYearly.apply {
+ removeAllViews()
+
+ // 外层父布局:水平 LinearLayout,左固定周标签,右为横向滚动热力图
+ val outerLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ }
+
+ // 左侧星期标签列
+ val dayLabelLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ val dayLabels = arrayOf("周一", "周二", "周三", "周四", "周五", "周六", "周日")
+ // 顶部空白占位
+ addView(TextView(context).apply {
+ text = ""
+ textSize = 20f
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ })
+ dayLabels.forEach { label ->
+ val textView = TextView(context).apply {
+ text = label
+ textSize = 10f
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ setPadding(4, 0, 4, 0)
+ }
+ addView(textView)
+ }
+ }
+
+ // 右侧滚动部分
+ val scrollView = HorizontalScrollView(context).apply {
+ isHorizontalScrollBarEnabled = false
+ layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ val scrollContentLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ }
+
+ val gridLayout = GridLayout(context).apply {
+ rowCount = 8
+ columnCount = 52
+ }
+
+ // 添加月份标签(估算)
+ val months = arrayOf(
+ "1月", "2月", "3月", "4月", "5月", "6月",
+ "7月", "8月", "9月", "10月", "11月", "12月"
+ )
+ /* months.forEachIndexed { index, month ->
+ val label = TextView(context).apply {
+ text = month
+ textSize = 10f
+ setPadding(10, 0, 8, 4)
+ val weekPosition = (index * 4.3).toInt()
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(weekPosition)
+ rowSpec = GridLayout.spec(0)
+ }
+ }
+ gridLayout.addView(label)
+ }*/
+ months.forEachIndexed { index, month ->
+ val label = TextView(context).apply {
+ text = month
+ textSize = 10f
+ setPadding(10, 0, 8, 4)
+
+ val weekPosition = (index * 4.3).toInt()
+ val span = 4 // 控制跨列范围
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(weekPosition, span, GridLayout.CENTER)
+ rowSpec = GridLayout.spec(0)
+ }
+ }
+ gridLayout.addView(label)
+ }
+
+ // 添加热力格子
+ for (day in 0..6) {
+ for (week in 0..51) {
+ val count = heatmapMatrix[day][week]
+ val cell = View(context).apply {
+ layoutParams = GridLayout.LayoutParams().apply {
+ width = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ columnSpec = GridLayout.spec(week)
+ rowSpec = GridLayout.spec(day + 1)
+ setMargins(1, 1, 1, 1)
+ }
+ setBackgroundColor(getHeatmapColor(count))
+ }
+ gridLayout.addView(cell)
+ }
+ }
+
+ scrollContentLayout.addView(gridLayout)
+ scrollView.addView(scrollContentLayout)
+
+ // 添加两个主要部分到外层布局
+ outerLayout.addView(dayLabelLayout)
+ outerLayout.addView(scrollView)
+
+ // 图例
+ val legendLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.END or Gravity.CENTER_VERTICAL
+ setPadding(8, 16, 8, 0)
+ layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ val labelLow = TextView(context).apply {
+ text = "少"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+ legendLayout.addView(labelLow)
+
+ val legendLevels = listOf(0, 5, 10, 15, 20)
+ legendLevels.forEach { level ->
+ val colorBox = View(context).apply {
+ setBackgroundColor(getHeatmapColor(level))
+ val size = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ layoutParams = LinearLayout.LayoutParams(size, size).apply {
+ marginEnd = 4
+ }
+ }
+
+ val label = TextView(context).apply {
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+
+ legendLayout.addView(colorBox)
+ legendLayout.addView(label)
+ }
+
+ val labelHigh = TextView(context).apply {
+ text = "多"
+ textSize = 10f
+ setPadding(8, 0, 0, 0)
+ }
+ legendLayout.addView(labelHigh)
+
+ // 总容器垂直布局:热力图 + 图例
+ val container = LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ addView(outerLayout)
+ addView(legendLayout)
+ }
+
+// addView(container)
+
+ // 设置外部 margin
+ val params = LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ ).apply {
+ setMargins(16, 16, 16, 16) // 左、上、右、下的 margin,单位是像素
+ }
+
+ // 添加到父布局并应用 margin
+ addView(container, params)
+
+ }
+ }
+ }
+
+
+
+ private fun updateHeatmapData_a() {
+ viewModel.getYearlyHeatmap(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ if (stats.isEmpty()) return@observe
+
+ // 创建52周x7天的数据矩阵
+ val heatmapMatrix = Array(7) { IntArray(52) }
+
+ // 填充数据
+ stats.forEach { stat ->
+ val week = stat.weekOfYear - 1 // 0-51
+ val dayOfWeek = stat.dayOfWeek - 1 // 0-6
+ if (week in 0..51 && dayOfWeek in 0..6) {
+ heatmapMatrix[dayOfWeek][week] = stat.count
+ }
+ }
+
+ // 更新UI
+ binding.layoutWeekStats.heatmapYearly.apply {
+ removeAllViews()
+
+ val gridLayout = GridLayout(context).apply {
+ rowCount = 8 // 1行月份 + 7行星期
+ columnCount = 53 // 1列星期 + 52列周数
+ }
+
+ // 添加月份标签
+ val months = arrayOf(
+ "1月", "2月", "3月", "4月", "5月", "6月",
+ "7月", "8月", "9月", "10月", "11月", "12月"
+ )
+ months.forEachIndexed { index, month ->
+ val label = TextView(context).apply {
+ text = month
+ textSize = 10f
+ setPadding(0, 0, 8, 4)
+ val weekPosition = (index * 4.3).toInt() // 估算月份起始位置
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(weekPosition + 1)
+ rowSpec = GridLayout.spec(0)
+ }
+ }
+ gridLayout.addView(label)
+ }
+
+ // 添加星期标签
+ val dayLabels = arrayOf("周一", "周二", "周三", "周四", "周五", "周六", "周日")
+ dayLabels.forEachIndexed { index, label ->
+ val textView = TextView(context).apply {
+ text = label
+ textSize = 10f
+ setPadding(4, 0, 8, 0)
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(0)
+ rowSpec = GridLayout.spec(index + 1)
+ }
+ }
+ gridLayout.addView(textView)
+ }
+
+ // 添加热力图单元格
+ for (day in 0..6) {
+ for (week in 0..51) {
+ val count = heatmapMatrix[day][week]
+ val cell = View(context).apply {
+ layoutParams = GridLayout.LayoutParams().apply {
+ width = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ columnSpec = GridLayout.spec(week + 1)
+ rowSpec = GridLayout.spec(day + 1)
+ setMargins(1, 1, 1, 1)
+ }
+ setBackgroundColor(getHeatmapColor(count))
+ }
+ gridLayout.addView(cell)
+ }
+ }
+
+ // 创建图例(Legend)
+ val legendLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.END or Gravity.CENTER_VERTICAL // 靠右对齐
+ setPadding(8, 16, 8, 0)
+ layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ // 左侧“少”标签
+ val labelLow = TextView(context).apply {
+ text = "少"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+ legendLayout.addView(labelLow)
+
+ // 渐变色块 + 数值
+ val legendLevels = listOf(0, 5, 10, 15, 20)
+ legendLevels.forEach { level ->
+ val colorBox = View(context).apply {
+ setBackgroundColor(getHeatmapColor(level))
+ val size = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ layoutParams = LinearLayout.LayoutParams(size, size).apply {
+ marginEnd = 4
+ }
+ }
+
+ val label = TextView(context).apply {
+// text = "$level"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+
+ legendLayout.addView(colorBox)
+ legendLayout.addView(label)
+ }
+
+ // 右侧“多”标签
+ val labelHigh = TextView(context).apply {
+ text = "多"
+ textSize = 10f
+ setPadding(8, 0, 0, 0)
+ }
+ legendLayout.addView(labelHigh)
+
+ // 垂直组合 gridLayout + legendLayout
+ val container = LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ addView(gridLayout)
+ addView(legendLayout)
+ }
+
+ addView(container)
+ }
+ }
+ }
+
+ private fun updateHeatmapData_aaa() {
+ viewModel.getYearlyHeatmap(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ if (stats.isEmpty()) return@observe
+
+ // 创建52周x7天的数据矩阵
+ val heatmapMatrix = Array(7) { IntArray(52) }
+
+ // 填充数据
+ stats.forEach { stat ->
+ val week = stat.weekOfYear - 1 // 0-51
+ val dayOfWeek = stat.dayOfWeek - 1 // 0-6
+ if (week in 0..51 && dayOfWeek in 0..6) {
+ heatmapMatrix[dayOfWeek][week] = stat.count
+ }
+ }
+
+ // 更新UI
+ binding.layoutWeekStats.heatmapYearly.apply {
+ removeAllViews()
+
+ val gridLayout = GridLayout(context).apply {
+ rowCount = 8 // 1行月份 + 7行星期
+ columnCount = 53 // 1列星期 + 52列周数
+ }
+
+ // 添加月份标签
+ val months = arrayOf("1月", "2月", "3月", "4月", "5月", "6月",
+ "7月", "8月", "9月", "10月", "11月", "12月")
+ months.forEachIndexed { index, month ->
+ val label = TextView(context).apply {
+ text = month
+ textSize = 10f
+ setPadding(0, 0, 8, 4)
+ val weekPosition = (index * 4.3).toInt() // 估算月份起始位置
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(weekPosition + 1)
+ rowSpec = GridLayout.spec(0)
+ }
+ }
+ gridLayout.addView(label)
+ }
+
+ // 添加星期标签
+ val dayLabels = arrayOf("周一", "周二", "周三", "周四", "周五", "周六", "周日")
+ dayLabels.forEachIndexed { index, label ->
+ val textView = TextView(context).apply {
+ text = label
+ textSize = 10f
+ setPadding(4, 0, 8, 0)
+ layoutParams = GridLayout.LayoutParams().apply {
+ columnSpec = GridLayout.spec(0)
+ rowSpec = GridLayout.spec(index + 1)
+ }
+ }
+ gridLayout.addView(textView)
+ }
+
+ // 添加热力图单元格
+ for (day in 0..6) {
+ for (week in 0..51) {
+ val count = heatmapMatrix[day][week]
+ val cell = View(context).apply {
+ layoutParams = GridLayout.LayoutParams().apply {
+ width = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ columnSpec = GridLayout.spec(week + 1)
+ rowSpec = GridLayout.spec(day + 1)
+ setMargins(1, 1, 1, 1)
+ }
+ setBackgroundColor(getHeatmapColor(count))
+ }
+ gridLayout.addView(cell)
+ }
+ }
+
+ // ✅ 把 gridLayout 包裹进 HorizontalScrollView
+ val scrollView = HorizontalScrollView(context).apply {
+ layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ isHorizontalScrollBarEnabled = true
+ }
+ scrollView.addView(gridLayout)
+
+
+
+
+ // 创建图例(Legend)
+ val legendLayout = LinearLayout(context).apply {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.END or Gravity.CENTER_VERTICAL // 靠右对齐
+ setPadding(8, 16, 8, 0)
+ layoutParams = LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ // 左侧“少”标签
+ val labelLow = TextView(context).apply {
+ text = "少"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+ legendLayout.addView(labelLow)
+
+ // 渐变色块 + 数值
+ val legendLevels = listOf(0, 5, 10, 15, 20)
+ legendLevels.forEach { level ->
+ val colorBox = View(context).apply {
+ setBackgroundColor(getHeatmapColor(level))
+ val size = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ layoutParams = LinearLayout.LayoutParams(size, size).apply {
+ marginEnd = 4
+ }
+ }
+
+ val label = TextView(context).apply {
+// text = "$level"
+ textSize = 10f
+ setPadding(0, 0, 8, 0)
+ }
+
+ legendLayout.addView(colorBox)
+ legendLayout.addView(label)
+ }
+
+ // 右侧“多”标签
+ val labelHigh = TextView(context).apply {
+ text = "多"
+ textSize = 10f
+ setPadding(8, 0, 0, 0)
+ }
+ legendLayout.addView(labelHigh)
+
+ // 垂直组合 gridLayout + legendLayout
+ val container = LinearLayout(context).apply {
+ orientation = LinearLayout.VERTICAL
+ addView(scrollView)
+ addView(legendLayout)
+ }
+
+ addView(container)
+ }
+ }
+ }
+
+ private fun getHeatmapColor(count: Int): Int {
+ return when {
+ count == 0 -> Color.parseColor("#EBECF1") // 最淡
+ count < 5 -> Color.parseColor("#ACE7B1")
+ count < 10 -> Color.parseColor("#68C16F")
+ count < 15 -> Color.parseColor("#529F57")
+ else -> Color.parseColor("#356D40") // 最深
+ }
+ }
+
+
+
+ private fun updateHeatmapData_bak() {
+ viewModel.getYearlyHeatmap(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats ->
+ if (stats.isEmpty()) return@observe
+
+ // 创建52周x7天的数据矩阵
+ val heatmapMatrix = Array(7) { IntArray(52) }
+
+ // 填充数据
+ stats.forEach { stat ->
+ val week = stat.weekOfYear - 1 // 0-51
+ val dayOfWeek = stat.dayOfWeek - 1 // 0-6
+ if (week in 0..51 && dayOfWeek in 0..6) {
+ heatmapMatrix[dayOfWeek][week] = stat.count
+ }
+ }
+
+ // 更新UI
+ binding.layoutWeekStats.heatmapYearly.apply {
+ removeAllViews()
+
+ val gridLayout = GridLayout(context).apply {
+ rowCount = 8 // 增加一行用于显示月份
+ columnCount = 53 // 增加一列用于显示星期标签
+ }
+
+ // 添加月份标签
+ val months = arrayOf("1月", "2月", "3月", "4月", "5月", "6月",
+ "7月", "8月", "9月", "10月", "11月", "12月")
+ months.forEachIndexed { index, month ->
+ val label = TextView(context).apply {
+ text = month
+ textSize = 10f
+ setPadding(0, 0, 8, 4)
+ // 计算每个月份标签的位置
+ val weekPosition = (index * 4.3).toInt()
+ val params = GridLayout.LayoutParams()
+ params.columnSpec = GridLayout.spec(weekPosition + 1)
+ params.rowSpec = GridLayout.spec(0)
+ layoutParams = params
+ }
+ gridLayout.addView(label)
+ }
+
+ // 添加星期标签
+ val dayLabels = arrayOf("周一", "周二", "周三", "周四", "周五", "周六", "周日")
+ dayLabels.forEachIndexed { index, label ->
+ val textView = TextView(context).apply {
+ text = label
+ textSize = 10f
+ setPadding(4, 0, 8, 0)
+ val params = GridLayout.LayoutParams()
+ params.columnSpec = GridLayout.spec(0)
+ params.rowSpec = GridLayout.spec(index + 1)
+ layoutParams = params
+ }
+ gridLayout.addView(textView)
+ }
+
+ // 添加热力图单元格
+ for (day in 0..6) {
+ for (week in 0..51) {
+ val count = heatmapMatrix[day][week]
+ val cell = View(context).apply {
+ val params = GridLayout.LayoutParams().apply {
+ width = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ height = resources.getDimensionPixelSize(R.dimen.heatmap_cell_size)
+ columnSpec = GridLayout.spec(week + 1)
+ rowSpec = GridLayout.spec(day + 1)
+ setMargins(1, 1, 1, 1)
+ }
+ layoutParams = params
+ setBackgroundColor(getHeatmapColor(count))
+ }
+ gridLayout.addView(cell)
+ }
+ }
+
+ addView(gridLayout)
+ }
+ }
+ }
+
+ private fun getHeatmapColor_bak(count: Int): Int {
+ return when {
+ count == 0 -> Color.parseColor("#EBEDF0")
+ count == 1 -> Color.parseColor("#9BE9A8")
+ count == 2 -> Color.parseColor("#40C463")
+ count <= 4 -> Color.parseColor("#30A14E")
+ else -> Color.parseColor("#216E39")
+ }
+ }
+
+ private fun updateCharts() {
+ when (currentDateType) {
+ DateType.DAY -> {
+ // 日视图显示包裹列表,隐藏统计图表
+ binding.recyclerPackages.visibility = View.VISIBLE
+ binding.layoutWeekStats.root.visibility = View.GONE
+ binding.layoutYearStats.root.visibility = View.GONE
+ binding.cardPackageStats.visibility = View.VISIBLE
+ }
+ DateType.WEEK, DateType.MONTH -> {
+ // 周和月视图显示柱状图和饼图,隐藏包裹列表
+ binding.recyclerPackages.visibility = View.GONE
+ binding.layoutWeekStats.root.visibility = View.VISIBLE
+ binding.layoutYearStats.root.visibility = View.GONE
+ binding.layoutWeekStats.chartDailyPackages.visibility = View.VISIBLE
+ (binding.layoutWeekStats.chartDailyPackages.parent as? View)?.visibility = View.VISIBLE
+ binding.layoutWeekStats.heatmapYearly.visibility = View.GONE
+ binding.cardPackageStats.visibility = View.VISIBLE
+ updateBarChartData()
+ updatePieChartData()
+ }
+ DateType.YEAR -> {
+ // 年视图显示热力图和饼图,隐藏包裹列表和柱状图
+ binding.recyclerPackages.visibility = View.GONE
+ binding.layoutWeekStats.root.visibility = View.VISIBLE
+ binding.layoutYearStats.root.visibility = View.VISIBLE
+ (binding.layoutWeekStats.chartDailyPackages.parent as? View)?.visibility = View.GONE
+ binding.layoutWeekStats.heatmapYearly.visibility = View.VISIBLE
+ binding.cardPackageStats.visibility = View.GONE
+ updateHeatmapData()
+ updatePieChartData()
+ updateYearlyStats()
+ }
+ }
+ }
+
+ private fun updateYearlyStats() {
+ viewModel.getYearlyStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats: List<DailyStat> ->
+ if (stats.isEmpty()) return@observe
+
+ // 更新年度包裹总数
+// binding.layoutYearStats.textTotalPackages.text = "${stats.sumOf { it.count }}个"
+
+ // 更新平均每天包裹数
+ val avgDaily = stats.sumOf { it.count }.toFloat() / 365
+ binding.layoutYearStats.textDailyAverage.text = String.format("%.2f", avgDaily)
+ }
+ }
+
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
+ private fun loadUserInfo() {
+
+ lifecycleScope.launch {
+ try {
+ // 从本地获取保存的手机号
+ val savedPhone = PreferencesManager.getPhone()
+ if (savedPhone.isNullOrEmpty()) {
+ Toast.makeText(context, "用户未登录", Toast.LENGTH_SHORT).show()
+ return@launch
+ }
+
+ val response = RetrofitClient.apiService.getUserInfo(savedPhone)
+ if (response.code == "0" && response.data != null) {
+ // 保存用户信息
+ currentUserInfo = response.data
+ val userInfo = response.data
+ if(userInfo.isMember){
+ hiddleOverlay()
+ }else{
+ // 显示遮罩层
+ showOverlay()
+ }
+
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ Toast.makeText(context, "获取用户信息失败", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ }
}
\ No newline at end of file
--
Gitblit v1.9.3