| | |
| | | fun getCourierStatsByWeek(date: Long): Flow<List<CourierStat>> |
| | | |
| | | @Query(""" |
| | | SELECT strftime('%W', createtime) as date, |
| | | COUNT(*) as count, |
| | | MIN(createtime) as week_start |
| | | FROM code |
| | | WHERE strftime('%Y', createtime) = strftime('%Y', 'now') |
| | | GROUP BY strftime('%W', createtime) |
| | | ORDER BY week_start ASC |
| | | WITH RECURSIVE weeks(week_start, week_end) AS ( |
| | | -- 从选定的日期开始计算周 |
| | | SELECT |
| | | date(datetime(:date/1000, 'unixepoch', 'localtime'), 'weekday 1', '-28 days') as week_start, |
| | | date(datetime(:date/1000, 'unixepoch', 'localtime'), 'weekday 0', '-28 days') as week_end |
| | | UNION ALL |
| | | SELECT |
| | | date(week_start, '+7 days'), |
| | | date(week_end, '+7 days') |
| | | FROM weeks |
| | | WHERE date(week_start) <= date(datetime(:date/1000, 'unixepoch', 'localtime')) |
| | | LIMIT 5 |
| | | ) |
| | | SELECT |
| | | CAST(strftime('%W', week_start) AS INTEGER) as date, |
| | | COUNT(code.id) as count, |
| | | week_start as week_start |
| | | FROM weeks |
| | | LEFT JOIN code ON datetime(code.createtime) BETWEEN datetime(weeks.week_start) |
| | | AND datetime(weeks.week_end, '+23 hours', '+59 minutes', '+59 seconds') |
| | | GROUP BY weeks.week_start |
| | | ORDER BY weeks.week_start ASC |
| | | """) |
| | | fun getDailyStatsByWeek(): Flow<List<DailyStat>> |
| | | fun getDailyStatsByWeek(date: Long): Flow<List<DailyStat>> |
| | | |
| | | @Query(""" |
| | | SELECT * FROM code |
| | |
| | | |
| | | fun getCourierStats(date: Long) = codeDao.getCourierStatsByWeek(date) |
| | | |
| | | fun getDailyStats() = codeDao.getDailyStatsByWeek() |
| | | fun getDailyStats(date: Long) = codeDao.getDailyStatsByWeek(date) |
| | | |
| | | |
| | | @WorkerThread |
| | |
| | | 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 |
| | | } |
| | | viewModel.getDailyStats(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats -> |
| | | if (stats.isEmpty()) return@observe |
| | | |
| | | val entries = stats.mapIndexed { index, stat -> |
| | | BarEntry(index.toFloat(), stat.count.toFloat()) |
| | |
| | | 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 "第${stats[position].date}周" |
| | | } |
| | | return "" |
| | | } |
| | | } |
| | | labelCount = stats.size |
| | | granularity = 1f |
| | | labelRotationAngle = -45f |
| | | textSize = 10f |
| | | setDrawGridLines(false) |
| | | } |
| | | |
| | | barChart.notifyDataSetChanged() |
| | | barChart.invalidate() |
| | | // 调整图表显示 |
| | | barChart.apply { |
| | | setVisibleXRangeMaximum(5f) |
| | | moveViewToX(0f) |
| | | |
| | | axisLeft.apply { |
| | | axisMinimum = 0f |
| | | granularity = 1f |
| | | setDrawGridLines(true) |
| | | } |
| | | |
| | | barData.barWidth = 0.6f |
| | | description.isEnabled = false |
| | | legend.isEnabled = false |
| | | |
| | | invalidate() |
| | | } |
| | | } |
| | | } |
| | | private fun setupPieChart() { |
| | |
| | | |
| | | fun getCourierStats(date: Long) = repository.getCourierStats(date).asLiveData() |
| | | |
| | | fun getDailyStats() = repository.getDailyStats().asLiveData() |
| | | fun getDailyStats(date: Long) = repository.getDailyStats(date).asLiveData() |
| | | |
| | | fun insert(code: Code) = viewModelScope.launch { |
| | | repository.insert(code) |