app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/model/CourierStat.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/model/DailyStat.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/java/com/example/firstapp/ui/dashboard/DashboardViewModel.kt | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/fragment_dashboard.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
app/src/main/res/layout/layout_week_stats.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt
@@ -73,29 +73,31 @@ fun getPackagesByDay(date: Long): Flow<List<Code>> @Query(""" SELECT * FROM code WHERE strftime('%Y-%W', substr(createtime, 1, 10)) = strftime('%Y-%W', datetime(:date/1000, 'unixepoch', 'localtime')) ORDER BY createtime DESC """) fun getPackagesByWeek(date: Long): Flow<List<Code>> @Query(""" SELECT category as courierName, COUNT(*) as count SELECT type as courierName, COUNT(*) as count FROM code WHERE strftime('%Y-%W', substr(createtime, 1, 10)) = strftime('%Y-%W', datetime(:date/1000, 'unixepoch', 'localtime')) GROUP BY category GROUP BY type ORDER BY count DESC """) fun getCourierStatsByWeek(date: Long): Flow<List<CourierStat>> @Query(""" SELECT substr(createtime, 1, 10) as date, COUNT(*) as count SELECT strftime('%W', createtime) as date, COUNT(*) as count, MIN(createtime) as week_start FROM code WHERE strftime('%Y-%W', substr(createtime, 1, 10)) = strftime('%Y-%W', datetime(:date/1000, 'unixepoch', 'localtime')) GROUP BY substr(createtime, 1, 10) WHERE strftime('%Y', createtime) = strftime('%Y', 'now') GROUP BY strftime('%W', createtime) ORDER BY week_start ASC """) fun getDailyStatsByWeek(date: Long): Flow<List<DailyStat>> fun getDailyStatsByWeek(): Flow<List<DailyStat>> @Query(""" SELECT * FROM code WHERE substr(createtime, 1, 10) = date(:date/1000, 'unixepoch', 'localtime') ORDER BY createtime DESC """) fun getPackagesByWeek(date: Long): Flow<List<Code>> } app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt
@@ -43,7 +43,7 @@ fun getCourierStats(date: Long) = codeDao.getCourierStatsByWeek(date) fun getDailyStats(date: Long) = codeDao.getDailyStatsByWeek(date) fun getDailyStats() = codeDao.getDailyStatsByWeek() @WorkerThread app/src/main/java/com/example/firstapp/model/CourierStat.kt
@@ -4,10 +4,9 @@ @DatabaseView( """ SELECT category as courierName, COUNT(*) as count SELECT type as courierName, COUNT(*) as count FROM Code WHERE substr(createtime, 1, 10) = date('now') GROUP BY category GROUP BY type """ ) data class CourierStat( app/src/main/java/com/example/firstapp/model/DailyStat.kt
@@ -7,11 +7,11 @@ SELECT substr(createtime, 1, 10) as date, COUNT(*) as count FROM code WHERE substr(createtime, 1, 10) = date('now') GROUP BY substr(createtime, 1, 10) """ ) data class DailyStat( val date: String, val count: Int val count: Int, val week_start: String? = null ) app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt
@@ -20,8 +20,10 @@ 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() { @@ -132,53 +134,115 @@ 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) valueFormatter = IndexAxisValueFormatter(getDayLabels()) 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(currentDate.timeInMillis).observe(viewLifecycleOwner) { stats -> 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 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) { 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(true) setUsePercentValues(false) // 改为显示实际数量 setDrawEntryLabels(false) legend.isEnabled = true legend.verticalAlignment = Legend.LegendVerticalAlignment.CENTER legend.horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT legend.orientation = Legend.LegendOrientation.VERTICAL // 增大饼图尺寸 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() @@ -186,16 +250,26 @@ private fun updatePieChartData() { viewModel.getCourierStats(currentDate.timeInMillis).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) resources.getColor(R.color.teal_200), resources.getColor(R.color.purple_200), resources.getColor(R.color.teal_700) ) dataSet.valueTextSize = 14f // 增大数值文字大小 pieChart.data = PieData(dataSet) val pieData = PieData(dataSet) pieData.setValueFormatter(object : ValueFormatter() { override fun getFormattedValue(value: Float): String { return value.toInt().toString() } }) pieChart.data = pieData pieChart.invalidate() } } app/src/main/java/com/example/firstapp/ui/dashboard/DashboardViewModel.kt
@@ -23,7 +23,7 @@ fun getCourierStats(date: Long) = repository.getCourierStats(date).asLiveData() fun getDailyStats(date: Long) = repository.getDailyStats(date).asLiveData() fun getDailyStats() = repository.getDailyStats().asLiveData() fun insert(code: Code) = viewModelScope.launch { repository.insert(code) app/src/main/res/layout/fragment_dashboard.xml
@@ -81,49 +81,57 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp"> android:padding="16dp" android:gravity="center_vertical"> <ImageView android:layout_width="0dp" android:layout_width="48dp" android:layout_height="48dp" android:layout_weight="1" android:src="@drawable/resource_package" /> <TextView android:id="@+id/text_package_count" android:layout_width="0dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="16dp" android:layout_weight="1" android:textSize="24sp" android:textStyle="bold" tools:text="4个" /> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 包裹列表 --> <ViewFlipper android:id="@+id/view_flipper_stats" <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/card_package_stats"> android:layout_height="0dp" android:fillViewport="true" android:clipToPadding="false" app:layout_constraintTop_toBottomOf="@id/card_package_stats" app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="56dp"> <!-- 日视图 --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_packages" <ViewFlipper android:id="@+id/view_flipper_stats" android:layout_width="match_parent" android:layout_height="wrap_content" /> android:layout_height="wrap_content"> <!-- 周视图 --> <include android:id="@+id/layout_week_stats" layout="@layout/layout_week_stats" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- 日视图 --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_packages" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" android:paddingBottom="16dp" /> <!-- 月视图和年视图可以根据需要添加 --> <!-- 周视图 --> <include android:id="@+id/layout_week_stats" layout="@layout/layout_week_stats" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ViewFlipper> </ViewFlipper> </androidx.core.widget.NestedScrollView> </androidx.constraintlayout.widget.ConstraintLayout> app/src/main/res/layout/layout_week_stats.xml
@@ -4,53 +4,25 @@ android:layout_height="wrap_content" android:orientation="vertical"> <!-- 包裹总数统计卡片 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp"> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/resource_package" /> <TextView android:id="@+id/text_total_packages" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="16dp" android:textSize="24sp" android:textStyle="bold" android:text="4个" /> </LinearLayout> </androidx.cardview.widget.CardView> <!-- 每日包裹数量柱状图 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="200dp" android:layout_height="280dp" android:layout_marginHorizontal="16dp" android:layout_marginTop="8dp" android:layout_marginBottom="16dp"> <com.github.mikephil.charting.charts.BarChart android:id="@+id/chart_daily_packages" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp" /> android:padding="16dp" /> </androidx.cardview.widget.CardView> <!-- 快递公司占比饼图 --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="200dp" android:layout_height="280dp" android:layout_marginHorizontal="16dp" android:layout_marginBottom="16dp"> @@ -58,6 +30,6 @@ android:id="@+id/chart_courier_distribution" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp" /> android:padding="16dp" /> </androidx.cardview.widget.CardView> </LinearLayout>