app/src/main/java/com/example/firstapp/activity/SettingActivity.kt
@@ -4,22 +4,19 @@ import android.annotation.SuppressLint import android.app.AlertDialog import android.content.Intent import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.Gravity import android.view.LayoutInflater import android.view.MenuItem import android.view.MotionEvent import android.view.View import android.view.WindowInsets import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.widget.Toolbar import android.widget.Button import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.example.firstapp.databinding.ActivitySettingBinding import com.example.firstapp.R import com.example.firstapp.core.Core import com.example.firstapp.database.service.RetrofitClient import com.example.firstapp.ui.home.HomeViewModel import com.example.firstapp.utils.Log import kotlinx.coroutines.launch /** * An example full-screen activity that shows and hides the system UI (i.e. @@ -66,6 +63,70 @@ // // }) // 退出登录 logout() // 账号注销 accountClose() } private fun accountClose(){ binding.accountClose.setOnClickListener { val dialogView = LayoutInflater.from(this).inflate(R.layout.account_close_dialog_custom, null) val dialog = AlertDialog.Builder(this) .setView(dialogView) .create() dialog.window?.setBackgroundDrawableResource(R.drawable.dialog_background) val btnConfirm = dialogView.findViewById<Button>(R.id.btnConfirm) btnConfirm.setOnClickListener { dialog.dismiss() } val btnCancel = dialogView.findViewById<Button>(R.id.btnCancel) btnCancel.setOnClickListener { // 关闭账户 lifecycleScope.launch { try { // 清除本地的数据库 RetrofitClient.apiService.closeAccount() Core.code.deleteAll() Core.msg.deleteAll() Core.keyword.deleteAll() Core.reminder.deleteAll() dialog.dismiss() // 跳转到 LoginActivity 并清除之前的任务栈 var intent = Intent(this@SettingActivity, LoginActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK startActivity(intent) // 关闭当前页面 finish() } catch (ex: Exception) { Log.e("关闭账户", ex.message ?: "关闭账户报错") } } } dialog.show() } } private fun logout(){ binding.settingExit.setOnClickListener { // 弹出确认退出的对话框 val alertDialog = AlertDialog.Builder(this) @@ -79,7 +140,6 @@ val intent = Intent(this, LoginActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK startActivity(intent) // 关闭当前页面 finish() } @@ -92,9 +152,6 @@ // 显示对话框 alertDialog.show() } } // 点击返回按钮时调用 app/src/main/java/com/example/firstapp/adapter/PackageAdapter.kt
@@ -44,6 +44,10 @@ private val textPickTime: TextView = view.findViewById(R.id.text_pick_time) fun bind(code: Code) { textTime.textSize=10f textPickTime.textSize=10f // imgCourier.setImageResource(code.category) textCourierName.text = code.oneLevel textTrackingNumber.text = code.code @@ -53,7 +57,7 @@ try { val date: Date? = parser.parse(code.createTime) // 解析字符串 date?.let { textTime.text = "到货:"+formatter.format(it) // 格式化并赋值 textTime.text = "到货:"+formatter.format(it) // 格式化并赋值 } ?: run { // 处理解析失败(date 为 null 的情况) textTime.text = "Invalid Date" app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt
@@ -29,6 +29,9 @@ @Query("DELETE FROM Code where id=:id") fun delete(id: Long) @Query("DELETE FROM Code") fun deleteAll(): Completable @Query("SELECT * FROM Code WHERE id = :id LIMIT 1") fun getCodeById(id: Long): Code? @@ -75,10 +78,18 @@ @Query(""" SELECT * FROM code WHERE substr(createTime, 1, 10) = date(:date/1000, 'unixepoch', 'localtime') date(:date/1000, 'unixepoch', 'localtime') ORDER BY createTime DESC """) fun getPackagesByDay(date: Long): Flow<List<Code>> @Query(""" SELECT * FROM code WHERE substr(createTime, 1, 10) = date(:date/1000, 'unixepoch', 'localtime') and pickup = 1 ORDER BY createTime DESC """) fun getPackagesByDayUnread(date: Long): Flow<List<Code>> @Query(""" SELECT oneLevel as courierName, COUNT(*) as count @@ -283,4 +294,50 @@ ORDER BY createTime DESC """) fun getPackagesByTypeAndStation(type: String, stationName: String): List<Code> @Query(""" SELECT COUNT(1) FROM code WHERE date(createTime) BETWEEN date(:startDateCur) AND date(:endDateCur) """) fun getCurrentWeekStats2(startDateCur: String, endDateCur: String): Flow<Long> // @Query(""" // WITH RECURSIVE dates(date_value) AS ( // SELECT date('now', 'weekday 1', '-7 days') // UNION ALL // SELECT date(date_value, '+1 day') // FROM dates // WHERE date_value < date('now', 'weekday 1', '-7 days', '+6 days') // ) // SELECT // strftime('%d', date_value) AS date, // COUNT(c.id) AS count, // '' as weekStart // FROM dates d // LEFT JOIN code c ON date(c.createTime) = d.date_value // GROUP BY d.date_value // ORDER BY d.date_value ASC // // """) @Query(""" WITH RECURSIVE dates(date_value) AS ( SELECT date(:startDateCur) UNION ALL SELECT date(date_value, '+1 day') FROM dates WHERE date_value < date(:endDateCur) ) SELECT strftime('%d', date_value) AS date, COUNT(c.id) AS count, '' AS weekStart FROM dates d LEFT JOIN code c ON date(c.createTime) = d.date_value GROUP BY d.date_value ORDER BY d.date_value ASC """) fun getWeeklyStatsChart(startDateCur: String, endDateCur: String): Flow<List<DailyStat>> } app/src/main/java/com/example/firstapp/database/dao/KeywordDao.kt
@@ -7,6 +7,7 @@ import androidx.room.Update import com.example.firstapp.database.entity.KeywordConfig import com.example.firstapp.database.entity.KeywordEntity import io.reactivex.Completable //@Dao //interface KeywordDao { @@ -34,4 +35,7 @@ @Query("SELECT * FROM keywords") fun getAllKeywords(): List<KeywordEntity> @Query("DELETE FROM keywords") fun deleteAll(): Completable } app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt
@@ -23,4 +23,4 @@ @Query("DELETE FROM reminders") suspend fun deleteAllReminders() } } app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt
@@ -3,6 +3,7 @@ import androidx.annotation.WorkerThread import com.example.firstapp.database.dao.CodeDao import com.example.firstapp.database.entity.Code import com.example.firstapp.model.DailyStat import com.example.firstapp.model.StationGroup import kotlinx.coroutines.flow.Flow @@ -14,6 +15,9 @@ @WorkerThread fun delete(id: Long) = codeDao.delete(id) @WorkerThread fun deleteAll() = codeDao.deleteAll() fun getAll() = codeDao.getAllCodes() @@ -36,6 +40,14 @@ fun getPackages(date: Long, dateType: String): Flow<List<Code>> { return when (dateType) { "DAY" -> codeDao.getPackagesByDay(date) "WEEK" -> codeDao.getPackagesByWeek(date) else -> codeDao.getPackagesByDay(date) } } fun getPackagesUnread(date: Long, dateType: String): Flow<List<Code>> { return when (dateType) { "DAY" -> codeDao.getPackagesByDayUnread(date) "WEEK" -> codeDao.getPackagesByWeek(date) else -> codeDao.getPackagesByDay(date) } @@ -87,4 +99,7 @@ return codeDao.getPackagesByTypeAndStation(type, stationName) } fun getCurrentWeekStats2(startDateCur: String, endDateCur: String) = codeDao.getCurrentWeekStats2(startDateCur,endDateCur) fun getWeeklyStatsChart(startDateCur: String, endDateCur: String): Flow<List<DailyStat>> = codeDao.getWeeklyStatsChart(startDateCur,endDateCur) } app/src/main/java/com/example/firstapp/database/repository/KeywordRepository.kt
@@ -1,5 +1,6 @@ package com.example.firstapp.database.repository import androidx.annotation.WorkerThread import com.example.firstapp.database.dao.KeywordDao import com.example.firstapp.database.entity.KeywordConfig import com.example.firstapp.database.entity.KeywordEntity @@ -39,5 +40,9 @@ keywordDao.insertAll(keywordEntities) } @WorkerThread fun deleteAll() = keywordDao.deleteAll() } app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt
@@ -8,7 +8,7 @@ class ReminderRepository(context: Context) { private val reminderDao: ReminderDao = AppDatabase.getInstance(context).reminderDao() private val reminderDao: ReminderDao = AppDatabase.getInstance(context).reminderDao() fun getAllReminders(): Flow<List<Reminder>> = reminderDao.getAllReminders() suspend fun insertReminder(reminder: Reminder) { @@ -30,4 +30,4 @@ suspend fun deleteAllReminders() { reminderDao.deleteAllReminders() } } } app/src/main/java/com/example/firstapp/database/response/AccountCloseResponse.kt
对比新文件 @@ -0,0 +1,7 @@ package com.example.firstapp.database.response data class AccountCloseResponse( val code: Int, val msg: String, val data: Boolean ) app/src/main/java/com/example/firstapp/database/service/ApiService.kt
@@ -6,6 +6,7 @@ import com.example.firstapp.database.request.ProductOrdersRequest import com.example.firstapp.database.request.SmsLoginRequest import com.example.firstapp.database.request.SmsSendRequest import com.example.firstapp.database.response.AccountCloseResponse import com.example.firstapp.database.response.AlipayOrderInfoResponse import com.example.firstapp.database.response.ContentResponse import com.example.firstapp.database.response.DictResponse @@ -68,6 +69,8 @@ @Part avatar: MultipartBody.Part? ): ApiResponse<Unit> @POST("api/account/close") suspend fun closeAccount(): AccountCloseResponse fun getUserCategories(currentUserId: String): List<CategoryConfig> app/src/main/java/com/example/firstapp/model/DailyStat.kt
@@ -2,6 +2,7 @@ import androidx.room.DatabaseView import androidx.room.ColumnInfo import androidx.room.Ignore @DatabaseView( """ app/src/main/java/com/example/firstapp/model/DailyStat2.kt
对比新文件 @@ -0,0 +1,17 @@ package com.example.firstapp.model import androidx.room.ColumnInfo import androidx.room.DatabaseView @DatabaseView( """ SELECT substr(createTime, 1, 10) as date, COUNT(*) as count FROM code GROUP BY substr(createTime, 1, 10) """ ) data class DailyStat2( val date: String, val count: Int ) app/src/main/java/com/example/firstapp/ui/dashboard/DashboardFragment.kt
@@ -21,17 +21,13 @@ 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() { @@ -45,6 +41,9 @@ private lateinit var pieChart: PieChart private lateinit var heatmapView: View private var currentUserInfo: UserInfo? = null // 确保使用你的实际数据类 private var startDateCur:String = "" private var endDateCur:String = "" enum class DateType { @@ -113,6 +112,10 @@ } 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) binding.tabDateRange.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab?) { currentDateType = when(tab?.position) { @@ -122,6 +125,40 @@ 3 -> DateType.YEAR else -> DateType.DAY } 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() @@ -160,10 +197,13 @@ 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月" @@ -178,10 +218,15 @@ } } private fun setupView(view: View) { val weekStatsView = binding.layoutWeekStats.root barChart = weekStatsView.findViewById(R.id.chart_daily_packages) 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 @@ -190,6 +235,7 @@ setupPieChart() setupHeatmap() updateCharts() } private fun setupBarChart() { barChart.apply { @@ -240,7 +286,8 @@ private fun updateBarChartData() { val statsFlow = when (currentDateType) { DateType.WEEK -> { viewModel.getWeeklyStats(currentDate.timeInMillis, 6) // viewModel.getWeeklyStats(currentDate.timeInMillis, 6) viewModel.getWeeklyStatsChart(startDateCur,endDateCur) } DateType.MONTH -> { viewModel.getYearMonthlyStats(currentDate.timeInMillis) @@ -416,14 +463,26 @@ when (currentDateType) { DateType.DAY -> { binding.textPackageCount.text = "${packages.size}个" // 获取本周统计 viewModel.getPackagesUnread(currentDate.timeInMillis, currentDateType.name) .observe(viewLifecycleOwner) { unpackages-> // 只读取未取件的包裹 packageAdapter.updatePackages(unpackages) } } DateType.WEEK -> { // 获取本周统计 viewModel.getCurrentWeekStats(currentDate.timeInMillis) .observe(viewLifecycleOwner) { stats -> val weekTotal = stats.sumOf { it.count } binding.textPackageCount.text = "${weekTotal}个" } 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 -> { // 获取本月统计 @@ -442,8 +501,8 @@ } } } packageAdapter.updatePackages(packages) packageAdapter.updatePackages(packages) // packageAdapter.updatePackages(packages) // binding.textPackageCount.text = "${packages.size}个" } } app/src/main/java/com/example/firstapp/ui/dashboard/DashboardViewModel.kt
@@ -4,7 +4,6 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import androidx.room.RewriteQueriesToDropUnusedColumns import com.example.firstapp.AppDatabase import com.example.firstapp.database.entity.Code import com.example.firstapp.database.repository.CodeRepository @@ -21,6 +20,9 @@ fun getPackages(date: Long, dateType: String) = repository.getPackages(date, dateType).asLiveData() fun getPackagesUnread(date: Long, dateType: String) = repository.getPackagesUnread(date, dateType).asLiveData() fun getCourierStats(date: Long, dateType: String) = repository.getCourierStats(date, dateType).asLiveData() @@ -47,4 +49,7 @@ fun getCurrentYearStats(date: Long) = repository.getCurrentYearStats(date).asLiveData() fun getCurrentWeekStats2(startDateCur: String, endDateCur: String) = repository.getCurrentWeekStats2(startDateCur,endDateCur).asLiveData() fun getWeeklyStatsChart(startDateCur: String, endDateCur: String) = repository.getWeeklyStatsChart(startDateCur, endDateCur).asLiveData() } app/src/main/res/drawable/border_button.xml
对比新文件 @@ -0,0 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 边框颜色和宽度 --> <stroke android:color="#000000" android:width="2dp" /> <!-- 边框宽度 --> <!-- 背景颜色 --> <solid android:color="@android:color/transparent" /> <!-- 设置透明背景 --> <!-- 圆角半径 --> <corners android:radius="200dp" /> <!-- 设置圆角半径,调整数值来控制圆角的大小 --> </shape> app/src/main/res/layout/account_close_dialog_custom.xml
对比新文件 @@ -0,0 +1,87 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/dialog_background" android:padding="20dp" android:gravity="center" > <!-- 标题 --> <TextView android:id="@+id/dialogTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="确定注销账号吗?" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:paddingBottom="10dp" /> <View android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1dp" android:background="#E2E2E2" android:layout_marginTop="5dp" android:layout_marginHorizontal="0dp" /> <!-- 内容 --> <TextView android:id="@+id/dialogMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="注销账号后,此账号的所有数据将被清空且不可恢复!" android:textSize="16sp" android:textColor="#000000" android:gravity="left" android:layout_marginTop="5dp" android:paddingBottom="20dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center" android:padding="16dp" > <!-- 同意按钮 --> <Button android:id="@+id/btnConfirm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="我在想想" android:textColor="@android:color/white" android:backgroundTint="#000000" android:gravity="center" /> <!-- 不同意按钮 --> <Button android:id="@+id/btnCancel" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" android:text="确定注销" android:textColor="#999999" android:background="@drawable/border_button" android:gravity="center" android:elevation="0dp" android:drawableLeft="@null" /> <!-- 确保没有图标 --> </LinearLayout> </LinearLayout> app/src/main/res/layout/activity_setting.xml
@@ -34,6 +34,23 @@ </androidx.appcompat.widget.Toolbar> <LinearLayout android:id="@+id/account_close" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:orientation="vertical" android:background="#F9F9F9" android:layout_marginTop="1dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="账号注销" android:textColor="#000000" /> </LinearLayout> <LinearLayout android:id="@+id/setting_exit" app/src/main/res/layout/fragment_dashboard.xml
@@ -68,6 +68,22 @@ </LinearLayout> <!-- 包裹统计卡片 --> <LinearLayout android:id="@+id/card_package_stats_title" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/layout_date_picker" > <TextView android:id="@+id/card_package_stats_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="本日收到包裹总数 ->" android:layout_marginLeft="16dp" > </TextView> </LinearLayout> <androidx.cardview.widget.CardView android:id="@+id/card_package_stats" android:layout_width="match_parent" @@ -75,7 +91,7 @@ android:layout_margin="16dp" app:cardCornerRadius="8dp" app:cardElevation="4dp" app:layout_constraintTop_toBottomOf="@id/layout_date_picker"> app:layout_constraintTop_toBottomOf="@id/card_package_stats_title"> <LinearLayout android:layout_width="match_parent" @@ -119,6 +135,7 @@ </LinearLayout> </androidx.cardview.widget.CardView> <!-- 年度统计布局 --> <include android:id="@+id/layout_year_stats" @@ -136,27 +153,68 @@ app:layout_constraintTop_toBottomOf="@id/layout_year_stats" app:layout_constraintBottom_toBottomOf="parent"> <ViewFlipper android:id="@+id/view_flipper_stats" <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- 日视图 --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_packages" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" android:paddingBottom="16dp" /> android:layout_height="wrap_content"> <ViewFlipper android:id="@+id/view_flipper_stats" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 周视图 --> <include android:id="@+id/layout_week_stats" layout="@layout/layout_week_stats" <!-- 日视图 --> <LinearLayout android:id="@+id/recycler_packages_11" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:id="@+id/layout_year_stats_title" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/card_package_stats" > <TextView android:id="@+id/layout_year_stats_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="包裹取件码记录 ->" android:layout_margin="16dp" > </TextView> </LinearLayout> <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" /> </LinearLayout> <!-- 周视图 --> <include android:id="@+id/layout_week_stats" layout="@layout/layout_week_stats" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ViewFlipper> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" /> android:layout_height="80dp" /> </ViewFlipper> </LinearLayout> </androidx.core.widget.NestedScrollView> <!-- 🔹 遮罩层 --> app/src/main/res/layout/fragment_dashboard0411.xml
对比新文件 @@ -0,0 +1,262 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.dashboard.DashboardFragment"> <!-- 时间范围选择器 --> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_date_range" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent"> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="天" /> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="周" /> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="月" /> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="年" /> </com.google.android.material.tabs.TabLayout> <!-- 日期选择器 --> <LinearLayout android:id="@+id/layout_date_picker" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp" app:layout_constraintTop_toBottomOf="@id/tab_date_range"> <ImageButton android:id="@+id/btn_previous_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:src="@android:drawable/ic_media_previous" /> <TextView android:id="@+id/text_current_date" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="16sp" tools:text="2025年1月14日" /> <ImageButton android:id="@+id/btn_next_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:src="@android:drawable/ic_media_next" /> </LinearLayout> <!-- 包裹统计卡片 --> <LinearLayout android:id="@+id/card_package_stats_title" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/layout_date_picker" > <TextView android:id="@+id/card_package_stats_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="本日收到包裹总数 ->" android:layout_marginLeft="16dp" > </TextView> </LinearLayout> <androidx.cardview.widget.CardView android:id="@+id/card_package_stats" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="16dp" app:cardCornerRadius="8dp" app:cardElevation="4dp" app:layout_constraintTop_toBottomOf="@id/card_package_stats_title"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp" android:weightSum="3"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center"> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:src="@drawable/resource_package" /> </LinearLayout> <Space android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center"> <TextView android:id="@+id/text_package_count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:textStyle="bold" tools:text="4个" /> </LinearLayout> </LinearLayout> </androidx.cardview.widget.CardView> <LinearLayout android:id="@+id/layout_year_stats_title" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/card_package_stats" > <TextView android:id="@+id/layout_year_stats_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="包裹取件码记录 ->" android:layout_margin="16dp" > </TextView> </LinearLayout> <!-- 年度统计布局 --> <include android:id="@+id/layout_year_stats" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/layout_year_stats_title" layout="@layout/layout_year_stats" /> <!-- 包裹列表和统计图表 --> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="0dp" android:fillViewport="true" app:layout_constraintTop_toBottomOf="@id/layout_year_stats" app:layout_constraintBottom_toBottomOf="parent"> <ViewFlipper android:id="@+id/view_flipper_stats" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 日视图 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout 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" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp"> </LinearLayout> </LinearLayout> <!-- 周视图 --> <include android:id="@+id/layout_week_stats" layout="@layout/layout_week_stats" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ViewFlipper> </androidx.core.widget.NestedScrollView> <!-- 🔹 遮罩层 --> <View android:id="@+id/view_overlay" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/overlay2" android:elevation="10dp" android:visibility="gone" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> <!-- 🔹 遮罩层上的按钮 --> <!-- 🔹 遮罩层上的内容容器(LinearLayout) --> <LinearLayout android:id="@+id/overlay_content" android:layout_width="300dp" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:padding="10dp" android:background="@drawable/overlay_black_background" android:elevation="20dp" android:translationZ="20dp" android:visibility="gone" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"> <ImageView android:id="@+id/overlay_content_vip_image" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:scaleType="centerCrop" android:src="@mipmap/vip_crown" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- 🔹 示例内容:标题 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="免费查看统计数据" android:textSize="18sp" android:textColor="#EEBC93" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> app/src/main/res/layout/item_package_dashboard.xml
@@ -31,7 +31,7 @@ <TextView android:id="@+id/text_courier_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="25dp" android:textSize="16sp" android:textStyle="bold" tools:text="某快递" /> @@ -42,7 +42,7 @@ android:layout_height="wrap_content" android:layout_marginTop="4dp" android:textColor="@android:color/darker_gray" android:textSize="12sp" android:textSize="8sp" tools:text="2025-01-14 10:30" /> </LinearLayout> @@ -54,7 +54,7 @@ <TextView android:id="@+id/text_tracking_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_height="25dp" android:textColor="@android:color/darker_gray" android:layout_gravity="end" tools:text="14-6-7023" /> @@ -66,7 +66,7 @@ android:layout_marginTop="4dp" android:textColor="@android:color/darker_gray" android:layout_gravity="end" android:textSize="12sp" android:textSize="8sp" tools:text="2025-01-15 11:30" /> </LinearLayout> app/src/main/res/layout/layout_week_stats.xml
@@ -4,19 +4,37 @@ android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/bar_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="本周包裹物流公司分布 ->" android:layout_margin="16dp" > </TextView> </LinearLayout> <!-- 柱状图容器,内边距16dp --> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="280dp" android:layout_marginHorizontal="16dp" android:layout_marginTop="8dp" android:layout_marginBottom="16dp"> android:layout_marginBottom="16dp" android:padding="100dp" > <com.github.mikephil.charting.charts.BarChart android:id="@+id/chart_daily_packages" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" /> android:layout_height="wrap_content" android:padding="50dp" /> </androidx.cardview.widget.CardView> <!-- 热力图容器 --> @@ -41,6 +59,21 @@ </HorizontalScrollView> </androidx.cardview.widget.CardView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/pie_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="本周包裹物流公司分布 ->" android:layout_margin="16dp" > </TextView> </LinearLayout> <!-- 饼图容器 --> <androidx.cardview.widget.CardView android:layout_width="match_parent"