From f67cf3b81a00f732ca743431258ae6b78f5f40ab Mon Sep 17 00:00:00 2001
From: tj <1378534974@qq.com>
Date: 星期四, 17 四月 2025 15:05:28 +0800
Subject: [PATCH] 11、我的 切换头像 点击切换头像没有显示允许存储权限的窗口,华为的手机目前有 49、首页 实时刷新 点击全部取件或其他分类后,回到上一层,内容没有刷新(5个分类) 52、数据统计 数据统计 1.周月年的柱状图统计逻辑需要修改为只统计快递类的数据 2.按年的图形统计,右下方加上图示说明 53、首页 首页登录 点击用户协议、隐私政策无反应
---
app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 422 insertions(+), 22 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 f8808f2..b689d58 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
@@ -21,8 +21,11 @@
import java.util.*
import java.text.SimpleDateFormat
import android.graphics.Color
+import android.view.Gravity
import android.widget.GridLayout
+import android.widget.LinearLayout
import android.widget.Toast
+import androidx.cardview.widget.CardView
import androidx.lifecycle.lifecycleScope
import com.example.firstapp.database.response.UserInfo
import com.example.firstapp.database.service.RetrofitClient
@@ -39,11 +42,14 @@
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 {
@@ -113,11 +119,13 @@
private fun setupTabLayout() {
val weekStatsView = binding.layoutWeekStats.root
- val bar_title:TextView = weekStatsView.findViewById(R.id.bar_title)
- val pie_title:TextView = weekStatsView.findViewById(R.id.pie_title)
+ 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
@@ -191,6 +199,81 @@
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 -> {
// 获取本周的起始和结束日期
@@ -221,6 +304,7 @@
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)
@@ -431,31 +515,200 @@
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 // 增大数值文字大小
+ 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 // 增大数值文字大小
- val pieData = PieData(dataSet)
- pieData.setValueFormatter(object : ValueFormatter() {
- override fun getFormattedValue(value: Float): String {
- return value.toInt().toString()
- }
- })
+ val pieData = PieData(dataSet)
+ pieData.setValueFormatter(object : ValueFormatter() {
+ override fun getFormattedValue(value: Float): String {
+ return value.toInt().toString()
+ }
+ })
- pieChart.data = pieData
- pieChart.invalidate()
+ 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() {
+ 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 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
@@ -465,7 +718,7 @@
binding.textPackageCount.text = "${packages.size}个"
// 获取本周统计
- viewModel.getPackagesUnread(currentDate.timeInMillis,
+ viewModel.getPackagesReaded(currentDate.timeInMillis,
currentDateType.name)
.observe(viewLifecycleOwner) { unpackages->
// 只读取未取件的包裹
@@ -511,6 +764,153 @@
}
private fun updateHeatmapData() {
+ 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 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
@@ -592,7 +992,7 @@
}
}
- private fun getHeatmapColor(count: Int): Int {
+ private fun getHeatmapColor_bak(count: Int): Int {
return when {
count == 0 -> Color.parseColor("#EBEDF0")
count == 1 -> Color.parseColor("#9BE9A8")
@@ -643,7 +1043,7 @@
if (stats.isEmpty()) return@observe
// 更新年度包裹总数
- binding.layoutYearStats.textTotalPackages.text = "${stats.sumOf { it.count }}个"
+// binding.layoutYearStats.textTotalPackages.text = "${stats.sumOf { it.count }}个"
// 更新平均每天包裹数
val avgDaily = stats.sumOf { it.count }.toFloat() / 365
--
Gitblit v1.9.3