# Calendar Widget Android 应用需求文档 ## 项目概述 将现有的 Calendar Widget 任务管理系统迁移到 Android 平台,保持核心功能的同时提供原生移动应用体验。 ## 技术栈 - **开发语言**: Kotlin - **UI框架**: Jetpack Compose - **架构模式**: MVVM (Model-View-ViewModel) - **网络请求**: Retrofit + OkHttp - **本地存储**: Room Database - **依赖注入**: Hilt - **小组件**: Android App Widget API ## 应用结构 ### 1. 控制页面 (MainActivity) #### 功能需求 - **任务列表展示** - 显示所有任务的列表视图 - 每个任务项显示:名称、状态颜色、最小间隔天数、上次执行时间 - 支持下拉刷新更新任务列表 - **任务管理** - 添加新任务:浮动操作按钮触发对话框 - 编辑任务:长按任务项进入编辑模式 - 删除任务:侧滑删除或长按菜单删除 - 拖拽排序:长按拖动重新排列任务优先级 - **任务执行** - 点击"执行"按钮记录任务执行时间 - 成功执行后自动刷新状态颜色 #### UI设计要点 ```kotlin // 主界面布局结构 @Composable fun ControlScreen() { Scaffold( topBar = { /* 应用标题栏 */ }, floatingActionButton = { /* 添加任务按钮 */ } ) { LazyColumn { items(tasks) { task -> TaskCard( task = task, onExecute = { /* 执行任务 */ }, onEdit = { /* 编辑任务 */ }, onDelete = { /* 删除任务 */ } ) } } } } ``` ### 2. 展示页面 (DisplayActivity) #### 功能需求 - **任务状态可视化** - 网格布局展示任务卡片 - 动态适配屏幕大小(横屏4列,竖屏2列) - 每个卡片显示任务名称和颜色条 - 点击卡片快速执行任务 - **视图模式** - 紧凑模式:仅显示名称和颜色 - 详细模式:显示名称、颜色、剩余天数 #### UI设计要点 ```kotlin @Composable fun DisplayScreen() { val configuration = LocalConfiguration.current val columns = if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2 LazyVerticalGrid( columns = GridCells.Fixed(columns), contentPadding = PaddingValues(16.dp) ) { items(tasks) { task -> TaskDisplayCard( task = task, onClick = { /* 执行任务 */ } ) } } } ``` ### 3. Android 小组件 (Widget) #### 功能需求 - **尺寸支持** - 小型 (2x1): 显示1个任务 - 中型 (2x2): 显示4个任务 - 大型 (4x2): 显示8个任务 - **交互功能** - 点击任务执行并刷新小组件 - 自动每5分钟更新一次 - 支持手动刷新按钮 #### 实现要点 ```kotlin class TaskWidgetProvider : AppWidgetProvider() { override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { for (appWidgetId in appWidgetIds) { val size = getWidgetSize(appWidgetManager, appWidgetId) val views = createRemoteViews(context, size) appWidgetManager.updateAppWidget(appWidgetId, views) } // 设置下次更新时间为5分钟后 scheduleNextUpdate(context) } private fun scheduleNextUpdate(context: Context) { val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context, TaskWidgetProvider::class.java).apply { action = AppWidgetManager.ACTION_APPWIDGET_UPDATE } val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) // 5分钟后更新 val updateInterval = 5 * 60 * 1000L // 5分钟转换为毫秒 alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC, System.currentTimeMillis() + updateInterval, pendingIntent ) } } ``` #### 小组件布局 (仿照 widget.js 样式) ```xml ``` ## 数据管理 ### API 接口层 ```kotlin interface TaskApiService { @GET("tasks") suspend fun getTasks(@Header("X-Api-Key") apiKey: String): List @POST("tasks") suspend fun createTask(@Header("X-Api-Key") apiKey: String, @Body task: CreateTaskRequest): Task @PUT("tasks/{id}") suspend fun updateTask(@Header("X-Api-Key") apiKey: String, @Path("id") id: Int, @Body task: UpdateTaskRequest): Task @DELETE("tasks/{id}") suspend fun deleteTask(@Header("X-Api-Key") apiKey: String, @Path("id") id: Int) @POST("tasks/{id}/schedule") suspend fun scheduleTask(@Header("X-Api-Key") apiKey: String, @Path("id") id: Int) @POST("tasks/reorder") suspend fun reorderTasks(@Header("X-Api-Key") apiKey: String, @Body request: ReorderRequest) } ``` ### 本地缓存 ```kotlin @Entity(tableName = "tasks") data class TaskEntity( @PrimaryKey val id: Int, val name: String, val color: String, val minIntervalDays: Int, val lastExecutionTime: String?, val priority: Int ) @Dao interface TaskDao { @Query("SELECT * FROM tasks ORDER BY priority") fun getAllTasks(): Flow> @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertTasks(tasks: List) @Query("DELETE FROM tasks") suspend fun deleteAllTasks() } ``` ## 状态管理 ### ViewModel 实现 ```kotlin @HiltViewModel class TaskViewModel @Inject constructor( private val repository: TaskRepository ) : ViewModel() { private val _uiState = MutableStateFlow(TaskUiState()) val uiState: StateFlow = _uiState.asStateFlow() fun loadTasks() { viewModelScope.launch { repository.getTasks() .catch { /* 处理错误,使用缓存 */ } .collect { tasks -> _uiState.update { it.copy(tasks = tasks) } } } } fun executeTask(taskId: Int) { viewModelScope.launch { repository.scheduleTask(taskId) loadTasks() // 刷新列表 updateWidget() // 更新小组件 } } } ``` ## 应用设置 ### SharedPreferences 配置 ```kotlin object AppSettings { private const val PREF_NAME = "calendar_widget_prefs" private const val KEY_API_KEY = "api_key" private const val KEY_API_HOST = "api_host" private const val KEY_AUTO_REFRESH = "auto_refresh" private const val KEY_REFRESH_INTERVAL = "refresh_interval" fun saveApiKey(context: Context, apiKey: String) { context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .putString(KEY_API_KEY, apiKey) .apply() } } ``` ### 设置页面功能 - API密钥配置 - 服务器地址配置 - 小组件自动刷新间隔(默认5分钟,可选1/5/10/15/30/60分钟) - 主题选择(浅色/深色) - 通知设置 ## UI/UX 设计规范 ### 颜色主题 ```kotlin val CalendarWidgetTheme = lightColorScheme( primary = Color(0xFF667EEA), secondary = Color(0xFF764BA2), background = Color(0xFFF5F5F9), surface = Color(0xFFF2F2F2), error = Color(0xFFFF4757), onPrimary = Color.White, onSecondary = Color.White, onBackground = Color.Black, onSurface = Color.Black ) // 任务状态颜色 object TaskColors { val Green = Color(0xFF00B894) val Yellow = Color(0xFFFDCB6E) val Red = Color(0xFFFF4757) } ``` ### Material Design 3 组件 - 使用 Material You 动态主题 - 圆角卡片设计(16dp corner radius) - 浮动操作按钮 - 底部导航栏 - Snackbar 提示信息 ## 权限需求 ```xml ``` ## 构建配置 ### build.gradle.kts (Module) ```kotlin android { compileSdk = 34 defaultConfig { applicationId = "com.tunpok.calendarwidget" minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0.0" } buildFeatures { compose = true } } dependencies { // Compose implementation("androidx.compose.ui:ui:1.5.4") implementation("androidx.compose.material3:material3:1.1.2") // Navigation implementation("androidx.navigation:navigation-compose:2.7.5") // Network implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.okhttp3:okhttp:4.12.0") // Database implementation("androidx.room:room-runtime:2.6.0") implementation("androidx.room:room-ktx:2.6.0") // Dependency Injection implementation("com.google.dagger:hilt-android:2.48") // Widget implementation("androidx.glance:glance-appwidget:1.0.0") } ``` ## 测试策略 ### 单元测试 - Repository 层测试 - ViewModel 逻辑测试 - 日期计算和颜色映射测试 ### UI 测试 - Compose UI 测试 - 小组件更新测试 - 网络请求模拟测试 ## 发布准备 ### ProGuard 规则 ```proguard -keep class com.tunpok.calendarwidget.data.model.** { *; } -keepattributes Signature -keepattributes *Annotation* ``` ### 版本管理 - 使用语义化版本号 - 维护 CHANGELOG.md - 配置自动化构建和发布流程 ## 后续优化建议 1. **性能优化** - 实现图片和数据懒加载 - 使用 WorkManager 进行后台同步 - 实现智能更新策略(活动时5分钟更新,空闲时降低频率以节省电量) 2. **功能扩展** - 添加任务提醒通知 - 支持任务分类和标签 - 实现任务统计图表 - 添加批量操作功能 3. **用户体验** - 实现手势操作 - 添加动画效果 - 支持快捷方式 - 深色模式自动切换 4. **国际化** - 支持多语言 - 适配不同地区日期格式 - 时区自动转换