diff --git a/app/src/main/java/com/yovinchen/bookkeeping/MainActivity.kt b/app/src/main/java/com/yovinchen/bookkeeping/MainActivity.kt index 419c442..d14c0f7 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/MainActivity.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/MainActivity.kt @@ -24,40 +24,66 @@ import com.yovinchen.bookkeeping.ui.navigation.MainNavigation import com.yovinchen.bookkeeping.ui.theme.BookkeepingTheme import com.yovinchen.bookkeeping.utils.FilePickerUtil +/** + * 全局文件选择器启动器 + * 用于在整个应用程序中共享同一个文件选择器实例 + */ private var filePickerLauncher: ActivityResultLauncher>? = null +/** + * 获取预先注册的文件选择器启动器的扩展函数 + * + * @return 预先注册的文件选择器启动器 + * @throws IllegalStateException 如果文件选择器未初始化 + */ fun ComponentActivity.getPreregisteredFilePickerLauncher(): ActivityResultLauncher> { return filePickerLauncher ?: throw IllegalStateException("FilePickerLauncher not initialized") } +/** + * 应用程序的主活动 + * 负责初始化应用界面和必要的系统组件 + */ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // 设置系统窗口装饰,确保内容能够扩展到系统栏区域 WindowCompat.setDecorFitsSystemWindows(window, false) - // 预注册文件选择器 + // 预注册文件选择器,用于处理文件选择操作 filePickerLauncher = registerForActivityResult( ActivityResultContracts.OpenDocument() ) { uri: Uri? -> + // 当用户选择文件后,调用工具类处理文件选择结果 FilePickerUtil.handleFileSelection(this, uri) } + // 设置应用的主Compose内容 setContent { BookkeepingApp() } } } +/** + * 系统状态栏和导航栏颜色设置 + * 根据当前主题模式设置系统UI元素的颜色和外观 + * + * @param isDarkTheme 是否为暗色主题 + */ @Composable private fun SystemBarColor(isDarkTheme: Boolean) { val view = LocalView.current if (!view.isInEditMode) { + // 获取当前主题的表面颜色用于系统栏 val surfaceColor = MaterialTheme.colorScheme.surface.toArgb() val currentWindow = (view.context as? Activity)?.window SideEffect { currentWindow?.let { window -> + // 设置状态栏和导航栏颜色 window.statusBarColor = surfaceColor window.navigationBarColor = surfaceColor + // 设置系统栏图标的亮暗模式,以确保在不同背景下的可见性 WindowCompat.getInsetsController(window, view).apply { isAppearanceLightStatusBars = !isDarkTheme isAppearanceLightNavigationBars = !isDarkTheme @@ -67,27 +93,37 @@ private fun SystemBarColor(isDarkTheme: Boolean) { } } +/** + * 记账应用的主Compose函数 + * 处理主题设置并启动主导航组件 + */ @Composable fun BookkeepingApp() { + // 跟踪当前应用的主题模式状态 var themeMode by remember { mutableStateOf(ThemeMode.FOLLOW_SYSTEM) } + // 根据主题模式确定是否使用暗色主题 val isDarkTheme = when (themeMode) { - is ThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme() - is ThemeMode.LIGHT -> false - is ThemeMode.DARK -> true - is ThemeMode.CUSTOM -> isSystemInDarkTheme() + is ThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme() // 跟随系统设置 + is ThemeMode.LIGHT -> false // 强制使用亮色主题 + is ThemeMode.DARK -> true // 强制使用暗色主题 + is ThemeMode.CUSTOM -> isSystemInDarkTheme() // 自定义主题下的基础亮暗模式仍跟随系统 } + // 处理自定义主题颜色方案 val customColorScheme = when (themeMode) { is ThemeMode.CUSTOM -> { + // 从主题模式中提取自定义主色 val primaryColor = (themeMode as ThemeMode.CUSTOM).primaryColor if (isDarkTheme) { + // 暗色模式下的自定义颜色方案 MaterialTheme.colorScheme.copy( primary = primaryColor, secondary = primaryColor.copy(alpha = 0.7f), tertiary = primaryColor.copy(alpha = 0.5f) ) } else { + // 亮色模式下的自定义颜色方案 MaterialTheme.colorScheme.copy( primary = primaryColor, secondary = primaryColor.copy(alpha = 0.7f), @@ -95,27 +131,38 @@ fun BookkeepingApp() { ) } } - else -> null + else -> null // 非自定义主题模式使用默认颜色方案 } + // 应用主题到整个应用内容 BookkeepingTheme( darkTheme = isDarkTheme, customColorScheme = customColorScheme ) { + // 设置系统状态栏和导航栏颜色 SystemBarColor(isDarkTheme) + // 创建填充整个屏幕的基础Surface Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface ) { + // 启动主导航组件,并传递主题相关参数 MainNavigation( currentTheme = themeMode, - onThemeChange = { themeMode = it } + onThemeChange = { themeMode = it } // 允许导航组件中的屏幕更改主题 ) } } } +/** + * 示例问候函数 + * 仅用于开发预览和测试目的 + * + * @param name 要显示的名称 + * @param modifier 应用于Text组件的修饰符 + */ @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( @@ -124,6 +171,9 @@ fun Greeting(name: String, modifier: Modifier = Modifier) { ) } +/** + * Greeting组件的预览函数 + */ @Preview(showBackground = true) @Composable fun GreetingPreview() { @@ -132,6 +182,9 @@ fun GreetingPreview() { } } +/** + * 整个应用的预览函数 + */ @Preview(showBackground = true) @Composable fun BookkeepingAppPreview() { diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/AnalysisType.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/AnalysisType.kt index 1220cd3..e7342d5 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/AnalysisType.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/AnalysisType.kt @@ -1,7 +1,13 @@ package com.yovinchen.bookkeeping.model +/** + * 分析类型枚举 + * 定义记账应用中不同的数据分析视图类型 + * + * 用于在数据分析模块中区分不同的分析维度和图表类型 + */ enum class AnalysisType { - EXPENSE, - INCOME, - TREND + EXPENSE, // 支出分析,用于分析用户的支出情况 + INCOME, // 收入分析,用于分析用户的收入情况 + TREND // 趋势分析,用于分析用户收支随时间的变化趋势 } diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/BookkeepingRecord.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/BookkeepingRecord.kt index 5ec3bd4..37d7a5e 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/BookkeepingRecord.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/BookkeepingRecord.kt @@ -9,32 +9,71 @@ import androidx.room.TypeConverters import com.yovinchen.bookkeeping.model.Member import java.util.Date +/** + * 交易类型枚举 + * 定义记账记录的交易类型 + */ enum class TransactionType { - INCOME, EXPENSE + INCOME, // 收入 + EXPENSE // 支出 } +/** + * Room数据库类型转换器 + * 用于在数据库中存储和检索复杂类型 + */ class Converters { + /** + * 将时间戳转换为Date对象 + * + * @param value 时间戳(毫秒) + * @return 对应的Date对象,如果输入为null则返回null + */ @TypeConverter fun fromTimestamp(value: Long?): Date? { return value?.let { Date(it) } } + /** + * 将Date对象转换为时间戳 + * + * @param date Date对象 + * @return 对应的时间戳(毫秒),如果输入为null则返回null + */ @TypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time } + /** + * 将字符串转换为TransactionType枚举 + * + * @param value 交易类型的字符串表示 + * @return 对应的TransactionType枚举值 + */ @TypeConverter fun fromTransactionType(value: String): TransactionType { return enumValueOf(value) } + /** + * 将TransactionType枚举转换为字符串 + * + * @param type TransactionType枚举值 + * @return 对应的字符串表示 + */ @TypeConverter fun transactionTypeToString(type: TransactionType): String { return type.name } } +/** + * 记账记录实体类 + * 用于在Room数据库中存储用户的收支记录 + * + * 该实体与Member实体存在外键关系,表示每条记录可以关联到一个家庭成员 + */ @Entity( tableName = "bookkeeping_records", foreignKeys = [ @@ -42,21 +81,21 @@ class Converters { entity = Member::class, parentColumns = ["id"], childColumns = ["memberId"], - onDelete = ForeignKey.SET_NULL + onDelete = ForeignKey.SET_NULL // 当关联的成员被删除时,将此字段设为NULL ) ], indices = [ - Index(value = ["memberId"]) + Index(value = ["memberId"]) // 在memberId上创建索引以提高查询性能 ] ) -@TypeConverters(Converters::class) +@TypeConverters(Converters::class) // 应用类型转换器 data class BookkeepingRecord( @PrimaryKey(autoGenerate = true) - val id: Long = 0, - val amount: Double, - val type: TransactionType, - val category: String, - val description: String, - val date: Date, - val memberId: Int? = null // 可为空,表示未指定成员 + val id: Long = 0, // 记录ID,自动生成 + val amount: Double, // 金额 + val type: TransactionType, // 交易类型(收入或支出) + val category: String, // 分类 + val description: String, // 描述 + val date: Date, // 日期 + val memberId: Int? = null // 关联的成员ID,可为空表示未指定成员 ) diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/Category.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/Category.kt index 1fa83c3..8b72d22 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/Category.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/Category.kt @@ -3,11 +3,18 @@ package com.yovinchen.bookkeeping.model import androidx.room.Entity import androidx.room.PrimaryKey +/** + * 交易分类实体类 + * 用于在Room数据库中存储收支分类信息 + * + * 在记账应用中,每条记账记录都属于某个分类, + * 如"餐饮"、"交通"、"工资"等,便于用户对支出和收入进行分类统计 + */ @Entity(tableName = "categories") data class Category( @PrimaryKey(autoGenerate = true) - val id: Long = 0, - val name: String, - val type: TransactionType, - val icon: Int? = null + val id: Long = 0, // 分类ID,自动生成 + val name: String, // 分类名称 + val type: TransactionType, // 分类关联的交易类型(收入或支出) + val icon: Int? = null // 分类图标资源ID,可选,默认为null ) diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/CategoryStat.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/CategoryStat.kt index 0411e50..70434cc 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/CategoryStat.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/CategoryStat.kt @@ -1,8 +1,14 @@ package com.yovinchen.bookkeeping.model +/** + * 分类统计数据类 + * 用于表示某个分类的统计信息,通常用于数据分析和图表展示 + * + * 该类不是数据库实体,而是从数据库查询结果中聚合生成的统计数据 + */ data class CategoryStat( - val category: String, - val amount: Double, - val count: Int = 0, - val percentage: Double = 0.0 + val category: String, // 分类名称 + val amount: Double, // 该分类的总金额 + val count: Int = 0, // 该分类下的记录数量 + val percentage: Double = 0.0 // 该分类金额占总金额的百分比(0.0-100.0) ) diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/Member.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/Member.kt index 08179b7..601727b 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/Member.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/Member.kt @@ -3,11 +3,18 @@ package com.yovinchen.bookkeeping.model import androidx.room.Entity import androidx.room.PrimaryKey +/** + * 家庭成员实体类 + * 用于在Room数据库中存储家庭成员信息 + * + * 在记账应用中,每条记账记录可以关联到特定的家庭成员, + * 以便追踪不同成员的收支情况 + */ @Entity(tableName = "members") data class Member( @PrimaryKey(autoGenerate = true) - val id: Int = 0, - val name: String, - val description: String = "", // 可选的描述信息 - val icon: Int? = null // 新增icon字段,可为空 + val id: Int = 0, // 成员ID,自动生成 + val name: String, // 成员姓名 + val description: String = "", // 成员描述信息,可选,默认为空字符串 + val icon: Int? = null // 成员图标资源ID,可选,默认为null ) diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/MemberStat.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/MemberStat.kt index 3c8be05..9f8bfae 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/MemberStat.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/MemberStat.kt @@ -2,16 +2,39 @@ package com.yovinchen.bookkeeping.model import androidx.room.ColumnInfo +/** + * 家庭成员统计数据类 + * 用于表示某个成员的统计信息,通常用于数据分析和图表展示 + * + * 该类不是数据库实体,而是通过数据库查询直接映射的结果类, + * 表示按成员分组的聚合数据 + */ data class MemberStat( + /** + * 成员名称 + * 映射数据库查询结果中的member列 + */ @ColumnInfo(name = "member") val member: String, + /** + * 该成员的总金额 + * 映射数据库查询结果中的amount列 + */ @ColumnInfo(name = "amount") val amount: Double, + /** + * 该成员下的记录数量 + * 映射数据库查询结果中的count列 + */ @ColumnInfo(name = "count") val count: Int, + /** + * 该成员金额占总金额的百分比(0.0-100.0) + * 映射数据库查询结果中的percentage列 + */ @ColumnInfo(name = "percentage") val percentage: Double = 0.0 ) diff --git a/app/src/main/java/com/yovinchen/bookkeeping/model/ThemeMode.kt b/app/src/main/java/com/yovinchen/bookkeeping/model/ThemeMode.kt index c3aeb5b..d8be10b 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/model/ThemeMode.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/model/ThemeMode.kt @@ -2,9 +2,35 @@ package com.yovinchen.bookkeeping.model import androidx.compose.ui.graphics.Color +/** + * 主题模式密封类 + * 用于表示应用程序的不同主题设置选项 + * 通过密封类实现,限制可能的主题模式类型 + */ sealed class ThemeMode { + /** + * 跟随系统主题模式 + * 应用将根据设备系统的暗色/亮色主题设置自动调整 + */ object FOLLOW_SYSTEM : ThemeMode() + + /** + * 固定亮色主题模式 + * 无论设备系统设置如何,应用将始终使用亮色主题 + */ object LIGHT : ThemeMode() + + /** + * 固定暗色主题模式 + * 无论设备系统设置如何,应用将始终使用暗色主题 + */ object DARK : ThemeMode() + + /** + * 自定义主题模式 + * 允许用户选择自定义的主题颜色 + * + * @property primaryColor 用户选择的主要颜色,将影响应用的主色调 + */ data class CUSTOM(val primaryColor: Color) : ThemeMode() } diff --git a/app/src/main/java/com/yovinchen/bookkeeping/ui/screen/HomeScreen.kt b/app/src/main/java/com/yovinchen/bookkeeping/ui/screen/HomeScreen.kt index 2779013..786675c 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/ui/screen/HomeScreen.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/ui/screen/HomeScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState diff --git a/app/src/main/java/com/yovinchen/bookkeeping/utils/FilePickerUtil.kt b/app/src/main/java/com/yovinchen/bookkeeping/utils/FilePickerUtil.kt index 70e0bd8..59493e6 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/utils/FilePickerUtil.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/utils/FilePickerUtil.kt @@ -10,40 +10,72 @@ import com.yovinchen.bookkeeping.getPreregisteredFilePickerLauncher import java.io.File import java.io.FileOutputStream +/** + * 文件选择器工具类 + * 用于处理文件选择、权限获取和文件处理的工具类 + * + * 主要功能: + * 1. 启动系统文件选择器 + * 2. 处理选择结果 + * 3. 将选择的文件复制到应用缓存目录 + * 4. 文件类型验证 + */ object FilePickerUtil { + /** + * 当前活跃的文件选择回调 + * 用于在文件选择完成后调用 + */ private var currentCallback: ((File) -> Unit)? = null + /** + * 启动文件选择器 + * + * @param activity 当前活动,用于启动文件选择器 + * @param onFileSelected 文件选择完成后的回调函数,参数为选中的文件 + */ fun startFilePicker(activity: ComponentActivity, onFileSelected: (File) -> Unit) { currentCallback = onFileSelected try { + // 设置可选择的文件类型,限制为CSV和Excel文件 val mimeTypes = arrayOf( "text/csv", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel" ) + // 使用预注册的文件选择器启动文件选择流程 activity.getPreregisteredFilePickerLauncher().launch(mimeTypes) } catch (e: Exception) { + // 文件选择器启动失败时显示错误提示 Toast.makeText(activity, "无法启动文件选择器:${e.message}", Toast.LENGTH_SHORT).show() currentCallback = null } } + /** + * 处理文件选择结果 + * + * @param context 上下文对象,用于访问ContentResolver + * @param uri 选中文件的URI,如果用户取消选择则为null + */ fun handleFileSelection(context: Context, uri: Uri?) { if (uri == null) { + // 用户未选择文件时显示提示 Toast.makeText(context, "未选择文件", Toast.LENGTH_SHORT).show() currentCallback = null return } try { + // 获取文件MIME类型 val mimeType = context.contentResolver.getType(uri) + // 验证文件类型是否合法 if (!isValidFileType(uri.toString(), mimeType)) { Toast.makeText(context, "请选择CSV或Excel文件", Toast.LENGTH_SHORT).show() return } - // 获取持久性权限 + // 获取持久性权限,确保应用在重启后仍能访问该文件 val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION context.contentResolver.takePersistableUriPermission(uri, takeFlags) @@ -51,6 +83,7 @@ object FilePickerUtil { // 将选中的文件复制到应用私有目录 val tempFile = copyUriToTempFile(context, uri) if (tempFile != null) { + // 调用回调函数,传递临时文件 currentCallback?.invoke(tempFile) } else { Toast.makeText(context, "文件处理失败,请重试", Toast.LENGTH_SHORT).show() @@ -59,10 +92,18 @@ object FilePickerUtil { e.printStackTrace() Toast.makeText(context, "文件处理出错:${e.message}", Toast.LENGTH_SHORT).show() } finally { + // 清除回调引用,避免内存泄漏 currentCallback = null } } + /** + * 验证文件类型是否合法 + * + * @param fileName 文件名,用于检查文件扩展名 + * @param mimeType 文件MIME类型 + * @return 如果文件类型合法则返回true,否则返回false + */ private fun isValidFileType(fileName: String, mimeType: String?): Boolean { val fileExtension = fileName.lowercase() return fileExtension.endsWith(".csv") || @@ -73,11 +114,20 @@ object FilePickerUtil { mimeType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" } + /** + * 将URI指向的文件复制到应用缓存目录 + * + * @param context 上下文对象,用于访问ContentResolver和缓存目录 + * @param uri 要复制的文件URI + * @return 复制后的临时文件,如果复制失败则返回null + */ private fun copyUriToTempFile(context: Context, uri: Uri): File? { return try { + // 获取文件名,如果无法获取则使用时间戳作为文件名 val fileName = getFileName(context, uri) ?: "temp_backup_${System.currentTimeMillis()}" val tempFile = File(context.cacheDir, fileName) + // 从URI读取内容并写入临时文件 context.contentResolver.openInputStream(uri)?.use { inputStream -> FileOutputStream(tempFile).use { outputStream -> inputStream.copyTo(outputStream) @@ -90,6 +140,13 @@ object FilePickerUtil { } } + /** + * 从URI中获取文件名 + * + * @param context 上下文对象,用于访问ContentResolver + * @param uri 文件URI + * @return 文件名,如果无法获取则返回null + */ private fun getFileName(context: Context, uri: Uri): String? { var fileName: String? = null context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> diff --git a/app/src/main/java/com/yovinchen/bookkeeping/utils/IconManager.kt b/app/src/main/java/com/yovinchen/bookkeeping/utils/IconManager.kt index 1f6636d..6ad7d42 100644 --- a/app/src/main/java/com/yovinchen/bookkeeping/utils/IconManager.kt +++ b/app/src/main/java/com/yovinchen/bookkeeping/utils/IconManager.kt @@ -6,77 +6,126 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource import com.yovinchen.bookkeeping.R +/** + * 图标管理器 + * 集中管理应用中使用的各类图标资源 + * + * 主要功能: + * 1. 管理分类图标和成员图标的映射关系 + * 2. 提供根据名称获取对应图标的方法 + * 3. 提供获取所有可用图标的方法 + */ object IconManager { - // 类别图标映射 + /** + * 类别图标映射 + * 将分类名称映射到对应的图标资源ID + */ private val categoryIcons = mapOf( - "餐饮" to R.drawable.ic_category_food_24dp, - "交通" to R.drawable.ic_category_taxi_24dp, - "购物" to R.drawable.ic_category_supermarket_24dp, - "娱乐" to R.drawable.ic_category_bar_24dp, - "居住" to R.drawable.ic_category_hotel_24dp, - "医疗" to R.drawable.ic_category_medicine_24dp, - "教育" to R.drawable.ic_category_training_24dp, - "宠物" to R.drawable.ic_category_pet_24dp, - "鲜花" to R.drawable.ic_category_flower_24dp, - "外卖" to R.drawable.ic_category_delivery_24dp, - "数码" to R.drawable.ic_category_digital_24dp, - "化妆品" to R.drawable.ic_category_cosmetics_24dp, - "水果" to R.drawable.ic_category_fruit_24dp, - "零食" to R.drawable.ic_category_snack_24dp, - "蔬菜" to R.drawable.ic_category_vegetable_24dp, - "工资" to R.drawable.ic_category_membership_24dp, - "礼物" to R.drawable.ic_category_gift_24dp, - "其他" to R.drawable.ic_category_more_24dp, - "工资" to R.drawable.ic_category_membership_24dp, - "会员" to R.drawable.ic_category_membership_24dp, - "奖金" to R.drawable.ic_category_gift_24dp, - "投资" to R.drawable.ic_category_digital_24dp, - "其他" to R.drawable.ic_category_more_24dp + "餐饮" to R.drawable.ic_category_food_24dp, // 餐饮类别对应食物图标 + "交通" to R.drawable.ic_category_taxi_24dp, // 交通类别对应出租车图标 + "购物" to R.drawable.ic_category_supermarket_24dp, // 购物类别对应超市图标 + "娱乐" to R.drawable.ic_category_bar_24dp, // 娱乐类别对应酒吧图标 + "居住" to R.drawable.ic_category_hotel_24dp, // 居住类别对应酒店图标 + "医疗" to R.drawable.ic_category_medicine_24dp, // 医疗类别对应药品图标 + "教育" to R.drawable.ic_category_training_24dp, // 教育类别对应培训图标 + "宠物" to R.drawable.ic_category_pet_24dp, // 宠物类别对应宠物图标 + "鲜花" to R.drawable.ic_category_flower_24dp, // 鲜花类别对应花图标 + "外卖" to R.drawable.ic_category_delivery_24dp, // 外卖类别对应外卖图标 + "数码" to R.drawable.ic_category_digital_24dp, // 数码类别对应数码产品图标 + "化妆品" to R.drawable.ic_category_cosmetics_24dp, // 化妆品类别对应化妆品图标 + "水果" to R.drawable.ic_category_fruit_24dp, // 水果类别对应水果图标 + "零食" to R.drawable.ic_category_snack_24dp, // 零食类别对应零食图标 + "蔬菜" to R.drawable.ic_category_vegetable_24dp, // 蔬菜类别对应蔬菜图标 + "工资" to R.drawable.ic_category_membership_24dp, // 工资类别对应会员图标 + "礼物" to R.drawable.ic_category_gift_24dp, // 礼物类别对应礼物图标 + "其他" to R.drawable.ic_category_more_24dp, // 其他类别对应更多图标 + "会员" to R.drawable.ic_category_membership_24dp, // 会员类别对应会员图标 + "奖金" to R.drawable.ic_category_gift_24dp, // 奖金类别对应礼物图标 + "投资" to R.drawable.ic_category_digital_24dp // 投资类别对应数码图标 ) - // 成员图标映射 + /** + * 成员图标映射 + * 将成员角色名称映射到对应的图标资源ID + */ private val memberIcons = mapOf( - "自己" to R.drawable.ic_member_boy_24dp, - "老婆" to R.drawable.ic_member_bride_24dp, - "老公" to R.drawable.ic_member_groom_24dp, - "家庭" to R.drawable.ic_member_family_24dp, - "儿子" to R.drawable.ic_member_baby_boy_24dp, - "女儿" to R.drawable.ic_member_baby_girl_24dp, - "爸爸" to R.drawable.ic_member_father_24dp, - "妈妈" to R.drawable.ic_member_mother_24dp, - "爷爷" to R.drawable.ic_member_grandfather_24dp, - "奶奶" to R.drawable.ic_member_grandmother_24dp, - "男生" to R.drawable.ic_member_boy_24dp, - "女生" to R.drawable.ic_member_girl_24dp, - "外公" to R.drawable.ic_member_grandfather_24dp, - "外婆" to R.drawable.ic_member_grandmother_24dp, - "其他" to R.drawable.ic_member_girl_24dp + "自己" to R.drawable.ic_member_boy_24dp, // 自己对应男孩图标 + "老婆" to R.drawable.ic_member_bride_24dp, // 老婆对应新娘图标 + "老公" to R.drawable.ic_member_groom_24dp, // 老公对应新郎图标 + "家庭" to R.drawable.ic_member_family_24dp, // 家庭对应家庭图标 + "儿子" to R.drawable.ic_member_baby_boy_24dp, // 儿子对应男婴图标 + "女儿" to R.drawable.ic_member_baby_girl_24dp, // 女儿对应女婴图标 + "爸爸" to R.drawable.ic_member_father_24dp, // 爸爸对应父亲图标 + "妈妈" to R.drawable.ic_member_mother_24dp, // 妈妈对应母亲图标 + "爷爷" to R.drawable.ic_member_grandfather_24dp, // 爷爷对应祖父图标 + "奶奶" to R.drawable.ic_member_grandmother_24dp, // 奶奶对应祖母图标 + "男生" to R.drawable.ic_member_boy_24dp, // 男生对应男孩图标 + "女生" to R.drawable.ic_member_girl_24dp, // 女生对应女孩图标 + "外公" to R.drawable.ic_member_grandfather_24dp, // 外公对应祖父图标 + "外婆" to R.drawable.ic_member_grandmother_24dp, // 外婆对应祖母图标 + "其他" to R.drawable.ic_member_girl_24dp // 其他成员使用女孩图标作为默认值 ) + /** + * 获取分类对应的图标向量 + * 用于在Compose UI中直接使用 + * + * @param name 分类名称 + * @return 对应的图标向量,如果未找到则返回null + */ @Composable fun getCategoryIconVector(name: String): ImageVector? { return categoryIcons[name]?.let { ImageVector.vectorResource(id = it) } } + /** + * 获取成员对应的图标向量 + * 用于在Compose UI中直接使用 + * + * @param name 成员名称 + * @return 对应的图标向量,如果未找到则返回null + */ @Composable fun getMemberIconVector(name: String): ImageVector? { return memberIcons[name]?.let { ImageVector.vectorResource(id = it) } } + /** + * 获取分类对应的图标资源ID + * + * @param name 分类名称 + * @return 对应的图标资源ID,如果未找到则返回null + */ @DrawableRes fun getCategoryIcon(name: String): Int? { return categoryIcons[name] } + /** + * 获取成员对应的图标资源ID + * + * @param name 成员名称 + * @return 对应的图标资源ID,如果未找到则返回null + */ @DrawableRes fun getMemberIcon(name: String): Int? { return memberIcons[name] } + /** + * 获取所有可用的分类图标资源ID列表 + * + * @return 所有分类图标的资源ID列表 + */ fun getAllCategoryIcons(): List { return categoryIcons.values.toList() } + /** + * 获取所有可用的成员图标资源ID列表 + * + * @return 所有成员图标的资源ID列表 + */ fun getAllMemberIcons(): List { return memberIcons.values.toList() }