| | |
| | | import java.util.* |
| | | import java.text.SimpleDateFormat |
| | | import android.graphics.Color |
| | | import android.widget.Button |
| | | import android.widget.GridLayout |
| | | import android.widget.Toast |
| | | import androidx.core.content.ContextCompat |
| | | import androidx.lifecycle.lifecycleScope |
| | | import com.bumptech.glide.Glide |
| | | import com.example.firstapp.database.response.UserInfo |
| | | import com.example.firstapp.database.service.RetrofitClient |
| | | import com.example.firstapp.model.DailyStat |
| | | import com.example.firstapp.utils.PreferencesManager |
| | | import com.github.mikephil.charting.components.YAxis |
| | | import kotlinx.coroutines.launch |
| | | |
| | | class DashboardFragment : Fragment() { |
| | | |
| | |
| | | private lateinit var barChart: BarChart |
| | | private lateinit var pieChart: PieChart |
| | | private lateinit var heatmapView: View |
| | | private var currentUserInfo: UserInfo? = null // 确保使用你的实际数据类 |
| | | |
| | | |
| | | enum class DateType { |
| | | DAY, WEEK, MONTH, YEAR |
| | | } |
| | |
| | | return binding.root |
| | | } |
| | | |
| | | override fun onResume() { |
| | | super.onResume() |
| | | // 重新加载用户信息 |
| | | loadUserInfo() |
| | | } |
| | | |
| | | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| | | super.onViewCreated(view, savedInstanceState) |
| | | |
| | |
| | | setupView(view) |
| | | updateDateDisplay() |
| | | 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.viewOverlay.visibility = View.VISIBLE |
| | | } |
| | | |
| | | private fun hiddleOverlay() { |
| | | binding.viewOverlay.visibility = View.GONE |
| | | binding.viewOverlay.visibility = View.GONE |
| | | |
| | | |
| | | } |
| | | |
| | | |
| | | private fun setupRecyclerView() { |
| | | binding.recyclerPackages.apply { |
| | |
| | | setDrawGridLines(false) |
| | | granularity = 1f |
| | | labelRotationAngle = 0f |
| | | textSize = 12f |
| | | textSize = 10f //标签字体 |
| | | setExtraLeftOffset(5f) // 减少左侧留白 |
| | | setExtraBottomOffset(15f) |
| | | } |
| | | |
| | |
| | | setExtraOffsets(10f, 10f, 10f, 20f) |
| | | } |
| | | |
| | | |
| | | |
| | | updateBarChartData() |
| | | } |
| | | private fun updateBarChartData() { |
| | |
| | | currentDate.timeInMillis, |
| | | currentDateType.name |
| | | ).observe(viewLifecycleOwner) { packages -> |
| | | when (currentDateType) { |
| | | DateType.DAY -> { |
| | | binding.textPackageCount.text = "${packages.size}个" |
| | | } |
| | | DateType.WEEK -> { |
| | | // 获取本周统计 |
| | | 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}个" |
| | | } |
| | | } |
| | | } |
| | | packageAdapter.updatePackages(packages) |
| | | binding.textPackageCount.text = "${packages.size}个" |
| | | packageAdapter.updatePackages(packages) |
| | | // binding.textPackageCount.text = "${packages.size}个" |
| | | } |
| | | } |
| | | private fun setupHeatmap() { |
| | |
| | | |
| | | // 更新UI |
| | | binding.layoutWeekStats.heatmapYearly.apply { |
| | | // 清除现有的子视图 |
| | | removeAllViews() |
| | | |
| | | // 创建网格布局 |
| | | val gridLayout = GridLayout(context).apply { |
| | | rowCount = 7 |
| | | columnCount = 52 |
| | | rowCount = 8 // 增加一行用于显示月份 |
| | | columnCount = 53 // 增加一列用于显示星期标签 |
| | | } |
| | | |
| | | // 添加日期标签 |
| | | val dayLabels = arrayOf("周日", "周一", "周二", "周三", "周四", "周五", "周六") |
| | | for (i in 0..6) { |
| | | // 添加月份标签 |
| | | 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 = dayLabels[i] |
| | | text = month |
| | | textSize = 10f |
| | | setPadding(0, 0, 8, 0) |
| | | 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 (week in 0..51) { |
| | | val count = heatmapMatrix[day][week] |
| | | val cell = View(context).apply { |
| | | layoutParams = ViewGroup.LayoutParams( |
| | | resources.getDimensionPixelSize(R.dimen.heatmap_cell_size), |
| | | resources.getDimensionPixelSize(R.dimen.heatmap_cell_size) |
| | | ) |
| | | 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)) |
| | | setPadding(1, 1, 1, 1) |
| | | } |
| | | gridLayout.addView(cell) |
| | | } |
| | |
| | | } |
| | | |
| | | private fun getHeatmapColor(count: Int): Int { |
| | | // 根据数量返回不同深浅的颜色 |
| | | return when { |
| | | count == 0 -> Color.parseColor("#EBEDF0") |
| | | count <= 2 -> Color.parseColor("#9BE9A8") |
| | | count <= 4 -> Color.parseColor("#40C463") |
| | | count <= 6 -> Color.parseColor("#30A14E") |
| | | count == 1 -> Color.parseColor("#9BE9A8") |
| | | count == 2 -> Color.parseColor("#40C463") |
| | | count <= 4 -> Color.parseColor("#30A14E") |
| | | else -> Color.parseColor("#216E39") |
| | | } |
| | | } |
| | |
| | | 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.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() |
| | | } |
| | |
| | | binding.recyclerPackages.visibility = View.GONE |
| | | binding.layoutWeekStats.root.visibility = View.VISIBLE |
| | | binding.layoutYearStats.root.visibility = View.VISIBLE |
| | | binding.layoutWeekStats.chartDailyPackages.visibility = View.GONE |
| | | (binding.layoutWeekStats.chartDailyPackages.parent as? View)?.visibility = View.GONE |
| | | binding.layoutWeekStats.heatmapYearly.visibility = View.VISIBLE |
| | | binding.cardPackageStats.visibility = View.GONE |
| | | updateHeatmapData() |
| | | updatePieChartData() |
| | | updateYearlyStats() |
| | | } |
| | | } |
| | | } |
| | |
| | | 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() |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |