diff --git a/CHANGELOG.md b/CHANGELOG.md index efd2614..b5ddb5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,72 @@ All notable changes to this project will be documented in this file. --- +## [1.3.37] - 2026-04-02 + +### 新增 +- ✨ **主题颜色选择器重新设计** + - 新增中国传统色彩:书褐色(#8B4513)和宣纸色(#F5F5F0) + - 颜色选择器改为横向滚动列表,每个颜色显示圆形色块和中文名称 + - 选中状态显示勾选图标和发光阴影效果 + - 颜色名称采用中国风命名:紫韵、天蓝、翠绿、橙光、朱红、青碧、书褐、明黄、桃粉、湖青、罗兰、宣纸 + - 涉及文件: + - `lib/models/colors/theme_colors.dart` - 新增中国传统色彩 + - `lib/views/profile/theme/app-diy.dart` - 重新设计颜色选择器 + +## [1.3.36] - 2026-04-02 + +### 新增 +- ✨ **Profile 组件主题色支持** + - Bug列表页面、全站统计页面、投票凭证弹窗、Pop菜单、服务器信息弹窗支持主题色设置 + - 所有组件颜色动态响应主题色变化,包括按钮、卡片、图标、文本等 + - 新增 `AppColors` 类统一管理动态主题色,支持深色/浅色模式自动切换 + - 使用 iOS 风格系统颜色(蓝、绿、红、橙、紫等)保持一致性 + - 涉及文件: + - `lib/models/colors/app_colors.dart` - 新建动态颜色管理类 + - `lib/views/profile/components/bug_list_page.dart` - 支持主题色 + - `lib/views/profile/components/entire_page.dart` - 支持主题色 + - `lib/views/profile/components/login_register_dialog.dart` - 支持主题色 + - `lib/views/profile/components/pop-menu.dart` - 支持主题色 + - `lib/views/profile/components/server_info_dialog.dart` - 支持主题色 + - `lib/views/profile/level/distinguish.dart` - 支持主题色 + - `lib/views/profile/level/flow-anim.dart` - 支持主题色 + - `lib/views/profile/level/poetry.dart` - 支持主题色 + - `lib/views/profile/app-info.dart` - 支持主题色 + +## [1.3.35] - 2026-04-02 + +### 新增 +- ✨ **活跃页面主题色支持** + - 搜索页面、热门页面、分类页面、活跃度页面支持主题色设置 + - 所有组件颜色动态响应主题色变化,包括Tab栏、按钮、卡片边框等 + - 涉及文件: + - `lib/views/active/active_search_page.dart` - 支持主题色 + - `lib/views/active/popular_page.dart` - 支持主题色 + - `lib/views/active/category_page.dart` - 支持主题色 + - `lib/views/active/rate.dart` - 支持主题色 + +## [1.3.34] - 2026-04-02 + +### 新增 +- ✨ **多页面主题色支持** + - 发现页面、标签页面、收藏页面、响应式首页等多个页面支持主题色设置 + - 所有组件颜色动态响应主题色变化 + - 涉及文件: + - `lib/views/active/tags/corr_page.dart` - 支持主题色 + - `lib/views/discover_page.dart` - 支持主题色 + - `lib/views/favorites_page.dart` - 支持主题色 + - `lib/views/responsive_home_page.dart` - 支持主题色 + +## [1.3.33] - 2026-04-02 + +### 新增 +- ✨ **首页主题色支持** + - 首页诗词卡片、按钮、加载状态等组件支持主题色设置 + - 主题色变化时,首页所有相关组件会实时更新 + - 涉及文件: + - `lib/views/home/home_part.dart` - 支持主题色 + - `lib/views/home/set/home_components.dart` - 支持主题色 + ## [1.3.32] - 2026-04-02 ### 新增 @@ -16,8 +82,6 @@ All notable changes to this project will be documented in this file. - 涉及文件: - `lib/views/profile/per_card.dart` - 添加头像切换功能 ---- - ## [1.3.31] - 2026-04-02 ### 优化 @@ -30,374 +94,6 @@ All notable changes to this project will be documented in this file. --- -## [1.3.30] - 2026-04-02 - -### 新增 -- ⭐ **添加全局 Tips 开关管理器** - - 创建 `GlobalTipsManager` 单例类,支持 ValueNotifier 状态监听 - - 修改设置页面,全局 Tips 开关使用 GlobalTipsManager 管理 - - 修改发现页面,使用 ValueListenableBuilder 监听状态变化 - - 开关关闭后,发现页面的 Tips 提示会立即隐藏,下方布局自动向上占位 - - 涉及文件: - - `lib/views/home/home-load.dart` - 添加 GlobalTipsManager - - `lib/views/profile/settings/app_fun.dart` - 使用 GlobalTipsManager - - `lib/views/discover_page.dart` - 使用 ValueListenableBuilder 监听状态 - -### 优化 -- 🎨 **给诗词原文添加轻微背景色** - - 给诗词原文区域添加主题色 20% 透明度的背景 - - 添加"诗词原文"标题,使区域更清晰 - - 涉及文件: - - `lib/views/home/home_part.dart` - 添加背景色和标题 - ---- - -## [1.3.29] - 2026-04-02 - -### 修复 -- 🐛 **修复调试信息开关关闭后仍显示调试信息的问题** - - 修改 `home_controller.dart`,将所有 `Get.snackbar` 调用改为通过 `DebugInfoManager` 显示 - - 调试信息现在完全受设置页面中的"调试信息"开关控制 - - 开关关闭后,所有调试提示(刷新、下一条、上一条、点赞、复制等)都不会显示 - - 涉及文件: - - `lib/services/get/home_controller.dart` - 统一通过 DebugInfoManager 显示调试信息 - ---- - -## [1.3.28] - 2026-04-02 - -### 优化 -- 🚀 **优化设置页面,内外实时生效** - - 修改 `DebugInfoManager`,添加 `ValueNotifier` 支持实时状态监听 - - 修改 `AutoRefreshManager`,添加 `ValueNotifier` 支持实时状态监听,init 时自动启动定时器 - - 修改 `home_page.dart`,从 `StatelessWidget` 改为 `StatefulWidget`,添加 `ValueListenableBuilder` 监听次要按钮状态 - - 次要按钮(上一条、分享)的显示/隐藏现在可以实时响应设置变化 - - 涉及文件: - - `lib/views/home/home-load.dart` - 添加 ValueNotifier 支持 - - `lib/views/home/home_page.dart` - 添加实时监听次要按钮状态 - - `lib/views/profile/settings/app_fun.dart` - 已优化设置逻辑 - ---- - -## [1.3.26] - 2026-04-02 - -### 优化 -- 🎨 **优化主页悬浮按钮位置,紧贴底部导航栏** - - 修改悬浮按钮 bottom 定位值,从使用 liquidGlassTotalHeight 改为使用 liquidGlassHeight + liquidGlassBottomMargin - - 调整按钮间距,使布局更紧凑美观 - - 确保按钮固定位置,不随诗词卡片上下滚动 - - 涉及文件: - - `lib/views/home/home_page.dart` - 修改悬浮按钮定位 - ---- - -## [1.3.25] - 2026-04-02 - -### 新增 -- ✨ **新增液态玻璃导航栏透明度级别控制** - - 在 TapLiquidGlassController 中添加 TransparencyLevel 枚举 - - 支持三个透明度级别:弱、中、强 - - 弱:当前效果(白色 0.35/0.2,灰色 0.35/0.2) - - 中:中等透明度(白色 0.22/0.12,灰色 0.22/0.12) - - 强:几乎透明(白色 0.1/0.05,灰色 0.1/0.05) - - 在功能设置页面添加 3 级开关,开启 Tap 沉浸光感后显示 - - 透明度设置持久化到 SharedPreferences - - 涉及文件: - - `lib/services/get/tap_liquid_glass_controller.dart` - 新增透明度级别控制 - - `lib/views/profile/settings/app_fun.dart` - 添加透明度级别开关 - - `lib/widgets/tap-liquid-glass.dart` - 应用透明度级别 - ---- - -## [1.3.24] - 2026-04-02 - -### 修复 -- 🔧 **修复发现页 Tips 显示和关闭功能** - - 在 DiscoverController 中添加全局 tips 开关设置加载逻辑 - - 修改 discover_page.dart 显示条件,根据全局开关和本地关闭状态控制显示 - - 全局Tips关闭时,发现页不显示提示 - - 全局Tips开启时,点击X可关闭提示(仅当前会话,不写入SharedPreferences) - - 涉及文件: - - `lib/services/get/discover_controller.dart` - 添加全局tips开关加载 - - `lib/views/discover_page.dart` - 修改tips显示逻辑 - ---- - -## [1.3.23] - 2026-04-02 - -### 优化 -- 🎨 **优化 Tap 沉浸光感液态玻璃导航栏视觉效果** - - 增强透明效果,降低背景透明度约 30-40% - - 移除选中项胶囊形背景,消除两层包裹效果 - - 移除点击水波纹和高亮效果,保持纯净玻璃质感 - - 添加灰度渐变底层,提升玻璃逼真度 - - 优化图标缩放效果(从 1.12 调整为 1.1) - - 增加模糊强度(从 20 提升至 35) - - 增强阴影效果,提升悬浮感 - - 涉及文件: - - `lib/widgets/tap-liquid-glass.dart` - 优化视觉效果 - - `lib/config/app_config.dart` - 增加模糊强度 - ---- - -## [1.3.22] - 2026-04-02 - -### 重新设计 -- 🎨 **重新设计 Tap 沉浸光感液态玻璃导航栏** - - 实现 iOS 26 风格的液态玻璃效果 - - 使用 BackdropFilter 实现真正的毛玻璃模糊 - - 下层页面滑动时,能透过底栏模糊看到底部大概轮廓 - - 添加双层阴影效果,增强悬浮感 - - 使用渐变背景替代纯色,提升玻璃质感 - - 选中项添加胶囊形背景指示器 - - 优化图标动画效果,选中时放大 1.12 倍 - - 支持动画开关控制,响应主题控制器设置 - - 添加详细的使用示例和注意事项注释 - - 涉及文件: - - `lib/widgets/tap-liquid-glass.dart` - 重新设计液态玻璃导航栏 - -### 修复 -- 🔧 **修复液态玻璃导航栏布局遮挡问题** - - 使用 Stack 布局替代 Scaffold.bottomNavigationBar - - 导航栏悬浮在页面内容上方,不再遮挡下方布局 - - 页面内容延伸到屏幕底部,透过玻璃可见 - - 添加 `liquidGlassTotalHeight` 配置计算导航栏总高度 - - 修改所有子页面 ListView/ScrollView 底部内边距 - - 涉及文件: - - `lib/widgets/main_navigation.dart` - 使用 Stack 布局实现悬浮效果 - - `lib/config/app_config.dart` - 添加导航栏高度计算 - - `lib/views/home/home_page.dart` - 添加底部内边距 - - `lib/views/discover_page.dart` - 添加底部内边距 - - `lib/views/active/popular_page.dart` - 添加底部内边距 - - `lib/views/footprint/all_list.dart` - 添加底部内边距 - - `lib/views/footprint/liked_poetry_manager.dart` - 添加底部内边距 - - `lib/views/footprint/local_jilu.dart` - 添加底部内边距 - - `lib/views/profile/profile_page.dart` - 添加底部内边距 - ---- - -## [1.3.21] - 2026-04-02 - -### 优化 -- 🎨 **优化Tap沉浸光感液态玻璃导航栏** - - 恢复毛玻璃效果,去掉外层纯色背景遮挡 - - 滑动时能模糊看到下层视图的大概轮廓 - - 保持椭圆形悬浮设计和毛玻璃模糊效果 - - 优化点击区域,使用 InkWell 替代 GestureDetector - - 点击区域扩展到整个 Expanded 区域,包括空白区域 - - 添加水波纹效果,提升点击反馈 - - 涉及文件: - - `lib/widgets/tap-liquid-glass.dart` - 优化液态玻璃导航栏 - ---- - -## [1.3.20] - 2026-04-01 - -### 新增 -- ✨ **深色模式支持全面上线** - - 创建 ThemeController 管理深色模式状态 - - 使用 SharedPreferences 持久化深色模式设置 - - 全局深色模式适配,涉及 20+ 页面 - - iOS 风格的深色配色方案 - - 统一的暗色背景、卡片、文字颜色 - - 涉及文件: - - `lib/models/night-mode/theme_model.dart` - 主题数据模型 - - `lib/services/get/theme_controller.dart` - 主题控制器 - - `lib/views/profile/theme/app-diy.dart` - 深色模式开关 - - `lib/views/home/home_page.dart` - 首页深色模式 - - `lib/views/home/home_part.dart` - 首页组件 - - `lib/views/home/home-load.dart` - 首页加载 - - `lib/views/home/home_components.dart` - 首页组件 - - `lib/views/discover_page.dart` - 发现页深色模式 - - `lib/views/active/rate.dart` - 评价页深色模式 - - `lib/views/active/category_page.dart` - 分类页深色模式 - - `lib/views/active/active_search_page.dart` - 搜索页深色模式 - - `lib/views/active/tags/corr_page.dart` - 标签页深色模式 - - `lib/views/favorites_page.dart` - 收藏页深色模式 - - `lib/views/footprint/all_list.dart` - 全部列表深色模式 - - `lib/views/footprint/collect_notes.dart` - 笔记页深色模式 - - `lib/views/footprint/footprint_page.dart` - 足迹页深色模式 - - `lib/views/footprint/local_jilu.dart` - 本地记录深色模式 - - `lib/views/profile/profile_page.dart` - 个人中心深色模式 - - `lib/views/profile/history_page.dart` - 历史页深色模式 - - `lib/views/profile/app-info.dart` - 应用信息深色模式 - - `lib/views/profile/level/distinguish.dart` - 辨别页深色模式 - - `lib/views/profile/level/flow-anim.dart` - 动画页深色模式 - - `lib/views/profile/level/level-jilu.dart` - 级别记录深色模式 - - `lib/views/profile/level/poetry.dart` - 诗词页深色模式 - - `lib/views/profile/guide/beginner_page.dart` - 教程页深色模式 - - `lib/views/profile/guide/sp-guide.dart` - 引导页深色模式 - - `lib/views/profile/guide/tongji.dart` - 统计页深色模式 - - `lib/utils/app_initializer.dart` - 应用初始化 - - `lib/utils/app_theme.dart` - 应用主题 - -### 修复 -- 🔧 **修复诗词卡片加载状态问题** - - 使用 Obx 包装 PoetryCard 组件 - - 确保 sectionLoadingStates 更新时 UI 响应式刷新 - - 解决"xx加载中..."一直显示的问题 - - 涉及文件: - - `lib/views/home/home_page.dart` - 修复加载状态 - ---- - -## [1.3.19] - 2026-04-01 - -### 新增 -- ✨ **实现应用数据计算功能** - - 使用原生 dart:io 实现软件包、缓存、数据大小计算 - - 递归计算目录大小,支持多层级文件遍历 - - 字节格式化,自动转换为 B/KB/MB/GB/TB - - 软件包大小:计算应用数据目录总大小 - - 缓存大小:计算临时目录大小 - - 数据大小:计算文档和支持目录大小 - - 占用空间:显示软件包+缓存+数据+10MB 的总和 - - 实现清空缓存功能,递归删除临时文件 - - 清空后自动刷新缓存大小显示 - - 新增原生清理数据按钮,直接删除文件系统数据 - - 双重确认对话框,防止误操作 - - 原生清理完成后提示关闭应用 - - 涉及文件: - - `lib/views/profile/guide/app-data.dart` - 实现数据计算功能 - -### 修复 -- 🔧 **统一版本号显示** - - 修复 learn-us.dart 中版本号引用错误问题 - - 修复 app-info.dart 中硬编码版本号问题 - - 统一使用 AppConfig.appVersion 显示版本号 - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 修正版本号引用 - - `lib/views/profile/app-info.dart` - 统一版本号显示 - -### 更新 -- 🎨 **多平台应用图标全面更新** - - 使用用户提供的本地图片作为应用图标 - - 原图尺寸:647x559,自动居中裁剪为正方形 - - 新增 216x216 尺寸图标 - - 支持所有平台图标生成: - - **HarmonyOS**:完整图标集(9个尺寸) - - **Android**:启动图标(5个尺寸) - - **macOS**:应用图标(7个尺寸) - - 所有平台图标已同步更新 - - 涉及文件: - - `ohos/entry/src/main/resources/base/media/` - HarmonyOS 图标集(含 icon_216.png) - - `ohos/AppScope/resources/base/media/app_icon.png` - HarmonyOS AppScope 图标 - - `android/app/src/main/res/mipmap-*/ic_launcher.png` - Android 启动图标 - - `macos/Runner/Assets.xcassets/AppIcon.appiconset/` - macOS 图标 - - `generate_all_icons.py` - 多平台图标生成脚本 - - `assets/XZ4QCHGE][UUYGCV2G(~88J.png` - 用户提供的原始图片 - ---- - -## [1.3.18] - 2026-04-01 - -### 改进 -- ✨ **优化诗词投稿检测功能** - - 在"检测是否存在"按钮左边添加检测状态显示 - - 显示"未检测"、"已检测"、"未通过"三种状态 - - 配套图标:pending、check_circle、close - - 使用主题色和错误色区分不同状态 - - 提交前要求必须先检测且通过才能提交 - - 未检测时提示"请先检测诗词是否存在" - - 涉及文件: - - `lib/views/profile/expand/manu-script.dart` - 优化检测功能 - ---- - -## [1.3.17] - 2026-04-01 - -### 优化 -- 🎨 **重新设计使用教程页面** - - iOS 风格的全新设计,更符合苹果设计理念 - - 增加了四个主要页面的界面预览模块(首页、发现页、足迹页、个人中心) - - 每个模块使用不同的 emoji 图标和配色方案,图文并茂 - - 保留左侧进度条并优化动画效果 - - 新增页面淡入动画和卡片逐个出现动画 - - 使用主题色 AppConstants.primaryColor 统一配色 - - 圆角卡片设计,柔和阴影,符合 iOS 风格 - - 涉及文件: - - `lib/views/profile/guide/beginner_page.dart` - 重新设计使用教程页面 - -### 改进 -- 🎨 **优化进度条悬浮效果** - - 进度条改为悬浮在内容上方,不再单独占位 - - 添加渐变背景遮罩,从左到右透明度渐变 - - 内容区域宽度增加,提升阅读体验 - - 涉及文件: - - `lib/views/profile/guide/beginner_page.dart` - 优化进度条悬浮效果 -- ✨ **优化导航栏设计** - - 标题文字使用主题色 AppConstants.primaryColor - - 右上角添加帮助图标按钮 - - 点击按钮跳转到欢迎引导页 SpGuidePage - - 涉及文件: - - `lib/views/profile/guide/beginner_page.dart` - 优化导航栏 -- ✨ **添加滚动隐藏 AppBar 功能** - - 使用 SliverAppBar 实现滚动时自动隐藏效果 - - floating: true 和 snap: true 配合,实现自然收起动画 - - 向下滚动时 AppBar 自动隐藏,向上滚动时自动显示 - - 所有图标颜色统一使用主题色 AppConstants.primaryColor - - 涉及文件: - - `lib/views/profile/guide/beginner_page.dart` - 添加滚动隐藏功能 -- 🎨 **美化开发者卡片** - - 新增微信公众号信息展示 - - 公众号名称:微风暴 - - 使用微信绿色主题色 (0xFF07C160) - - 添加搜索图标和标签样式设计 - - 渐变色背景卡片,圆角设计 - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 美化开发者卡片 -- 🎨 **优化卡片布局** - - 去掉开发者卡片和团队信息卡片中的分割线 - - 调整内边距,使布局更紧凑美观 - - 内容区块之间使用自然间距代替分割线 - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 优化卡片布局 -- ✨ **增强开发者卡片功能** - - 邮箱地址字体加大,从 13 改为 15 - - 公众号"微风暴"右边添加复制图标 - - 点击复制图标可复制公众号名称到剪贴板 - - 复制成功后显示 SnackBar 提示 - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 增强开发者卡片 -- 🎨 **优化设备信息卡片布局** - - 设备信息从 1×6 列表布局改为 2×3 网格布局 - - 新增网格布局信息项 widget,带卡片样式 - - 使用主题色 AppConstants.primaryColor 统一图标颜色 - - 可复制项带复制图标,点击可复制 - - 卡片样式:灰色背景,圆角边框,更美观 - - 去掉设备信息和设备详细信息之间的空白区域 - - 涉及文件: - - `lib/views/profile/app-info.dart` - 优化设备信息布局 - ---- - -## [1.3.16] - 2026-04-01 - -### 新增 -- ✨ **新增使用教程页面** - - 创建 iOS 风格的使用教程页面 `BeginnerPage` - - 超长列表布局,包含 16 个功能模块 - - 左侧悬浮进度指示器,带平滑动画 - - 显示当前阅读进度百分比 - - 主题色设计,圆角卡片,阴影效果 - - 功能模块:首页功能、发现页面、足迹页面、个人中心、诗词阅读、收藏功能、搜索功能、答题挑战、离线模式、个性化设置、投稿功能、投票功能、天气与十二时辰、图片分享、数据管理、帮助与反馈 - - 涉及文件: - - `lib/views/profile/guide/beginner_page.dart` - 新建使用教程页面 - - `lib/views/profile/components/pop-menu.dart` - 修改按钮跳转 - ---- - -## [1.3.15] - 2026-04-01 - -### 修改 -- 🎨 **修改收藏页面标题** - - 将收藏页面 AppBar 标题从"收藏"改为"足迹" - - 底部导航栏标签保持"收藏"不变 - - 涉及文件: - - `lib/views/favorites_page.dart` - 修改页面标题 - ---- - ## 软件特性功能 ### 已开发完成 @@ -416,6 +112,9 @@ All notable changes to this project will be documented in this file. - ✅ 全站统计页面 - ✅ 修复 AppBar 标题显示问题 - ✅ 个人卡片emoji头像切换功能 +- ✅ 深色模式支持 +- ✅ 液态玻璃导航栏 +- ✅ 多页面主题色支持 ### 开发中 - 🚧 更多功能优化 @@ -428,5 +127,6 @@ All notable changes to this project will be documented in this file. | 投稿功能优化 | 2 | ✅ 已完成 | | 界面美化 | 3 | ✅ 已完成 | | 数据管理功能 | 1 | ✅ 已完成 | +| 主题色支持 | 1 | ✅ 已完成 | | 性能优化 | 4 | 🔄 进行中 | | 新功能开发 | 5 | 📋 计划中 | diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 2980411..c05821f 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 583adce..8d4fb33 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 5b3ae51..7df2aa0 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 68663db..f53f8af 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 3d06d3f..4cee87e 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 323d563..bad5b72 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -43,7 +43,7 @@ class AppConfig { static const double landscapeBottomNavHeight = 56.0; // API 配置 - static const String baseUrl = 'https://api.example.com'; + static const String baseUrl = 'https://yy.vogov.cn'; static const Duration apiTimeout = Duration(seconds: 30); // 主题配置 diff --git a/lib/controllers/settings/suggestions.dart b/lib/controllers/settings/suggestions.dart new file mode 100644 index 0000000..3741f1b --- /dev/null +++ b/lib/controllers/settings/suggestions.dart @@ -0,0 +1,178 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../constants/app_constants.dart'; +import '../../services/get/theme_controller.dart'; +import '../../views/profile/theme/app-diy.dart'; +import '../../views/footprint/collect_notes.dart'; +import '../../views/profile/app-info.dart'; + +class SuggestionsCard extends StatefulWidget { + const SuggestionsCard({super.key}); + + @override + State createState() => _SuggestionsCardState(); +} + +class _SuggestionsCardState extends State { + final ThemeController _themeController = Get.find(); + bool _showAlternativeContent = false; + + @override + Widget build(BuildContext context) { + final isDark = _themeController.isDarkMode; + + return Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [ + GestureDetector( + onTap: () { + setState(() { + _showAlternativeContent = !_showAlternativeContent; + }); + }, + child: Row( + children: [ + Icon( + Icons.settings_suggest, + size: 40, + color: AppConstants.primaryColor, + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '设置建议', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black, + ), + ), + const SizedBox(height: 4), + Text( + _showAlternativeContent ? '是否在找,清理数据' : '是否在找,主题风格', + style: TextStyle( + fontSize: 13, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + ), + ], + ), + ), + Icon(Icons.refresh, color: AppConstants.primaryColor), + ], + ), + ), + const SizedBox(height: 16), + _showAlternativeContent + ? Row( + children: [ + Expanded( + child: _buildActionButton( + '清理数据', + '管理应用数据', + Icons.delete_sweep, + Colors.red, + () => Get.toNamed('/app-data-guide'), + ), + ), + const SizedBox(width: 12), + Expanded( + child: _buildActionButton( + '了解软件', + '查看应用信息', + Icons.info, + Colors.purple, + () => Get.to(() => const AppInfoPage()), + ), + ), + ], + ) + : Row( + children: [ + Expanded( + child: _buildActionButton( + '主题风格', + '自定义应用主题', + Icons.palette, + Colors.blue, + () => Get.to(() => const AppDiyPage()), + ), + ), + const SizedBox(width: 12), + Expanded( + child: _buildActionButton( + '创建笔记', + '快速创建新笔记', + Icons.note_add, + Colors.green, + () => Get.to(() => const CollectNotesPage()), + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildActionButton( + String title, + String subtitle, + IconData icon, + Color color, + VoidCallback onTap, + ) { + final isDark = _themeController.isDarkMode; + + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: color.withValues(alpha: 0.2), width: 1), + ), + child: Column( + children: [ + Icon(icon, color: color, size: 24), + const SizedBox(height: 4), + Text( + title, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black, + ), + ), + const SizedBox(height: 2), + Text( + subtitle, + style: TextStyle( + fontSize: 11, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index e27c412..fe09b3e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'utils/app_theme.dart'; import 'utils/app_initializer.dart'; import 'utils/force_guide_checker.dart'; import 'routes/app_routes.dart'; import 'constants/app_constants.dart'; +import 'config/app_config.dart'; import 'controllers/shared_preferences_storage_controller.dart'; import 'services/get/theme_controller.dart'; +import 'views/profile/guide/sp-guide.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -16,21 +19,31 @@ void main() async { // 初始化 ThemeController(在 AppInitializer 之前,确保主题最先加载) Get.put(ThemeController(), permanent: true); - final result = await AppInitializer.initialize(); + // 检查是否需要显示引导页 + String initialRoute = await _getInitialRoute(); - runApp( - MyApp( - initialRoute: result.initialRoute, - guideCheckResult: result.guideCheckResult, - ), - ); + runApp(MyApp(initialRoute: initialRoute)); +} + +Future _getInitialRoute() async { + final prefs = await SharedPreferences.getInstance(); + bool agreementAccepted = + prefs.getBool(AppConfig.keyAgreementAccepted) ?? false; + + // 如果协议未被接受,显示引导页 + if (!agreementAccepted) { + return '/sp-guide'; + } + + // 否则使用 AppInitializer 返回的初始路由 + final result = await AppInitializer.initialize(); + return result.initialRoute; } class MyApp extends StatelessWidget { final String initialRoute; - final GuideCheckResult? guideCheckResult; - const MyApp({super.key, required this.initialRoute, this.guideCheckResult}); + const MyApp({super.key, required this.initialRoute}); @override Widget build(BuildContext context) { @@ -45,6 +58,7 @@ class MyApp extends StatelessWidget { themeMode: themeController.currentThemeMode, initialRoute: initialRoute, onGenerateRoute: AppRoutes.generateRoute, + routes: {'/sp-guide': (context) => const SpGuidePage()}, ); }); } diff --git a/lib/models/colors/app_colors.dart b/lib/models/colors/app_colors.dart new file mode 100644 index 0000000..65b4588 --- /dev/null +++ b/lib/models/colors/app_colors.dart @@ -0,0 +1,87 @@ +/// 时间: 2026-04-02 +/// 功能: 应用动态颜色管理 +/// 介绍: 提供基于 ThemeController 的动态颜色获取,支持主题色实时切换 + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../services/get/theme_controller.dart'; + +/// 应用颜色管理类 +/// 使用 GetX 获取当前主题色,支持动态切换 +class AppColors { + /// 获取 ThemeController 实例 + static ThemeController get _themeController => Get.find(); + + /// 当前主题色(动态获取) + static Color get primary => _themeController.currentThemeColor; + + /// 当前强调色(动态获取) + static Color get accent => _themeController.currentAccentColor; + + /// 是否为深色模式 + static bool get isDarkMode => _themeController.isDarkMode; + + /// iOS 系统风格颜色 + static const Color iosBlue = Color(0xFF007AFF); + static const Color iosGreen = Color(0xFF34C759); + static const Color iosRed = Color(0xFFFF3B30); + static const Color iosOrange = Color(0xFFFF9500); + static const Color iosYellow = Color(0xFFFFCC00); + static const Color iosPurple = Color(0xFF5856D6); + static const Color iosTeal = Color(0xFF5AC8FA); + static const Color iosPink = Color(0xFFFF2D55); + static const Color iosIndigo = Color(0xFF5856D6); + static const Color iosGray = Color(0xFF8E8E93); + static const Color iosLightGray = Color(0xFFE5E5EA); + static const Color iosDarkGray = Color(0xFF3C3C43); + + /// 深色模式背景色 + static const Color darkBackground = Color(0xFF1A1A1A); + static const Color darkSurface = Color(0xFF2A2A2A); + static const Color darkCard = Color(0xFF333333); + + /// 浅色模式背景色 + static const Color lightBackground = Color(0xFFF2F2F7); + static const Color lightSurface = Colors.white; + static const Color lightCard = Color(0xFFF2F2F7); + + /// 获取背景色(根据主题模式) + static Color get background => isDarkMode ? darkBackground : lightBackground; + + /// 获取表面色(根据主题模式) + static Color get surface => isDarkMode ? darkSurface : lightSurface; + + /// 获取卡片色(根据主题模式) + static Color get card => isDarkMode ? darkCard : lightCard; + + /// 获取主文本色(根据主题模式) + static Color get primaryText => isDarkMode ? Colors.white : Colors.black; + + /// 获取次文本色(根据主题模式) + static Color get secondaryText => + isDarkMode ? Colors.grey[400]! : iosDarkGray.withAlpha(153); + + /// 获取三级文本色(根据主题模式) + static Color get tertiaryText => isDarkMode ? Colors.grey[500]! : iosGray; + + /// 获取分隔线颜色(根据主题模式) + static Color get divider => isDarkMode ? Colors.grey[700]! : iosLightGray; + + /// 获取带透明度的主题色 + static Color primaryWithAlpha(int alpha) => primary.withAlpha(alpha); + + /// 获取带透明度的强调色 + static Color accentWithAlpha(int alpha) => accent.withAlpha(alpha); + + /// 成功色(绿色,iOS风格) + static const Color success = iosGreen; + + /// 警告色(橙色,iOS风格) + static const Color warning = iosOrange; + + /// 错误色(红色,iOS风格) + static const Color error = iosRed; + + /// 信息色(蓝色,iOS风格) + static const Color info = iosBlue; +} diff --git a/lib/models/colors/theme_colors.dart b/lib/models/colors/theme_colors.dart new file mode 100644 index 0000000..2496fba --- /dev/null +++ b/lib/models/colors/theme_colors.dart @@ -0,0 +1,51 @@ +/// 时间: 2026-04-02 +/// 功能: 主题颜色管理 +/// 介绍: 提供主题颜色的管理和获取功能 + +import 'package:flutter/material.dart'; +import '../../constants/app_constants.dart'; + +class ThemeColors { + // 主题颜色选项 + static const List themeColors = [ + AppConstants.primaryColor, // 默认紫色 + Colors.blue, // 蓝色 + Colors.green, // 绿色 + Colors.orange, // 橙色 + Colors.red, // 红色 + Colors.teal, // 青色 + Color(0xFF8B4513), // 书褐色 - 传统中国风 + ]; + + // 强调色选项 + static const List accentColors = [ + AppConstants.primaryColor, // 默认紫色 + Colors.yellow, // 黄色 + Colors.pink, // 粉色 + Colors.cyan, // 青色 + Colors.purple, // 深紫色 + Color(0xFFF5F5F0), // 宣纸色 - 米白色 + ]; + + // 中国传统色彩 + static const Color ricePaperColor = Color(0xFFF5F5F0); // 宣纸色 - 米白 + static const Color inkBlackColor = Color(0xFF3C2A21); // 墨黑色 + static const Color bookBrownColor = Color(0xFF5D4037); // 书褐色 + static const Color traditionalBrownColor = Color(0xFF8B4513); // 传统褐色 + + // 根据索引获取主题颜色 + static Color getThemeColor(int index) { + if (index >= 0 && index < themeColors.length) { + return themeColors[index]; + } + return themeColors[0]; // 默认返回第一个颜色 + } + + // 根据索引获取强调色 + static Color getAccentColor(int index) { + if (index >= 0 && index < accentColors.length) { + return accentColors[index]; + } + return accentColors[0]; // 默认返回第一个颜色 + } +} diff --git a/lib/views/profile/level/api.md b/lib/services/document/api.md similarity index 100% rename from lib/views/profile/level/api.md rename to lib/services/document/api.md diff --git a/lib/services/get/care_controller.dart b/lib/services/get/care_controller.dart new file mode 100644 index 0000000..d689325 --- /dev/null +++ b/lib/services/get/care_controller.dart @@ -0,0 +1,87 @@ +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class CareController extends GetxController { + static const String _careModeKey = 'care_mode_enabled'; + static const String _userTypeKey = 'care_user_type'; + static const String _pinyinEnabledKey = 'care_pinyin_enabled'; + static const String _selectedOptionsKey = 'care_selected_options'; + static const String _careNavigationIndexKey = 'care_navigation_index'; + + final RxBool _isCareModeEnabled = false.obs; + final RxString _userType = '儿童'.obs; + final RxBool _pinyinEnabled = false.obs; + final RxSet _selectedOptions = {'诗词', '出处'}.obs; + final RxBool isCareButtonVisible = false.obs; + final RxInt _careNavigationIndex = 0.obs; + + bool get isCareModeEnabled => _isCareModeEnabled.value; + String get userType => _userType.value; + bool get pinyinEnabled => _pinyinEnabled.value; + Set get selectedOptions => _selectedOptions.toSet(); + int get careNavigationIndex => _careNavigationIndex.value; + + @override + void onInit() { + super.onInit(); + _loadCareSettings(); + } + + Future _loadCareSettings() async { + final prefs = await SharedPreferences.getInstance(); + _isCareModeEnabled.value = prefs.getBool(_careModeKey) ?? false; + _userType.value = prefs.getString(_userTypeKey) ?? '儿童'; + _pinyinEnabled.value = prefs.getBool(_pinyinEnabledKey) ?? false; + _careNavigationIndex.value = prefs.getInt(_careNavigationIndexKey) ?? 0; + + final savedOptions = prefs.getStringList(_selectedOptionsKey); + if (savedOptions != null && savedOptions.isNotEmpty) { + _selectedOptions.clear(); + _selectedOptions.addAll(savedOptions); + if (!_selectedOptions.contains('诗词')) { + _selectedOptions.add('诗词'); + } + } + } + + Future toggleCareMode() async { + _isCareModeEnabled.value = !_isCareModeEnabled.value; + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool(_careModeKey, _isCareModeEnabled.value); + } + + Future setUserType(String type) async { + _userType.value = type; + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_userTypeKey, type); + } + + Future setPinyinEnabled(bool enabled) async { + _pinyinEnabled.value = enabled; + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool(_pinyinEnabledKey, enabled); + } + + Future toggleOption(String option) async { + if (option == '诗词') return; // 诗词选项不可取消 + + if (_selectedOptions.contains(option)) { + _selectedOptions.remove(option); + } else { + _selectedOptions.add(option); + } + + final prefs = await SharedPreferences.getInstance(); + await prefs.setStringList(_selectedOptionsKey, _selectedOptions.toList()); + } + + void toggleCareButtonVisibility() { + isCareButtonVisible.value = !isCareButtonVisible.value; + } + + Future switchCareNavigation(int index) async { + _careNavigationIndex.value = index; + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt(_careNavigationIndexKey, index); + } +} diff --git a/lib/services/get/favorites_controller.dart b/lib/services/get/favorites_controller.dart index 502788e..840019f 100644 --- a/lib/services/get/favorites_controller.dart +++ b/lib/services/get/favorites_controller.dart @@ -28,9 +28,13 @@ class FavoritesController extends GetxController { } void showFilterOptions(BuildContext context) { + // 先获取当前值,避免在弹窗中使用 Obx + final currentSortByTime = sortByTime.value; + final currentLikesFirst = likesFirst.value; + showModalBottomSheet( context: context, - builder: (context) => Container( + builder: (BuildContext context) => Container( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, @@ -43,54 +47,51 @@ class FavoritesController extends GetxController { ListTile( leading: const Icon(Icons.date_range), title: const Text('按时间排序'), - trailing: Obx( - () => Icon( - sortByTime.value - ? Icons.radio_button_checked - : Icons.radio_button_unchecked, - color: AppConstants.primaryColor, - ), + trailing: Icon( + currentSortByTime + ? Icons.radio_button_checked + : Icons.radio_button_unchecked, + color: AppConstants.primaryColor, ), onTap: () { Navigator.pop(context); sortByTime.value = true; - Get.snackbar('提示', '已按时间排序'); - // 触发排序更新 - update(); + // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar + Future.delayed(const Duration(milliseconds: 100), () { + Get.snackbar('提示', '已按时间排序'); + }); }, ), ListTile( leading: const Icon(Icons.title), title: const Text('按分类排序'), - trailing: Obx( - () => Icon( - !sortByTime.value - ? Icons.radio_button_checked - : Icons.radio_button_unchecked, - color: AppConstants.primaryColor, - ), + trailing: Icon( + !currentSortByTime + ? Icons.radio_button_checked + : Icons.radio_button_unchecked, + color: AppConstants.primaryColor, ), onTap: () { Navigator.pop(context); sortByTime.value = false; - Get.snackbar('提示', '已按分类排序'); - // 触发排序更新 - update(); + // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar + Future.delayed(const Duration(milliseconds: 100), () { + Get.snackbar('提示', '已按分类排序'); + }); }, ), const Divider(), ListTile( leading: const Icon(Icons.swap_vert), - title: Text(likesFirst.value ? '点赞在前' : '笔记在前'), - trailing: Obx( - () => Icon(Icons.swap_vert, color: AppConstants.primaryColor), - ), + title: Text(currentLikesFirst ? '点赞在前' : '笔记在前'), + trailing: Icon(Icons.swap_vert, color: AppConstants.primaryColor), onTap: () { Navigator.pop(context); likesFirst.value = !likesFirst.value; - Get.snackbar('提示', likesFirst.value ? '点赞在前' : '笔记在前'); - // 触发顺序更新 - update(); + // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar + Future.delayed(const Duration(milliseconds: 100), () { + Get.snackbar('提示', likesFirst.value ? '点赞在前' : '笔记在前'); + }); }, ), ], diff --git a/lib/services/get/theme_controller.dart b/lib/services/get/theme_controller.dart index 5d1e057..f54b3e3 100644 --- a/lib/services/get/theme_controller.dart +++ b/lib/services/get/theme_controller.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../../models/colors/theme_colors.dart'; import '../../models/night-mode/theme_model.dart'; /// 主题控制器 @@ -40,6 +41,14 @@ class ThemeController extends GetxController { bool get enableAnimation => _enableAnimation.value; bool get enableBlurEffect => _enableBlurEffect.value; + // 获取当前主题颜色 + Color get currentThemeColor => + ThemeColors.getThemeColor(_themeColorIndex.value); + + // 获取当前强调色 + Color get currentAccentColor => + ThemeColors.getAccentColor(_accentColorIndex.value); + /// 获取当前 Flutter ThemeMode ThemeMode get currentThemeMode { if (_isDarkMode.value) { @@ -71,9 +80,11 @@ class ThemeController extends GetxController { _prefs = await SharedPreferences.getInstance(); _isDarkMode.value = _prefs?.getBool(_darkModeKey) ?? false; - _themeMode.value = AppThemeMode.values[ - (_prefs?.getInt(_themeModeKey) ?? 0).clamp(0, AppThemeMode.values.length - 1) - ]; + _themeMode.value = + AppThemeMode.values[(_prefs?.getInt(_themeModeKey) ?? 0).clamp( + 0, + AppThemeMode.values.length - 1, + )]; _themeColorIndex.value = _prefs?.getInt(_themeColorIndexKey) ?? 0; _accentColorIndex.value = _prefs?.getInt(_accentColorIndexKey) ?? 0; _fontSizeIndex.value = _prefs?.getInt(_fontSizeIndexKey) ?? 1; @@ -102,6 +113,14 @@ class ThemeController extends GetxController { Get.changeThemeMode(currentThemeMode); } + /// 应用主题颜色到 GetX + void _applyThemeColor() { + // 这里可以根据需要创建新的主题并应用 + // 由于我们使用的是 GetX 的主题系统, + // 我们可以通过更新全局状态来让组件响应主题颜色变化 + update(); + } + /// 切换深色模式 /// [enabled] true 开启深色模式, false 关闭深色模式 Future toggleDarkMode(bool enabled) async { @@ -144,6 +163,17 @@ class ThemeController extends GetxController { _themeColorIndex.value = index; await _saveThemeSettings(); + _applyThemeColor(); + + // 显示提示 + Get.snackbar( + '主题颜色', + '已更换主题颜色', + snackPosition: SnackPosition.BOTTOM, + duration: const Duration(seconds: 2), + margin: const EdgeInsets.all(16), + borderRadius: 12, + ); } /// 设置强调色索引 @@ -152,6 +182,17 @@ class ThemeController extends GetxController { _accentColorIndex.value = index; await _saveThemeSettings(); + _applyThemeColor(); + + // 显示提示 + Get.snackbar( + '强调颜色', + '已更换强调颜色', + snackPosition: SnackPosition.BOTTOM, + duration: const Duration(seconds: 2), + margin: const EdgeInsets.all(16), + borderRadius: 12, + ); } /// 设置字体大小索引 diff --git a/lib/views/active/active_search_page.dart b/lib/views/active/active_search_page.dart index e24efb8..5370052 100644 --- a/lib/views/active/active_search_page.dart +++ b/lib/views/active/active_search_page.dart @@ -304,7 +304,8 @@ class _ActiveSearchPageState extends State ), ), selected: _field.isEmpty, - selectedColor: AppConstants.primaryColor, + selectedColor: + _themeController.currentThemeColor, backgroundColor: isDark ? Colors.grey[800] : Colors.grey[200], @@ -327,7 +328,8 @@ class _ActiveSearchPageState extends State ), ), selected: _field == 'name', - selectedColor: AppConstants.primaryColor, + selectedColor: + _themeController.currentThemeColor, backgroundColor: isDark ? Colors.grey[800] : Colors.grey[200], @@ -350,7 +352,8 @@ class _ActiveSearchPageState extends State ), ), selected: _field == 'keywords', - selectedColor: AppConstants.primaryColor, + selectedColor: + _themeController.currentThemeColor, backgroundColor: isDark ? Colors.grey[800] : Colors.grey[200], @@ -373,7 +376,8 @@ class _ActiveSearchPageState extends State ), ), selected: _field == 'introduce', - selectedColor: AppConstants.primaryColor, + selectedColor: + _themeController.currentThemeColor, backgroundColor: isDark ? Colors.grey[800] : Colors.grey[200], @@ -402,7 +406,7 @@ class _ActiveSearchPageState extends State ), Expanded( child: RefreshIndicator( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, onRefresh: () async { await _runSearch(reset: true); }, @@ -426,7 +430,7 @@ class _ActiveSearchPageState extends State ); } }, - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, foregroundColor: Colors.white, tooltip: '返回上一页', child: const Icon(Icons.arrow_back), diff --git a/lib/views/active/category_page.dart b/lib/views/active/category_page.dart index 4c820eb..23ac10a 100644 --- a/lib/views/active/category_page.dart +++ b/lib/views/active/category_page.dart @@ -19,6 +19,7 @@ class CategoryPage extends StatelessWidget { return Obx(() { final isDark = themeController.isDarkModeRx.value; + final themeColor = themeController.currentThemeColor; return Column( children: [ @@ -41,11 +42,11 @@ class CategoryPage extends StatelessWidget { ), ) .toList(), - labelColor: AppConstants.primaryColor, + labelColor: themeColor, unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], - indicatorColor: AppConstants.primaryColor, + indicatorColor: themeColor, indicatorWeight: 3, labelStyle: const TextStyle( fontWeight: FontWeight.w600, @@ -71,11 +72,13 @@ class CategoryPage extends StatelessWidget { controller.sceneData, controller.tabCategories[0]['label'] as String, isDark, + themeColor, ), _buildCategoryList( controller.dynastyData, controller.tabCategories[1]['label'] as String, isDark, + themeColor, ), ], ), @@ -90,6 +93,7 @@ class CategoryPage extends StatelessWidget { Map> data, String categoryType, bool isDark, + Color themeColor, ) { return ListView.separated( padding: const EdgeInsets.symmetric(vertical: 8), @@ -138,14 +142,14 @@ class CategoryPage extends StatelessWidget { vertical: 4, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(26), + color: themeColor.withAlpha(26), borderRadius: BorderRadius.circular(12), ), child: Text( '${items.length}', style: TextStyle( fontSize: 13, - color: AppConstants.primaryColor, + color: themeColor, fontWeight: FontWeight.w600, ), ), @@ -157,7 +161,12 @@ class CategoryPage extends StatelessWidget { spacing: 10, runSpacing: 10, children: items.map((item) { - return _buildCategoryChip(item, categoryType, isDark); + return _buildCategoryChip( + item, + categoryType, + isDark, + themeColor, + ); }).toList(), ), ], @@ -169,7 +178,12 @@ class CategoryPage extends StatelessWidget { ); } - Widget _buildCategoryChip(String label, String categoryType, bool isDark) { + Widget _buildCategoryChip( + String label, + String categoryType, + bool isDark, + Color themeColor, + ) { final controller = Get.find(); return GestureDetector( @@ -179,17 +193,14 @@ class CategoryPage extends StatelessWidget { child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(26), + color: themeColor.withAlpha(26), borderRadius: BorderRadius.circular(20), - border: Border.all( - color: AppConstants.primaryColor.withAlpha(77), - width: 1, - ), + border: Border.all(color: themeColor.withAlpha(77), width: 1), ), child: Text( label, style: TextStyle( - color: AppConstants.primaryColor, + color: themeColor, fontSize: 14, fontWeight: FontWeight.w500, ), diff --git a/lib/views/active/popular_page.dart b/lib/views/active/popular_page.dart index 2ee3098..f5bc5af 100644 --- a/lib/views/active/popular_page.dart +++ b/lib/views/active/popular_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; import '../../utils/http/http_client.dart'; @@ -6,6 +7,7 @@ import '../../models/poetry_model.dart'; import '../../controllers/load/locally.dart'; import '../../controllers/history_controller.dart'; import '../../services/network_listener_service.dart'; +import '../../services/get/theme_controller.dart'; /// 时间: 2026-03-25 /// 功能: 热门页面 @@ -22,6 +24,7 @@ class PopularPage extends StatefulWidget { class _PopularPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; + final ThemeController _themeController = Get.find(); final List> _tabCategories = [ {'label': '总榜', 'icon': Icons.bar_chart}, {'label': '日榜', 'icon': Icons.today}, @@ -53,58 +56,81 @@ class _PopularPageState extends State @override Widget build(BuildContext context) { - return Column( - children: [ - // 黑色分割线 - Container(height: 1, color: Colors.black.withValues(alpha: 0.1)), - // Tab栏 - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - child: TabBar( - controller: _tabController, - tabs: _tabCategories - .map( - (category) => Tab( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(category['icon'], size: 16), - const SizedBox(width: 6), - Text(category['label']), - ], + return Obx(() { + final isDark = _themeController.isDarkModeRx.value; + final themeColor = _themeController.currentThemeColor; + + return Column( + children: [ + // 分割线 + Container( + height: 1, + color: isDark ? Colors.grey[800] : Colors.black.withAlpha(10), + ), + // Tab栏 + Container( + color: isDark ? Colors.grey[900] : Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: TabBar( + controller: _tabController, + tabs: _tabCategories + .map( + (category) => Tab( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(category['icon'], size: 16), + const SizedBox(width: 6), + Text(category['label']), + ], + ), ), - ), - ) - .toList(), - labelColor: AppConstants.primaryColor, - unselectedLabelColor: Colors.grey[600], - indicatorColor: AppConstants.primaryColor, - indicatorWeight: 3, - labelStyle: const TextStyle(fontWeight: FontWeight.bold), + ) + .toList(), + labelColor: themeColor, + unselectedLabelColor: isDark + ? Colors.grey[400] + : Colors.grey[600], + indicatorColor: themeColor, + indicatorWeight: 3, + labelStyle: const TextStyle(fontWeight: FontWeight.bold), + ), ), - ), - // 内容区域 - Expanded( - child: TabBarView( - controller: _tabController, - children: _tabCategories.map((category) { - return _buildRankContent(category['label']); - }).toList(), + // 内容区域 + Expanded( + child: Container( + color: isDark ? const Color(0xFF121212) : Colors.grey[50], + child: TabBarView( + controller: _tabController, + children: _tabCategories.map((category) { + return _buildRankContent( + category['label'], + isDark, + themeColor, + ); + }).toList(), + ), + ), ), - ), - ], - ); + ], + ); + }); } - Widget _buildRankContent(String category) { + Widget _buildRankContent(String category, bool isDark, Color themeColor) { if (_loading) { - return const Center( + return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - CircularProgressIndicator(), - SizedBox(height: 16), - Text('正在加载排行榜...'), + CircularProgressIndicator(color: themeColor), + const SizedBox(height: 16), + Text( + '正在加载排行榜...', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.grey[600], + ), + ), ], ), ); @@ -115,12 +141,25 @@ class _PopularPageState extends State child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.error_outline, size: 64, color: Colors.grey), + Icon( + Icons.error_outline, + size: 64, + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), const SizedBox(height: 16), - Text(_errorMessage, style: const TextStyle(color: Colors.grey)), + Text( + _errorMessage, + style: TextStyle( + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + ), const SizedBox(height: 16), ElevatedButton( onPressed: _loadRankList, + style: ElevatedButton.styleFrom( + backgroundColor: themeColor, + foregroundColor: Colors.white, + ), child: const Text('🔄 重试'), ), ], @@ -129,17 +168,29 @@ class _PopularPageState extends State } if (_rankList.isEmpty) { - return const Center( + return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.bar_chart, size: 64, color: Colors.grey), - SizedBox(height: 16), - Text('暂无排行数据', style: TextStyle(color: Colors.grey)), - SizedBox(height: 8), + Icon( + Icons.bar_chart, + size: 64, + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + const SizedBox(height: 16), + Text( + '暂无排行数据', + style: TextStyle( + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + ), + const SizedBox(height: 8), Text( '换个时间段试试吧', - style: TextStyle(color: Colors.grey, fontSize: 12), + style: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[600], + fontSize: 12, + ), ), ], ), @@ -147,6 +198,7 @@ class _PopularPageState extends State } return RefreshIndicator( + color: themeColor, onRefresh: () async => await _loadRankList(forceRefresh: true), child: NotificationListener( onNotification: (scrollNotification) { @@ -167,14 +219,24 @@ class _PopularPageState extends State itemCount: _rankList.length + (_showBottomIndicator ? 1 : 0), itemBuilder: (context, index) { if (index == _rankList.length) { - return const Center( + return Center( child: Padding( - padding: EdgeInsets.all(16), - child: Text('到底了', style: TextStyle(color: Colors.grey)), + padding: const EdgeInsets.all(16), + child: Text( + '到底了', + style: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[600], + ), + ), ), ); } - return _buildRankItem(_rankList[index], index + 1); + return _buildRankItem( + _rankList[index], + index + 1, + isDark, + themeColor, + ); }, ), ), @@ -223,19 +285,23 @@ class _PopularPageState extends State } } - Widget _buildRankItem(PoetryModel poetry, int index) { + Widget _buildRankItem( + PoetryModel poetry, + int index, + bool isDark, + Color themeColor, + ) { final rank = poetry.rank > 0 ? poetry.rank : index; final isTopThree = rank <= 3; return Card( margin: const EdgeInsets.only(bottom: 12), elevation: isTopThree ? 4 : 2, + color: isDark ? Colors.grey[850] : Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide( - color: isTopThree - ? AppConstants.primaryColor - : AppConstants.primaryColor.withValues(alpha: 0.2), + color: isTopThree ? themeColor : themeColor.withAlpha(20), width: isTopThree ? 2 : 1, ), ), @@ -254,16 +320,12 @@ class _PopularPageState extends State width: 40, height: 40, decoration: BoxDecoration( - color: isTopThree - ? AppConstants.primaryColor - : AppConstants.primaryColor.withValues(alpha: 0.3), + color: isTopThree ? themeColor : themeColor.withAlpha(30), borderRadius: BorderRadius.circular(20), border: isTopThree ? null : Border.all( - color: AppConstants.primaryColor.withValues( - alpha: 0.2, - ), + color: themeColor.withAlpha(20), width: 1, ), ), @@ -273,9 +335,7 @@ class _PopularPageState extends State style: TextStyle( color: isTopThree ? Colors.white - : AppConstants.primaryColor.withValues( - alpha: 0.8, - ), + : themeColor.withAlpha(80), fontWeight: FontWeight.bold, fontSize: 16, ), @@ -292,8 +352,11 @@ class _PopularPageState extends State // 标题 Text( poetry.name, - style: Theme.of(context).textTheme.titleMedium - ?.copyWith(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: isDark ? Colors.white : Colors.black87, + ), maxLines: 2, overflow: TextOverflow.ellipsis, ), @@ -310,16 +373,14 @@ class _PopularPageState extends State vertical: 2, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues( - alpha: 0.1, - ), + color: themeColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), child: Text( poetry.alias, style: TextStyle( fontSize: 10, - color: AppConstants.primaryColor, + color: themeColor, ), ), ), @@ -331,7 +392,9 @@ class _PopularPageState extends State poetry.url, style: TextStyle( fontSize: 12, - color: Colors.grey[600], + color: isDark + ? Colors.grey[400] + : Colors.grey[600], ), overflow: TextOverflow.ellipsis, ), @@ -347,21 +410,29 @@ class _PopularPageState extends State '👁', poetry.hitsTotal.toString(), '总浏览', + isDark, ), const SizedBox(width: 16), - _buildStatItem('💖', poetry.like.toString(), '点赞'), + _buildStatItem( + '💖', + poetry.like.toString(), + '点赞', + isDark, + ), const SizedBox(width: 16), if (_tabController.index == 1) _buildStatItem( '📅', poetry.hitsDay.toString(), '今日', + isDark, ), if (_tabController.index == 2) _buildStatItem( '📊', poetry.hitsMonth.toString(), '本月', + isDark, ), ], ), @@ -382,14 +453,14 @@ class _PopularPageState extends State vertical: 6, ), decoration: BoxDecoration( - color: Colors.orange[700], + color: themeColor, borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: 0.15), + color: Colors.black.withAlpha(15), blurRadius: 4, offset: const Offset(0, 2), ), @@ -424,7 +495,7 @@ class _PopularPageState extends State ); } - Widget _buildStatItem(String icon, String value, String label) { + Widget _buildStatItem(String icon, String value, String label, bool isDark) { return Row( mainAxisSize: MainAxisSize.min, children: [ @@ -432,10 +503,20 @@ class _PopularPageState extends State const SizedBox(width: 4), Text( value, - style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: isDark ? Colors.grey[300] : Colors.black87, + ), ), const SizedBox(width: 2), - Text(label, style: TextStyle(fontSize: 10, color: Colors.grey[600])), + Text( + label, + style: TextStyle( + fontSize: 10, + color: isDark ? Colors.grey[500] : Colors.grey[600], + ), + ), ], ); } diff --git a/lib/views/active/rate.dart b/lib/views/active/rate.dart index 82f69ec..8b6d043 100644 --- a/lib/views/active/rate.dart +++ b/lib/views/active/rate.dart @@ -70,9 +70,9 @@ class _RatePageState extends State child: TabBar( controller: _tabController, tabs: _tabs.map((tab) => Tab(text: tab)).toList(), - labelColor: AppConstants.primaryColor, - unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], - indicatorColor: AppConstants.primaryColor, + labelColor: _themeController.currentThemeColor, + unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], + indicatorColor: _themeController.currentThemeColor, indicatorWeight: 2, labelStyle: const TextStyle(fontWeight: FontWeight.w600), ), @@ -438,27 +438,29 @@ class _RatePageState extends State } Color _getActivityColor(int value) { + final themeColor = _themeController.currentThemeColor; if (value == 0) { return Colors.grey[100]!; } else if (value >= 1 && value <= 5) { - return AppConstants.primaryColor.withAlpha(77); + return themeColor.withAlpha(77); } else if (value >= 6 && value <= 20) { - return AppConstants.primaryColor.withAlpha(128); + return themeColor.withAlpha(128); } else if (value >= 21 && value <= 100) { - return AppConstants.primaryColor.withAlpha(179); + return themeColor.withAlpha(179); } else { - return AppConstants.primaryColor; + return themeColor; } } Widget _buildSectionTitle(String title, bool isDark) { + final themeColor = _themeController.currentThemeColor; return Row( children: [ Container( width: 4, height: 20, decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: themeColor, borderRadius: BorderRadius.circular(2), ), ), @@ -497,9 +499,10 @@ class _RatePageState extends State } Widget _buildStatItem(String label, String value, IconData icon, bool isDark) { + final themeColor = _themeController.currentThemeColor; return Column( children: [ - Icon(icon, color: AppConstants.primaryColor, size: 24), + Icon(icon, color: themeColor, size: 24), const SizedBox(height: 8), Text( value, @@ -512,6 +515,7 @@ class _RatePageState extends State } Widget _buildLegend(bool isDark) { + final themeColor = _themeController.currentThemeColor; return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( @@ -531,10 +535,10 @@ class _RatePageState extends State runSpacing: 8, children: [ _buildLegendItem('无活跃', Colors.grey[100]!, isDark), - _buildLegendItem('1-5', AppConstants.primaryColor.withAlpha(77), isDark), - _buildLegendItem('6-20', AppConstants.primaryColor.withAlpha(128), isDark), - _buildLegendItem('21-100', AppConstants.primaryColor.withAlpha(179), isDark), - _buildLegendItem('100+', AppConstants.primaryColor, isDark), + _buildLegendItem('1-5', themeColor.withAlpha(77), isDark), + _buildLegendItem('6-20', themeColor.withAlpha(128), isDark), + _buildLegendItem('21-100', themeColor.withAlpha(179), isDark), + _buildLegendItem('100+', themeColor, isDark), ], ), ], diff --git a/lib/views/active/tags/corr_page.dart b/lib/views/active/tags/corr_page.dart index 02fca57..50fcf3b 100644 --- a/lib/views/active/tags/corr_page.dart +++ b/lib/views/active/tags/corr_page.dart @@ -231,7 +231,10 @@ class _CorrPageState extends State backgroundColor: isDark ? Colors.grey[900] : Colors.white, elevation: 0, leading: IconButton( - icon: Icon(Icons.arrow_back_ios, color: AppConstants.primaryColor), + icon: Icon( + Icons.arrow_back_ios, + color: _themeController.currentThemeColor, + ), onPressed: () => Navigator.pop(context), ), title: Column( @@ -298,7 +301,7 @@ class _CorrPageState extends State duration: const Duration(milliseconds: 300), child: RefreshIndicator( key: const ValueKey('list'), - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, onRefresh: _loadData, child: ListView.builder( controller: _scrollController, @@ -428,7 +431,7 @@ class _CorrPageState extends State ElevatedButton( onPressed: _loadData, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 32, @@ -486,7 +489,7 @@ class _CorrPageState extends State height: 24, child: CircularProgressIndicator( strokeWidth: 2, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), ), @@ -544,14 +547,16 @@ class _CorrPageState extends State vertical: 4, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(26), + color: _themeController.currentThemeColor.withAlpha( + 26, + ), borderRadius: BorderRadius.circular(8), ), child: Text( alias, style: TextStyle( fontSize: 12, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.w500, ), ), @@ -808,14 +813,18 @@ class _CorrPageState extends State }, icon: Icon( Icons.note_add, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), label: Text( '创建笔记', - style: TextStyle(color: AppConstants.primaryColor), + style: TextStyle( + color: _themeController.currentThemeColor, + ), ), style: OutlinedButton.styleFrom( - side: BorderSide(color: AppConstants.primaryColor), + side: BorderSide( + color: _themeController.currentThemeColor, + ), padding: const EdgeInsets.symmetric(vertical: 12), ), ), @@ -827,7 +836,7 @@ class _CorrPageState extends State icon: const Icon(Icons.favorite, color: Colors.white), label: const Text('点赞'), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), ), diff --git a/lib/views/discover_page.dart b/lib/views/discover_page.dart index d67a097..c80e24e 100644 --- a/lib/views/discover_page.dart +++ b/lib/views/discover_page.dart @@ -74,7 +74,7 @@ class _DiscoverPageState extends State backgroundColor: isDark ? Colors.grey[900] : Colors.white, foregroundColor: isDark ? Colors.white - : AppConstants.primaryColor, + : _themeController.currentThemeColor, leading: controller.categories[_tabController.index] == '热门' ? _buildInfoButton(context, isDark) : null, @@ -139,7 +139,7 @@ class _DiscoverPageState extends State child: Text( '💡 探索更多精彩内容,发现你感兴趣的诗词世界', style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontSize: 14, fontWeight: FontWeight.w400, ), @@ -213,12 +213,12 @@ class _DiscoverPageState extends State children: [ CircleAvatar( radius: 20, - backgroundColor: AppConstants.primaryColor.withValues( + backgroundColor: _themeController.currentThemeColor.withValues( alpha: 0.1, ), child: Icon( Icons.person, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 20, ), ), @@ -365,7 +365,7 @@ class _DiscoverPageState extends State return IconButton( icon: Icon( Icons.info_outline, - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : _themeController.currentThemeColor, ), onPressed: () => _showHotInfoPopup(buttonContext, isDark), ); @@ -414,7 +414,7 @@ class _DiscoverPageState extends State children: [ Icon( Icons.local_fire_department, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 20, ), const SizedBox(width: 8), diff --git a/lib/views/favorites_page.dart b/lib/views/favorites_page.dart index 12f50f8..d52b1fb 100644 --- a/lib/views/favorites_page.dart +++ b/lib/views/favorites_page.dart @@ -72,8 +72,10 @@ class _FavoritesPageState extends State tabBarScrollable: true, tabLabelPadding: const EdgeInsets.symmetric(horizontal: 10), backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.white, - foregroundColor: isDark ? Colors.white : Colors.black87, - actions: _buildAppBarActions(controller), + foregroundColor: isDark + ? Colors.white + : themeController.currentThemeColor, + actions: _buildAppBarActions(controller, context), ), body: Column( children: [ @@ -93,12 +95,20 @@ class _FavoritesPageState extends State } // 构建AppBar操作按钮 - List _buildAppBarActions(FavoritesController controller) { - final currentCategory = - controller.categories[controller.currentTabIndex.value]; + List _buildAppBarActions( + FavoritesController controller, + BuildContext context, + ) { final isDark = themeController.isDarkMode; List actions = [ + // 统一显示添加笔记按钮 + IconButton( + icon: Icon(Icons.add, color: isDark ? Colors.white70 : null), + onPressed: () { + Get.to(const CollectNotesPage()); + }, + ), IconButton( icon: Icon( controller.isGridView.value ? Icons.view_list : Icons.grid_view, @@ -108,23 +118,15 @@ class _FavoritesPageState extends State ), IconButton( icon: Icon(Icons.filter_list, color: isDark ? Colors.white70 : null), - onPressed: () => controller.showFilterOptions(context), + onPressed: () { + // 使用 Get.context 而不是传递的 context + if (Get.context != null) { + controller.showFilterOptions(Get.context!); + } + }, ), ]; - // 只在笔记页面显示添加笔记按钮 - if (currentCategory == '笔记') { - actions.insert( - 0, - IconButton( - icon: Icon(Icons.add, color: isDark ? Colors.white70 : null), - onPressed: () { - Get.to(const CollectNotesPage()); - }, - ), - ); - } - return actions; } diff --git a/lib/views/footprint/all_list.dart b/lib/views/footprint/all_list.dart index 1690f94..3a69fb8 100644 --- a/lib/views/footprint/all_list.dart +++ b/lib/views/footprint/all_list.dart @@ -178,11 +178,12 @@ class AllListPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final themeColor = _themeController.currentThemeColor; if (_isLoading && _cards.isEmpty) { return Center( child: CircularProgressIndicator( - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : themeColor, ), ); } @@ -216,7 +217,7 @@ class AllListPageState extends State { if (index == _cards.length) { return _buildBottomIndicator(isDark); } - return _buildCard(_cards[index], isDark); + return _buildCard(_cards[index], isDark, themeColor); }, ), ); @@ -285,25 +286,22 @@ class AllListPageState extends State { ); } - Widget _buildCard(UnifiedCard card, bool isDark) { + Widget _buildCard(UnifiedCard card, bool isDark, Color themeColor) { switch (card.type) { case CardType.like: - return _buildLikeCard(card.data as PoetryData, isDark); + return _buildLikeCard(card.data as PoetryData, isDark, themeColor); case CardType.note: return _buildNoteCard(card.data as Map, isDark); } } - Widget _buildLikeCard(PoetryData poetry, bool isDark) { + Widget _buildLikeCard(PoetryData poetry, bool isDark, Color themeColor) { return Container( margin: const EdgeInsets.only(bottom: 0), decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(10), - border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.2), - width: 1, - ), + border: Border.all(color: themeColor.withValues(alpha: 0.2), width: 1), boxShadow: [ BoxShadow( color: isDark @@ -340,7 +338,7 @@ class AllListPageState extends State { vertical: 4, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: themeColor.withValues(alpha: 0.1), borderRadius: const BorderRadius.only( topRight: Radius.circular(10), bottomLeft: Radius.circular(10), @@ -349,17 +347,13 @@ class AllListPageState extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon( - Icons.favorite, - size: 12, - color: AppConstants.primaryColor, - ), + Icon(Icons.favorite, size: 12, color: themeColor), const SizedBox(width: 3), Text( '点赞诗词', style: TextStyle( fontSize: 11, - color: AppConstants.primaryColor, + color: themeColor, fontWeight: FontWeight.w500, ), ), @@ -391,17 +385,10 @@ class AllListPageState extends State { children: [ TextButton.icon( onPressed: () => _showPoetryDetails(poetry), - icon: Icon( - Icons.visibility, - size: 14, - color: AppConstants.primaryColor, - ), + icon: Icon(Icons.visibility, size: 14, color: themeColor), label: Text( '查看详情', - style: TextStyle( - fontSize: 12, - color: AppConstants.primaryColor, - ), + style: TextStyle(fontSize: 12, color: themeColor), ), ), const Spacer(), diff --git a/lib/views/footprint/collect_notes.dart b/lib/views/footprint/collect_notes.dart index 29030bf..f4aaabb 100644 --- a/lib/views/footprint/collect_notes.dart +++ b/lib/views/footprint/collect_notes.dart @@ -198,6 +198,8 @@ class _CollectNotesPageState extends State { // 显示密码设置对话框 Future _showPasswordDialog() async { + final themeColor = _themeController.currentThemeColor; + final isDark = _themeController.isDarkMode; if (_password != null && _password!.isNotEmpty) { final action = await showDialog( context: context, @@ -207,7 +209,7 @@ class _CollectNotesPageState extends State { ), title: Row( children: [ - Icon(Icons.lock, color: AppConstants.primaryColor, size: 24), + Icon(Icons.lock, color: themeColor, size: 24), const SizedBox(width: 8), const Text('锁定设置'), ], @@ -218,18 +220,22 @@ class _CollectNotesPageState extends State { Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.grey[100], + color: isDark ? Colors.grey[800] : Colors.grey[100], borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.vpn_key, size: 16, color: Colors.grey[600]), + Icon( + Icons.vpn_key, + size: 16, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), const SizedBox(width: 8), Text( '当前密码: $_password', style: TextStyle( - color: Colors.grey[700], + color: isDark ? Colors.grey[400] : Colors.grey[700], fontSize: 13, fontWeight: FontWeight.w500, ), @@ -282,25 +288,21 @@ class _CollectNotesPageState extends State { horizontal: 16, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: themeColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: themeColor.withValues(alpha: 0.3), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.edit, - color: AppConstants.primaryColor, - size: 22, - ), + Icon(Icons.edit, color: themeColor, size: 22), const SizedBox(width: 10), Text( '修改密码', style: TextStyle( - color: AppConstants.primaryColor, + color: themeColor, fontSize: 15, fontWeight: FontWeight.w600, ), @@ -555,6 +557,7 @@ class _CollectNotesPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final themeColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -565,7 +568,7 @@ class _CollectNotesPageState extends State { leading: IconButton( icon: Icon( Icons.arrow_back, - color: isDark ? Colors.white70 : AppConstants.primaryColor, + color: isDark ? Colors.white70 : themeColor, ), onPressed: () => Navigator.of(context).pop(), ), @@ -590,7 +593,7 @@ class _CollectNotesPageState extends State { icon: Icon( _isLocked ? Icons.lock : Icons.lock_outline, color: _isLocked - ? AppConstants.primaryColor + ? themeColor : (isDark ? Colors.grey[400] : Colors.grey[600]), ), onPressed: _showPasswordDialog, @@ -600,7 +603,7 @@ class _CollectNotesPageState extends State { icon: Icon( _isPinned ? Icons.push_pin : Icons.push_pin_outlined, color: _isPinned - ? AppConstants.primaryColor + ? themeColor : (isDark ? Colors.grey[400] : Colors.grey[600]), ), onPressed: _togglePin, @@ -611,7 +614,7 @@ class _CollectNotesPageState extends State { body: _isLoading ? Center( child: CircularProgressIndicator( - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : themeColor, ), ) : GestureDetector( @@ -621,7 +624,7 @@ class _CollectNotesPageState extends State { }, child: Column( children: [ - _buildStatusBar(isDark), + _buildStatusBar(isDark, themeColor), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), @@ -629,9 +632,9 @@ class _CollectNotesPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - _buildTitleInput(isDark), + _buildTitleInput(isDark, themeColor), const SizedBox(height: 16), - _buildContentInput(isDark), + _buildContentInput(isDark, themeColor), ], ), ), @@ -643,7 +646,7 @@ class _CollectNotesPageState extends State { }); } - Widget _buildStatusBar(bool isDark) { + Widget _buildStatusBar(bool isDark, Color themeColor) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[50], @@ -696,27 +699,15 @@ class _CollectNotesPageState extends State { ), if (_isPinned) ...[ const SizedBox(width: 16), - Icon(Icons.push_pin, size: 14, color: AppConstants.primaryColor), + Icon(Icons.push_pin, size: 14, color: themeColor), const SizedBox(width: 4), - Text( - '已置顶', - style: TextStyle( - fontSize: 12, - color: AppConstants.primaryColor, - ), - ), + Text('已置顶', style: TextStyle(fontSize: 12, color: themeColor)), ], if (_isLocked) ...[ const SizedBox(width: 16), - Icon(Icons.lock, size: 14, color: AppConstants.primaryColor), + Icon(Icons.lock, size: 14, color: themeColor), const SizedBox(width: 4), - Text( - '已锁定', - style: TextStyle( - fontSize: 12, - color: AppConstants.primaryColor, - ), - ), + Text('已锁定', style: TextStyle(fontSize: 12, color: themeColor)), ], ], ), @@ -776,7 +767,7 @@ class _CollectNotesPageState extends State { ); } - Widget _buildTitleInput(bool isDark) { + Widget _buildTitleInput(bool isDark, Color themeColor) { return Row( children: [ Expanded( @@ -786,7 +777,7 @@ class _CollectNotesPageState extends State { borderRadius: BorderRadius.circular(12), border: Border.all( color: _titleFocusNode.hasFocus - ? AppConstants.primaryColor.withValues(alpha: 0.5) + ? themeColor.withValues(alpha: 0.5) : (isDark ? Colors.grey[700]! : Colors.grey.withValues(alpha: 0.2)), @@ -859,11 +850,7 @@ class _CollectNotesPageState extends State { child: Row( children: [ if (category == _category) - Icon( - Icons.check, - size: 16, - color: AppConstants.primaryColor, - ), + Icon(Icons.check, size: 16, color: themeColor), if (category == _category) const SizedBox(width: 8), Text( category, @@ -884,11 +871,7 @@ class _CollectNotesPageState extends State { if (!_categoryOptions.contains(_category) && _category != null && _category!.isNotEmpty) - Icon( - Icons.check, - size: 16, - color: AppConstants.primaryColor, - ), + Icon(Icons.check, size: 16, color: themeColor), if (!_categoryOptions.contains(_category) && _category != null && _category!.isNotEmpty) @@ -917,18 +900,11 @@ class _CollectNotesPageState extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon( - Icons.folder_outlined, - size: 18, - color: AppConstants.primaryColor, - ), + Icon(Icons.folder_outlined, size: 18, color: themeColor), const SizedBox(width: 4), Text( _category ?? '分类', - style: TextStyle( - fontSize: 14, - color: AppConstants.primaryColor, - ), + style: TextStyle(fontSize: 14, color: themeColor), ), Icon( Icons.arrow_drop_down, @@ -944,7 +920,7 @@ class _CollectNotesPageState extends State { ); } - Widget _buildContentInput(bool isDark) { + Widget _buildContentInput(bool isDark, Color themeColor) { return Container( constraints: const BoxConstraints(minHeight: 300), decoration: BoxDecoration( @@ -952,7 +928,7 @@ class _CollectNotesPageState extends State { borderRadius: BorderRadius.circular(12), border: Border.all( color: _contentFocusNode.hasFocus - ? AppConstants.primaryColor.withValues(alpha: 0.5) + ? themeColor.withValues(alpha: 0.5) : (isDark ? Colors.grey[700]! : Colors.grey.withValues(alpha: 0.2)), diff --git a/lib/views/footprint/footprint_page.dart b/lib/views/footprint/footprint_page.dart index b501600..7e5b0f3 100644 --- a/lib/views/footprint/footprint_page.dart +++ b/lib/views/footprint/footprint_page.dart @@ -100,6 +100,7 @@ class _FootprintPageState extends State try { // 从SQLite获取完整数据 final likedList = await HistoryController.getLikedHistory(); + final themeColor = _themeController.currentThemeColor; // 查找对应的诗词数据,优先使用存储的完整数据 Map poetryData; @@ -136,7 +137,9 @@ class _FootprintPageState extends State width: 40, height: 4, decoration: BoxDecoration( - color: Colors.grey[300], + color: _themeController.isDarkMode + ? Colors.grey[700] + : Colors.grey[300], borderRadius: BorderRadius.circular(2), ), ), @@ -146,17 +149,16 @@ class _FootprintPageState extends State padding: const EdgeInsets.all(16), child: Row( children: [ - Icon( - Icons.article, - color: AppConstants.primaryColor, - size: 24, - ), + Icon(Icons.article, color: themeColor, size: 24), const SizedBox(width: 8), - const Text( + Text( '诗词详情', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, + color: _themeController.isDarkMode + ? Colors.white + : Colors.black, ), ), const Spacer(), @@ -174,7 +176,9 @@ class _FootprintPageState extends State padding: const EdgeInsets.all(8), child: Icon( Icons.more_horiz, - color: Colors.grey[600], + color: _themeController.isDarkMode + ? Colors.grey[400] + : Colors.grey[600], size: 20, ), ), @@ -184,7 +188,9 @@ class _FootprintPageState extends State IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.close), - color: Colors.grey[600], + color: _themeController.isDarkMode + ? Colors.grey[400] + : Colors.grey[600], ), ], ), @@ -202,7 +208,7 @@ class _FootprintPageState extends State '精选诗句', poetryData['name'] ?? poetry.name, Icons.format_quote, - AppConstants.primaryColor, + themeColor, ), // 时间和标签 - 同一行 @@ -277,7 +283,7 @@ class _FootprintPageState extends State '译文/介绍', poetryData['introduce'], Icons.translate, - AppConstants.primaryColor, + themeColor, ), // 原文 - 单独一行 @@ -319,6 +325,7 @@ class _FootprintPageState extends State IconData icon, Color accentColor, ) { + final isDark = _themeController.isDarkMode; return Container( width: double.infinity, margin: const EdgeInsets.only(bottom: 12), @@ -361,9 +368,9 @@ class _FootprintPageState extends State padding: const EdgeInsets.all(12), child: Text( content, - style: const TextStyle( + style: TextStyle( fontSize: 15, - color: Colors.black87, + color: isDark ? Colors.white : Colors.black87, height: 1.5, ), ), @@ -405,27 +412,26 @@ class _FootprintPageState extends State Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final themeColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.grey[50], appBar: AppBar( title: const Text('点赞足迹'), - backgroundColor: isDark - ? const Color(0xFF2A2A2A) - : AppConstants.primaryColor, + backgroundColor: isDark ? const Color(0xFF2A2A2A) : themeColor, foregroundColor: Colors.white, elevation: 0, ), - body: _buildBody(isDark), + body: _buildBody(isDark, themeColor), ); }); } - Widget _buildBody(bool isDark) { + Widget _buildBody(bool isDark, Color themeColor) { if (_isLoading) { return Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( - isDark ? Colors.white : AppConstants.primaryColor, + isDark ? Colors.white : themeColor, ), ), ); @@ -453,7 +459,7 @@ class _FootprintPageState extends State ElevatedButton( onPressed: _loadLikedPoetry, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: themeColor, foregroundColor: Colors.white, ), child: const Text('重试'), @@ -506,16 +512,14 @@ class _FootprintPageState extends State Icon( Icons.refresh, size: 20, - color: isDark ? Colors.white70 : AppConstants.primaryColor, + color: isDark ? Colors.white70 : themeColor, ), const SizedBox(width: 8), Text( '下拉刷新列表', style: TextStyle( fontSize: 14, - color: isDark - ? Colors.white70 - : AppConstants.primaryColor, + color: isDark ? Colors.white70 : themeColor, fontWeight: FontWeight.w500, ), ), @@ -537,7 +541,7 @@ class _FootprintPageState extends State itemCount: _likedPoetryList.length, itemBuilder: (context, index) { final poetry = _likedPoetryList[index]; - return _buildLikedPoetryCard(poetry, isDark); + return _buildLikedPoetryCard(poetry, isDark, themeColor); }, ), ), @@ -546,7 +550,11 @@ class _FootprintPageState extends State ); } - Widget _buildLikedPoetryCard(PoetryData poetry, bool isDark) { + Widget _buildLikedPoetryCard( + PoetryData poetry, + bool isDark, + Color themeColor, + ) { return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( @@ -587,20 +595,20 @@ class _FootprintPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withValues(alpha: 0.1), - AppConstants.primaryColor.withValues(alpha: 0.05), + themeColor.withValues(alpha: 0.1), + themeColor.withValues(alpha: 0.05), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.2), + color: themeColor.withValues(alpha: 0.2), width: 1, ), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: themeColor.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 2), ), @@ -611,11 +619,7 @@ class _FootprintPageState extends State children: [ Row( children: [ - Icon( - Icons.format_quote, - color: AppConstants.primaryColor, - size: 20, - ), + Icon(Icons.format_quote, color: themeColor, size: 20), const SizedBox(width: 8), Expanded( child: Text( @@ -623,7 +627,7 @@ class _FootprintPageState extends State style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: AppConstants.primaryColor, + color: themeColor, ), ), ), @@ -702,7 +706,7 @@ class _FootprintPageState extends State icon: const Icon(Icons.visibility, size: 18), label: const Text('查看详情'), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: themeColor, foregroundColor: Colors.white, elevation: 2, shape: RoundedRectangleBorder( diff --git a/lib/views/footprint/liked_poetry_manager.dart b/lib/views/footprint/liked_poetry_manager.dart index 2f30c2d..6cd5569 100644 --- a/lib/views/footprint/liked_poetry_manager.dart +++ b/lib/views/footprint/liked_poetry_manager.dart @@ -14,6 +14,8 @@ import '../../../config/app_config.dart'; import '../../../controllers/history_controller.dart'; import '../../../utils/http/poetry_api.dart'; import '../../../services/network_listener_service.dart'; +import '../../../services/get/theme_controller.dart'; +import 'package:get/get.dart'; import '../home/set/home_components.dart'; /// 点赞诗词管理器 @@ -295,6 +297,7 @@ class _LikedPoetryManagerState extends State bool _isLoading = false; String _errorMessage = ''; StreamSubscription? _networkSubscription; + final ThemeController _themeController = Get.find(); @override void initState() { @@ -393,14 +396,21 @@ class _LikedPoetryManagerState extends State @override Widget build(BuildContext context) { - return _buildLikedPoetryList(); + return Obx(() { + return _buildLikedPoetryList(); + }); } Widget _buildLikedPoetryList() { + final themeColor = _themeController.currentThemeColor; + final isDark = _themeController.isDarkMode; + if (_isLoading) { - return const Center( + return Center( child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(AppConstants.primaryColor), + valueColor: AlwaysStoppedAnimation( + isDark ? Colors.white : themeColor, + ), ), ); } @@ -420,7 +430,7 @@ class _LikedPoetryManagerState extends State ElevatedButton( onPressed: _loadLikedPoetry, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: themeColor, foregroundColor: Colors.white, ), child: const Text('重试'), @@ -435,16 +445,26 @@ class _LikedPoetryManagerState extends State child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.favorite_border, size: 64, color: Colors.grey[400]), + Icon( + Icons.favorite_border, + size: 64, + color: isDark ? Colors.grey[600] : Colors.grey[400], + ), const SizedBox(height: 16), Text( '暂无点赞记录', - style: TextStyle(fontSize: 16, color: Colors.grey[600]), + style: TextStyle( + fontSize: 16, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), ), const SizedBox(height: 8), Text( '去主页点赞喜欢的诗词吧', - style: TextStyle(fontSize: 14, color: Colors.grey[500]), + style: TextStyle( + fontSize: 14, + color: isDark ? Colors.grey[500] : Colors.grey[500], + ), ), ], ), @@ -464,44 +484,61 @@ class _LikedPoetryManagerState extends State itemCount: _likedPoetryList.length + 1, itemBuilder: (context, index) { if (index == _likedPoetryList.length) { - return _buildBottomIndicator(); + return _buildBottomIndicator(isDark); } final poetry = _likedPoetryList[index]; - return _buildLikedPoetryCard(poetry); + return _buildLikedPoetryCard(poetry, themeColor, isDark); }, ), ); } - Widget _buildBottomIndicator() { + Widget _buildBottomIndicator(bool isDark) { return Container( padding: const EdgeInsets.symmetric(vertical: 24), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Container(width: 40, height: 1, color: Colors.grey[300]), + Container( + width: 40, + height: 1, + color: isDark ? Colors.grey[700] : Colors.grey[300], + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( '到底了', - style: TextStyle(fontSize: 12, color: Colors.grey[400]), + style: TextStyle( + fontSize: 12, + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), ), ), - Container(width: 40, height: 1, color: Colors.grey[300]), + Container( + width: 40, + height: 1, + color: isDark ? Colors.grey[700] : Colors.grey[300], + ), ], ), ); } - Widget _buildLikedPoetryCard(PoetryData poetry) { + Widget _buildLikedPoetryCard( + PoetryData poetry, + Color themeColor, + bool isDark, + ) { return Container( margin: const EdgeInsets.only(bottom: 8), decoration: BoxDecoration( - color: Colors.white, + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: 0.03), + color: isDark + ? Colors.black.withValues(alpha: 0.3) + : Colors.black.withValues(alpha: 0.03), blurRadius: 4, offset: const Offset(0, 1), ), @@ -519,15 +556,15 @@ class _LikedPoetryManagerState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withValues(alpha: 0.1), - AppConstants.primaryColor.withValues(alpha: 0.05), + themeColor.withValues(alpha: 0.1), + themeColor.withValues(alpha: 0.05), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(6), border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.2), + color: themeColor.withValues(alpha: 0.2), width: 1, ), ), @@ -537,18 +574,14 @@ class _LikedPoetryManagerState extends State children: [ Row( children: [ - Icon( - Icons.format_quote, - color: AppConstants.primaryColor, - size: 14, - ), + Icon(Icons.format_quote, color: themeColor, size: 14), const SizedBox(width: 4), Text( '精选诗句', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w500, - color: AppConstants.primaryColor, + color: themeColor, ), ), ], @@ -556,10 +589,10 @@ class _LikedPoetryManagerState extends State const SizedBox(height: 4), Text( poetry.name, - style: const TextStyle( + style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: Colors.black87, + color: isDark ? Colors.white : Colors.black87, height: 1.2, ), ), @@ -573,7 +606,10 @@ class _LikedPoetryManagerState extends State padding: const EdgeInsets.fromLTRB(8, 4, 8, 2), child: Text( "出处:${poetry.url}", - style: TextStyle(fontSize: 11, color: Colors.grey[600]), + style: TextStyle( + fontSize: 11, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -613,7 +649,7 @@ class _LikedPoetryManagerState extends State icon: const Icon(Icons.visibility, size: 14), label: const Text('查看详情', style: TextStyle(fontSize: 12)), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: themeColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), diff --git a/lib/views/footprint/local_jilu.dart b/lib/views/footprint/local_jilu.dart index 0375590..26ee8ea 100644 --- a/lib/views/footprint/local_jilu.dart +++ b/lib/views/footprint/local_jilu.dart @@ -78,17 +78,18 @@ class _LocalNotesListState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final themeColor = _themeController.currentThemeColor; if (_isLoadingNotes && _notes.isEmpty) { return Center( child: CircularProgressIndicator( - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : themeColor, ), ); } if (_notes.isEmpty) { - return _buildEmptyNotes(isDark); + return _buildEmptyNotes(isDark, themeColor); } return RefreshIndicator( @@ -107,7 +108,7 @@ class _LocalNotesListState extends State { return _buildBottomIndicator(isDark); } final note = _notes[index]; - return _buildNoteCard(note, isDark); + return _buildNoteCard(note, isDark, themeColor); }, ), ); @@ -145,7 +146,7 @@ class _LocalNotesListState extends State { ); } - Widget _buildEmptyNotes(bool isDark) { + Widget _buildEmptyNotes(bool isDark, Color themeColor) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -176,7 +177,7 @@ class _LocalNotesListState extends State { ); } - Widget _buildNoteCard(Map note, bool isDark) { + Widget _buildNoteCard(Map note, bool isDark, Color themeColor) { final title = note['title'] as String? ?? ''; final content = note['content'] as String? ?? ''; final timeStr = note['time'] as String? ?? ''; @@ -272,7 +273,7 @@ class _LocalNotesListState extends State { vertical: 2, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues( + color: themeColor.withValues( alpha: 0.1, ), borderRadius: BorderRadius.circular(10), @@ -281,7 +282,7 @@ class _LocalNotesListState extends State { category, style: TextStyle( fontSize: 10, - color: AppConstants.primaryColor, + color: themeColor, ), ), ), @@ -292,7 +293,7 @@ class _LocalNotesListState extends State { child: Icon( Icons.lock, size: 16, - color: AppConstants.primaryColor, + color: themeColor, ), ), GestureDetector( @@ -305,7 +306,7 @@ class _LocalNotesListState extends State { : Icons.push_pin_outlined, size: 16, color: isPinned - ? AppConstants.primaryColor + ? themeColor : (isDark ? Colors.grey[500] : Colors.grey[400]), @@ -418,7 +419,7 @@ class _LocalNotesListState extends State { Icon( Icons.lock, size: 28, - color: AppConstants.primaryColor, + color: themeColor, ), const SizedBox(width: 12), Column( @@ -430,7 +431,7 @@ class _LocalNotesListState extends State { '已锁定', style: TextStyle( fontSize: 14, - color: AppConstants.primaryColor, + color: themeColor, fontWeight: FontWeight.w500, ), ), diff --git a/lib/views/home/care/care-page.dart b/lib/views/home/care/care-page.dart new file mode 100644 index 0000000..01b69fe --- /dev/null +++ b/lib/views/home/care/care-page.dart @@ -0,0 +1,478 @@ +/// 时间: 2026-04-02 +/// 功能: 关怀页面 +/// 介绍: 简约大字风格的关怀功能页面 +/// 最新变化: 2026-04-02 添加多个按钮和文本描述区域 + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../services/get/theme_controller.dart'; +import '../../../services/get/care_controller.dart'; + +class CarePage extends StatefulWidget { + const CarePage({super.key}); + + @override + State createState() => _CarePageState(); +} + +class _CarePageState extends State { + final CareController _careController = Get.find(); + bool _readAloudEnabled = false; + final List _options = ['诗词', '出处', '译文', '更多', '原文', '问候语']; + + @override + Widget build(BuildContext context) { + final themeController = Get.find(); + final isDark = themeController.isDarkModeRx.value; + final primaryColor = themeController.currentThemeColor; + + return Scaffold( + backgroundColor: isDark ? const Color(0xFF121212) : Colors.white, + appBar: AppBar( + title: Text( + '关怀', + style: TextStyle( + color: isDark ? Colors.white : primaryColor, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.white, + elevation: 0, + leading: IconButton( + icon: Icon( + Icons.arrow_back, + color: isDark ? Colors.white : primaryColor, + ), + onPressed: () => Navigator.pop(context), + ), + actions: [ + IconButton( + icon: Icon( + Icons.info_outline, + color: isDark ? Colors.white : primaryColor, + ), + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: isDark + ? const Color(0xFF2A2A2A) + : Colors.white, + title: Text( + '功能说明', + style: TextStyle( + color: isDark ? Colors.white : Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + content: Text( + '该功能处于开发状态,限时免费使用\n待后续开发完成后,使用需付费激活\n其他功能不受影响。', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.grey[700], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('确定', style: TextStyle(color: primaryColor)), + ), + ], + ), + ); + }, + ), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(32), + child: Column( + children: [ + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(Icons.people, size: 80, color: primaryColor), + const SizedBox(width: 32), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '关怀', + style: TextStyle( + fontSize: 48, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + const SizedBox(height: 16), + Text( + '用心呵护每一位用户', + style: TextStyle( + fontSize: 18, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + ), + ], + ), + ], + ), + ), + const SizedBox(height: 48), + _buildCareModeToggle(isDark, primaryColor), + const SizedBox(height: 24), + _buildUserTypeSelector(isDark, primaryColor), + const SizedBox(height: 24), + _buildPinyinToggle(isDark, primaryColor), + const SizedBox(height: 24), + _buildMultiSelectOptions(isDark, primaryColor), + const SizedBox(height: 24), + _buildDescriptionArea(isDark), + ], + ), + ), + ); + } + + Widget _buildCareModeToggle(bool isDark, Color primaryColor) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '关怀模式', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + Obx( + () => Switch( + value: _careController.isCareModeEnabled, + onChanged: (value) => _careController.toggleCareMode(), + activeColor: primaryColor, + ), + ), + ], + ), + ); + } + + Widget _buildUserTypeSelector(bool isDark, Color primaryColor) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '用户类型', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildUserTypeButton( + '儿童', + _careController.userType == '儿童', + isDark, + primaryColor, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildUserTypeButton( + '学生', + _careController.userType == '学生', + isDark, + primaryColor, + ), + ), + ], + ), + const SizedBox(height: 16), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF3A3A3A) : Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: Obx( + () => Text( + _careController.userType == '儿童' + ? '儿童模式:大字体、简单界面、拼音辅助,适合低龄儿童使用。界面更加卡通化,内容简单易懂,帮助儿童轻松学习诗词。' + : '学生模式:适中字体、学习辅助、诗词解析,适合学生群体使用。提供详细的诗词注释、背景知识,助力学生深入理解古典文学。', + style: TextStyle( + fontSize: 14, + height: 1.5, + color: isDark ? Colors.grey[300] : Colors.grey[700], + ), + ), + ), + ), + ], + ), + ); + } + + Widget _buildUserTypeButton( + String label, + bool isSelected, + bool isDark, + Color primaryColor, + ) { + return GestureDetector( + onTap: () => _careController.setUserType(label), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration( + color: isSelected + ? primaryColor + : (isDark ? const Color(0xFF3A3A3A) : Colors.white), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: isSelected ? primaryColor : Colors.transparent, + width: 2, + ), + ), + child: Center( + child: Text( + label, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: isSelected + ? Colors.white + : (isDark ? Colors.white : Colors.black87), + ), + ), + ), + ), + ); + } + + Widget _buildPinyinToggle(bool isDark, Color primaryColor) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(16), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '拼音显示', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + Obx( + () => Switch( + value: _careController.pinyinEnabled, + onChanged: (value) => _careController.setPinyinEnabled(value), + activeColor: primaryColor, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + '朗读', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + const SizedBox(width: 8), + IconButton( + icon: Icon( + Icons.info_outline, + color: isDark ? Colors.grey[400] : Colors.grey[600], + size: 20, + ), + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: isDark + ? const Color(0xFF2A2A2A) + : Colors.white, + title: Text( + '功能说明', + style: TextStyle( + color: isDark ? Colors.white : Colors.black87, + fontWeight: FontWeight.bold, + ), + ), + content: Text( + '你使用的设备暂不支持朗读功能\n 等待上游厂商适配TTS.', + style: TextStyle( + color: isDark + ? Colors.grey[300] + : Colors.grey[700], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text( + '确定', + style: TextStyle(color: primaryColor), + ), + ), + ], + ), + ); + }, + ), + ], + ), + Switch( + value: false, + onChanged: null, + activeColor: isDark ? Colors.grey[700] : Colors.grey[400], + inactiveTrackColor: isDark + ? Colors.grey[800] + : Colors.grey[300], + ), + ], + ), + ], + ), + ); + } + + Widget _buildMultiSelectOptions(bool isDark, Color primaryColor) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '显示选项', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + const SizedBox(height: 16), + Obx( + () => Wrap( + spacing: 12, + runSpacing: 12, + children: _options.map((option) { + final isSelected = _careController.selectedOptions.contains( + option, + ); + final isPoetry = option == '诗词'; + return GestureDetector( + onTap: isPoetry + ? null + : () => _careController.toggleOption(option), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + decoration: BoxDecoration( + color: isSelected + ? primaryColor + : (isDark ? const Color(0xFF3A3A3A) : Colors.white), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: isSelected ? primaryColor : Colors.transparent, + width: 2, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (isSelected) + Icon(Icons.check, color: Colors.white, size: 20), + if (isSelected) const SizedBox(width: 8), + Text( + option, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: isSelected + ? Colors.white + : (isDark ? Colors.white : Colors.black87), + ), + ), + ], + ), + ), + ); + }).toList(), + ), + ), + ], + ), + ); + } + + Widget _buildDescriptionArea(bool isDark) { + return Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '功能说明', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), + ), + const SizedBox(height: 12), + Text( + '关怀模式为儿童和学生用户提供更加友好的界面体验。\n\n' + '开启关怀模式后,应用将根据选择的用户类型自动调整界面显示。', + style: TextStyle( + fontSize: 16, + height: 1.6, + color: isDark ? Colors.grey[300] : Colors.grey[700], + ), + ), + ], + ), + ); + } +} diff --git a/lib/views/home/care/care_poetry_page.dart b/lib/views/home/care/care_poetry_page.dart new file mode 100644 index 0000000..544d2e1 --- /dev/null +++ b/lib/views/home/care/care_poetry_page.dart @@ -0,0 +1,512 @@ +/// 时间: 2026-04-02 +/// 功能: 关怀模式诗词页面 +/// 介绍: 关怀模式下显示的诗词页面,根据关怀设置显示不同内容 +/// 最新变化: 2026-04-02 初始创建 + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../services/get/home_controller.dart'; +import '../../../services/get/theme_controller.dart'; +import '../../../services/get/care_controller.dart'; +import '../../../constants/app_constants.dart'; +import '../home_part.dart'; +import 'care_widgets.dart'; +import 'pinyin_helper.dart'; + +class CarePoetryPage extends StatefulWidget { + const CarePoetryPage({super.key}); + + @override + State createState() => _CarePoetryPageState(); +} + +class _CarePoetryPageState extends State + with SingleTickerProviderStateMixin { + String _getTimeOfDayGreeting() { + final hour = DateTime.now().hour; + if (hour >= 5 && hour < 7) { + return '清晨了,呼吸新鲜空气'; + } else if (hour >= 7 && hour < 9) { + return '早上好,元气满满'; + } else if (hour >= 9 && hour < 12) { + return '上午好,努力工作'; + } else if (hour >= 12 && hour < 14) { + return '中午了,吃顿好的'; + } else if (hour >= 14 && hour < 17) { + return '下午了,喝杯咖啡'; + } else if (hour >= 17 && hour < 19) { + return '傍晚了,休息一下'; + } else if (hour >= 19 && hour < 22) { + return '晚上好,放松身心'; + } else { + return '深夜了,注意身体'; + } + } + + late AnimationController _animationController; + late Animation _fadeAnimation; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 500), + vsync: this, + ); + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.easeOut), + ); + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final homeController = Get.find(); + final themeController = Get.find(); + final careController = Get.find(); + + return Obx(() { + final isDark = themeController.isDarkModeRx.value; + final primaryColor = themeController.currentThemeColor; + final poetryData = homeController.poetryData.value; + + if (poetryData == null) { + return const Center(child: CircularProgressIndicator()); + } + + // 当诗词数据变化时,重新播放动画 + _animationController.reset(); + _animationController.forward(); + + return Scaffold( + backgroundColor: isDark ? const Color(0xFF121212) : Colors.grey[50], + body: SafeArea( + child: GestureDetector( + onTap: () async { + try { + await homeController.loadNextPoetry(); + } catch (e) { + print('加载诗词失败: $e'); + } + }, + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: FadeTransition( + opacity: _fadeAnimation, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // 关怀模式开关 + CarePageHeaderToggle(isDark: isDark), + const SizedBox(height: 16), + // 问候语bar + if (careController.selectedOptions.contains('问候语')) + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [primaryColor.withAlpha(204), primaryColor], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + Icon(Icons.wb_sunny, color: Colors.white, size: 20), + const SizedBox(width: 8), + Expanded( + child: Text( + _getTimeOfDayGreeting(), + style: const TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ), + ], + ), + ), + if (careController.selectedOptions.contains('问候语')) + const SizedBox(height: 16), + // 出处 + if (careController.selectedOptions.contains('出处')) + _buildPoetrySource(poetryData, isDark, primaryColor), + if (careController.selectedOptions.contains('出处')) + const SizedBox(height: 24), + if (!careController.selectedOptions.contains('问候语') && + !careController.selectedOptions.contains('出处')) + const SizedBox(height: 24), + // 诗词标题 + if (careController.selectedOptions.contains('诗词')) + _buildPoetryTitle(poetryData, isDark, primaryColor), + + const SizedBox(height: 24), + + // 诗词内容 + if (careController.selectedOptions.contains('诗词')) + GestureDetector( + onTap: () async { + try { + await homeController.loadNextPoetry(); + } catch (e) { + print('加载诗词失败: $e'); + } + }, + child: _buildPoetryContent( + poetryData, + isDark, + primaryColor, + ), + ), + + const SizedBox(height: 24), + + // 原文 + if (careController.selectedOptions.contains('原文')) + _buildPoetryOriginal(poetryData, isDark, primaryColor), + + if (careController.selectedOptions.contains('原文')) + const SizedBox(height: 24), + + const SizedBox(height: 24), + + // 译文 + if (careController.selectedOptions.contains('译文')) + _buildPoetryTranslation(poetryData, isDark, primaryColor), + + const SizedBox(height: 24), + + // 更多 + if (careController.selectedOptions.contains('更多')) + _buildPoetryMore(poetryData, isDark, primaryColor), + + const SizedBox(height: 48), + ], + ), + ), + ), + ), + ), + ); + }); + } + + Widget _buildPoetryTitle( + dynamic poetryData, + bool isDark, + Color primaryColor, + ) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Text( + poetryData.name ?? '未知标题', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: primaryColor, + ), + textAlign: TextAlign.center, + ), + ); + } + + Widget _buildPoetryContent( + dynamic poetryData, + bool isDark, + Color primaryColor, + ) { + final themeController = Get.find(); + final careController = Get.find(); + final accentColor = themeController.currentAccentColor; + final content = poetryData.name ?? ''; + final lines = content.split('\n'); + final showPinyin = careController.pinyinEnabled; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark + ? accentColor.withOpacity(0.2) + : accentColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: lines.asMap().entries.map((entry) { + int index = entry.key; + String line = entry.value; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + children: [ + if (showPinyin && line.trim().isNotEmpty) + Wrap( + alignment: WrapAlignment.center, + children: PinyinHelper.convertToCharPinyinList(line) + .asMap() + .entries + .map((charEntry) { + int charIndex = charEntry.key; + var item = charEntry.value; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: AnimatedOpacity( + opacity: 1.0, + duration: Duration( + milliseconds: 300 + charIndex * 100, + ), + curve: Curves.easeOut, + child: Column( + children: [ + Text( + item['pinyin'] ?? '', + style: TextStyle( + fontSize: 12, + color: isDark + ? Colors.grey[400] + : Colors.grey[600], + height: 1.2, + ), + textAlign: TextAlign.center, + ), + Text( + item['char'] ?? '', + style: TextStyle( + fontSize: 20, + color: primaryColor, + height: 1.6, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + }) + .toList(), + ), + if (!showPinyin || line.trim().isEmpty) + Wrap( + alignment: WrapAlignment.center, + children: line.split('').asMap().entries.map(( + charEntry, + ) { + int charIndex = charEntry.key; + String char = charEntry.value; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: AnimatedOpacity( + opacity: 1.0, + duration: Duration( + milliseconds: 300 + charIndex * 100, + ), + curve: Curves.easeOut, + child: Text( + char, + style: TextStyle( + fontSize: 20, + color: primaryColor, + height: 1.6, + ), + textAlign: TextAlign.center, + ), + ), + ); + }).toList(), + ), + ], + ), + ); + }).toList(), + ), + ); + } + + Widget _buildPoetrySource( + dynamic poetryData, + bool isDark, + Color primaryColor, + ) { + final url = poetryData.url ?? '未知作者'; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Text( + url, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: primaryColor, + ), + textAlign: TextAlign.center, + ), + ); + } + + Widget _buildPoetryTranslation( + dynamic poetryData, + bool isDark, + Color primaryColor, + ) { + final translation = poetryData.introduce ?? '暂无译文'; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Text( + translation, + style: TextStyle( + fontSize: 16, + color: isDark ? Colors.grey[300] : Colors.grey[700], + height: 1.6, + ), + textAlign: TextAlign.center, + ), + ); + } + + Widget _buildPoetryMore(dynamic poetryData, bool isDark, Color primaryColor) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Column( + children: [ + Text( + '更多信息', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: primaryColor, + ), + ), + const SizedBox(height: 12), + Text( + '诗词解析、背景知识等内容将在此显示', + style: TextStyle( + fontSize: 14, + color: isDark ? Colors.grey[300] : Colors.grey[700], + ), + textAlign: TextAlign.center, + ), + ], + ), + ); + } + + Widget _buildPoetryOriginal( + dynamic poetryData, + bool isDark, + Color primaryColor, + ) { + final original = poetryData.drtime ?? '暂无原文'; + final careController = Get.find(); + final showPinyin = careController.pinyinEnabled; + final lines = original.split('\n'); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.grey[100], + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: lines.asMap().entries.map((entry) { + int index = entry.key; + String line = entry.value; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + children: [ + if (showPinyin && line.trim().isNotEmpty) + Wrap( + alignment: WrapAlignment.center, + children: PinyinHelper.convertToCharPinyinList(line) + .asMap() + .entries + .map((charEntry) { + int charIndex = charEntry.key; + var item = charEntry.value; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: AnimatedOpacity( + opacity: 1.0, + duration: Duration( + milliseconds: 300 + charIndex * 100, + ), + curve: Curves.easeOut, + child: Column( + children: [ + Text( + item['pinyin'] ?? '', + style: TextStyle( + fontSize: 12, + color: isDark + ? Colors.grey[400] + : Colors.grey[600], + height: 1.2, + ), + textAlign: TextAlign.center, + ), + Text( + item['char'] ?? '', + style: TextStyle( + fontSize: 16, + color: primaryColor, + height: 1.6, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + }) + .toList(), + ), + if (!showPinyin || line.trim().isEmpty) + Text( + line, + style: TextStyle( + fontSize: 16, + color: primaryColor, + height: 1.6, + ), + textAlign: TextAlign.center, + ), + ], + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/views/home/care/care_widgets.dart b/lib/views/home/care/care_widgets.dart new file mode 100644 index 0000000..ccffcdc --- /dev/null +++ b/lib/views/home/care/care_widgets.dart @@ -0,0 +1,171 @@ +/// 时间: 2026-04-02 +/// 功能: 关怀模式相关组件 +/// 介绍: 包含关怀按钮和开关的UI组件 +/// 最新变化: 2026-04-02 初始创建 + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../services/get/theme_controller.dart'; +import '../../../services/get/care_controller.dart'; +import 'care-page.dart'; + +/// 关怀按钮组件 +class CareButton extends StatelessWidget { + const CareButton({super.key, required this.onTap, required this.isDark}); + + final VoidCallback onTap; + final bool isDark; + + @override + Widget build(BuildContext context) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; + + return GestureDetector( + onTap: onTap, + child: Container( + width: 44, + height: 44, + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(isDark ? 40 : 20), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Center(child: Icon(Icons.people, color: primaryColor, size: 24)), + ), + ); + } +} + +/// 关怀模式开关组件 +class CareModeToggle extends StatelessWidget { + const CareModeToggle({ + super.key, + required this.isEnabled, + required this.onToggle, + required this.isDark, + }); + + final bool isEnabled; + final VoidCallback onToggle; + final bool isDark; + + @override + Widget build(BuildContext context) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + margin: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(isDark ? 40 : 20), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon(Icons.people, color: primaryColor, size: 20), + const SizedBox(width: 12), + GestureDetector( + onTap: () => Get.to(() => const CarePage()), + child: Text( + '关怀', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black, + ), + ), + ), + ], + ), + Switch( + value: isEnabled, + onChanged: (_) => onToggle(), + activeColor: primaryColor, + inactiveTrackColor: isDark ? Colors.grey[700] : Colors.grey[300], + ), + ], + ), + ); + } +} + +/// 关怀模式页面顶部开关组件 +class CarePageHeaderToggle extends StatelessWidget { + const CarePageHeaderToggle({super.key, required this.isDark}); + + final bool isDark; + + @override + Widget build(BuildContext context) { + final themeController = Get.find(); + final careController = Get.find(); + final primaryColor = themeController.currentThemeColor; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + margin: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(isDark ? 40 : 20), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Icon(Icons.people, color: primaryColor, size: 20), + const SizedBox(width: 12), + GestureDetector( + onTap: () => Get.to(() => const CarePage()), + child: Text( + '关怀模式', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black, + ), + ), + ), + ], + ), + Obx( + () => Switch( + value: careController.isCareModeEnabled, + onChanged: (value) { + // 关闭关怀模式并返回正常页面 + careController.toggleCareMode(); + }, + activeColor: primaryColor, + inactiveTrackColor: isDark ? Colors.grey[700] : Colors.grey[300], + ), + ), + ], + ), + ); + } +} diff --git a/lib/views/home/care/pinyin_helper.dart b/lib/views/home/care/pinyin_helper.dart new file mode 100644 index 0000000..befb092 --- /dev/null +++ b/lib/views/home/care/pinyin_helper.dart @@ -0,0 +1,79 @@ +/// 时间: 2026-04-02 +/// 功能: 拼音处理辅助类 +/// 介绍: 使用pinyin库为汉字生成带音调的拼音 +/// 最新变化: 2026-04-02 修正API使用方式,避免递归调用 + +import 'package:pinyin/pinyin.dart' as pinyin; + +class PinyinHelper { + /// 将汉字转换为带音调的拼音 + static String convertToPinyin(String text) { + if (text.isEmpty) return ''; + + try { + // 使用pinyin库将汉字转换为拼音 + return pinyin.PinyinHelper.getPinyin( + text, + separator: ' ', + format: pinyin.PinyinFormat.WITH_TONE_MARK, + ); + } catch (e) { + // 无法转换时返回空字符串 + return ''; + } + } + + /// 为诗词内容生成拼音 + static String generatePoetryPinyin(String content) { + if (content.isEmpty) return ''; + + // 按行分割诗词 + List lines = content.split('\n'); + List pinyinLines = []; + + // 为每行生成拼音 + for (String line in lines) { + if (line.trim().isNotEmpty) { + String linePinyin = convertToPinyin(line); + pinyinLines.add(linePinyin); + } else { + pinyinLines.add(''); + } + } + + return pinyinLines.join('\n'); + } + + /// 将字符串转换为每个汉字及其对应的拼音的列表 + static List> convertToCharPinyinList(String text) { + if (text.isEmpty) return []; + + List> result = []; + + try { + // 为每个字符生成拼音 + for (int i = 0; i < text.length; i++) { + String char = text[i]; + String charPinyin = ''; + + try { + charPinyin = pinyin.PinyinHelper.getPinyin( + char, + separator: ' ', + format: pinyin.PinyinFormat.WITH_TONE_MARK, + ); + } catch (e) { + // 无法转换时使用空字符串 + charPinyin = ''; + } + + result.add({'char': char, 'pinyin': charPinyin}); + } + } catch (e) { + // 发生错误时返回空列表 + return []; + } + + return result; + } +} diff --git a/lib/views/home/home_page.dart b/lib/views/home/home_page.dart index 414c23b..e60117e 100644 --- a/lib/views/home/home_page.dart +++ b/lib/views/home/home_page.dart @@ -14,6 +14,9 @@ import 'home_part.dart'; import 'set/home_components.dart'; import 'set/home-load.dart'; import 'set/home-set.dart'; +import '../../services/get/care_controller.dart'; +import 'care/care_widgets.dart'; +import 'care/care_poetry_page.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -22,23 +25,31 @@ class HomePage extends StatefulWidget { State createState() => _HomePageState(); } -class _HomePageState extends State { +class _HomePageState extends State + with SingleTickerProviderStateMixin { final GlobalKey repaintKey = GlobalKey(); final SecondaryButtonsManager _secondaryButtonsManager = SecondaryButtonsManager(); final FloatingButtonsVisibilityManager _floatingButtonsVisibilityManager = FloatingButtonsVisibilityManager(); + final CareController _careController = Get.put(CareController()); + late AnimationController _animationController; @override void initState() { super.initState(); _secondaryButtonsManager.init(); _floatingButtonsVisibilityManager.init(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, + ); } @override void dispose() { _floatingButtonsVisibilityManager.dispose(); + _animationController.dispose(); super.dispose(); } @@ -47,12 +58,40 @@ class _HomePageState extends State { Get.lazyPut(() => HomeController()); final controller = Get.find(); final themeController = Get.find(); + final careController = Get.find(); return Obx(() { final isDark = themeController.isDarkModeRx.value; - return Scaffold( - backgroundColor: isDark ? const Color(0xFF121212) : Colors.grey[50], - body: SafeArea(child: _buildBody(controller, isDark)), + + // 触发动画 + if (_animationController.status != AnimationStatus.forward) { + _animationController.forward(from: 0); + } + + // 关怀模式开启时显示关怀页面,添加过渡动画 + if (careController.isCareModeEnabled) { + return FadeTransition( + opacity: Tween(begin: 0, end: 1).animate( + CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + ), + ), + child: const CarePoetryPage(), + ); + } + + return FadeTransition( + opacity: Tween(begin: 0, end: 1).animate( + CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOut, + ), + ), + child: Scaffold( + backgroundColor: isDark ? const Color(0xFF121212) : Colors.grey[50], + body: SafeArea(child: _buildBody(controller, isDark)), + ), ); }); } @@ -113,6 +152,30 @@ class _HomePageState extends State { ), ), ), + // 关怀按钮 - 左上角 + Positioned( + top: 8, + left: 16, + child: CareButton( + onTap: _careController.toggleCareButtonVisibility, + isDark: isDark, + ), + ), + // 关怀模式开关 + Obx( + () => _careController.isCareButtonVisible.value + ? Positioned( + top: 60, + left: 16, + right: 16, + child: CareModeToggle( + isEnabled: _careController.isCareModeEnabled, + onToggle: _careController.toggleCareMode, + isDark: isDark, + ), + ) + : const SizedBox.shrink(), + ), // 收起/恢复按钮 - 右上角(与下方分享按钮对齐) Positioned( top: 8, diff --git a/lib/views/home/home_part.dart b/lib/views/home/home_part.dart index 78f7e4e..902ed8a 100644 --- a/lib/views/home/home_part.dart +++ b/lib/views/home/home_part.dart @@ -4,8 +4,10 @@ /// 最新变化: 2026-04-02 支持深色模式 import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; +import '../../../services/get/theme_controller.dart'; import '../../../utils/http/poetry_api.dart'; import '../../../utils/audio_manager.dart'; import 'set/home_components.dart'; @@ -106,6 +108,8 @@ class _PoetryCardState extends State { @override Widget build(BuildContext context) { final isDark = widget.isDark; + final themeController = Get.find(); + final themeColor = themeController.currentThemeColor; final card = GestureDetector( onTap: () { AudioManager().playClickSound(); @@ -129,16 +133,16 @@ class _PoetryCardState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - _buildTimeBar(isDark), + _buildTimeBar(isDark, themeColor), Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - _buildTitleSection(isDark), + _buildTitleSection(isDark, themeColor), if (widget.poetryData.drtime.isNotEmpty) ...[ - _buildContentSection(context, isDark), + _buildContentSection(context, isDark, themeColor), const SizedBox(height: 3), ], Align( @@ -157,27 +161,27 @@ class _PoetryCardState extends State { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: AppConstants.primaryColor, + color: themeColor, ), ), const SizedBox(width: 4), Icon( Icons.format_quote, - color: AppConstants.primaryColor, + color: themeColor, size: 14, ), ], ), ), ), - _buildNameSection(isDark), + _buildNameSection(isDark, themeColor), const SizedBox(height: 12), if (widget.keywordList.isNotEmpty) ...[ - _buildKeywordSection(isDark), + _buildKeywordSection(isDark, themeColor), const SizedBox(height: 16), ], if (widget.poetryData.introduce.isNotEmpty) ...[ - _buildIntroductionSection(context, isDark), + _buildIntroductionSection(context, isDark, themeColor), ], ], ), @@ -185,7 +189,7 @@ class _PoetryCardState extends State { ], ), ), - _buildCopyTip(isDark), + _buildCopyTip(isDark, themeColor), ], ), ); @@ -196,7 +200,7 @@ class _PoetryCardState extends State { return card; } - Widget _buildTimeBar(bool isDark) { + Widget _buildTimeBar(bool isDark, Color themeColor) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { @@ -209,10 +213,7 @@ class _PoetryCardState extends State { padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - AppConstants.primaryColor.withAlpha(204), - AppConstants.primaryColor, - ], + colors: [themeColor.withAlpha(204), themeColor], begin: Alignment.topLeft, end: Alignment.bottomRight, ), @@ -251,7 +252,7 @@ class _PoetryCardState extends State { ); } - Widget _buildCopyTip(bool isDark) { + Widget _buildCopyTip(bool isDark, Color themeColor) { if (!_globalTipsEnabled || !_showCopyTip) { return const SizedBox.shrink(); } @@ -264,11 +265,11 @@ class _PoetryCardState extends State { child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: themeColor, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withAlpha(76), + color: themeColor.withAlpha(76), blurRadius: 8, offset: const Offset(0, 2), ), @@ -296,7 +297,7 @@ class _PoetryCardState extends State { ); } - Widget _buildTitleSection(bool isDark) { + Widget _buildTitleSection(bool isDark, Color themeColor) { final isLoading = widget.sectionLoadingStates?['title'] ?? false; return SizedBox( @@ -321,7 +322,7 @@ class _PoetryCardState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, + themeColor, ), ), ), @@ -357,7 +358,7 @@ class _PoetryCardState extends State { ); } - Widget _buildNameSection(bool isDark) { + Widget _buildNameSection(bool isDark, Color themeColor) { final isLoading = widget.sectionLoadingStates?['name'] ?? false; return Container( @@ -368,25 +369,20 @@ class _PoetryCardState extends State { gradient: LinearGradient( colors: isDark ? [const Color(0xFF2A2A2A), const Color(0xFF252525)] - : [ - AppConstants.primaryColor.withAlpha(26), - AppConstants.primaryColor.withAlpha(13), - ], + : [themeColor.withAlpha(26), themeColor.withAlpha(13)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), border: Border.all( - color: isDark - ? Colors.grey[700]! - : AppConstants.primaryColor.withAlpha(51), + color: isDark ? Colors.grey[700]! : themeColor.withAlpha(51), width: 1, ), boxShadow: [ BoxShadow( color: isDark ? Colors.black.withAlpha(40) - : AppConstants.primaryColor.withAlpha(26), + : themeColor.withAlpha(26), blurRadius: 8, offset: const Offset(0, 2), ), @@ -412,7 +408,7 @@ class _PoetryCardState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, + themeColor, ), ), ), @@ -456,7 +452,7 @@ class _PoetryCardState extends State { return text; } - Widget _buildKeywordSection(bool isDark) { + Widget _buildKeywordSection(bool isDark, Color themeColor) { final isLoading = widget.sectionLoadingStates?['keywords'] ?? false; return Column( @@ -475,7 +471,7 @@ class _PoetryCardState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, + themeColor, ), ), ), @@ -513,18 +509,14 @@ class _PoetryCardState extends State { ), decoration: BoxDecoration( color: isDark - ? AppConstants.secondaryColor.withAlpha( - 40, - ) - : AppConstants.secondaryColor.withAlpha( - 26, - ), + ? themeColor.withAlpha(40) + : themeColor.withAlpha(26), borderRadius: BorderRadius.circular(8), ), child: Text( keyword, style: TextStyle( - color: AppConstants.secondaryColor, + color: themeColor, fontSize: 12, ), overflow: TextOverflow.ellipsis, @@ -550,14 +542,14 @@ class _PoetryCardState extends State { ), decoration: BoxDecoration( color: isDark - ? AppConstants.primaryColor.withAlpha(40) - : AppConstants.primaryColor.withAlpha(26), + ? themeColor.withAlpha(40) + : themeColor.withAlpha(26), borderRadius: BorderRadius.circular(12), ), child: Text( widget.poetryData.alias, style: TextStyle( - color: AppConstants.primaryColor, + color: themeColor, fontSize: 12, fontWeight: FontWeight.w500, ), @@ -604,7 +596,11 @@ class _PoetryCardState extends State { ); } - Widget _buildContentSection(BuildContext context, bool isDark) { + Widget _buildContentSection( + BuildContext context, + bool isDark, + Color themeColor, + ) { final isLoading = widget.sectionLoadingStates?['content'] ?? false; return Builder( @@ -622,7 +618,7 @@ class _PoetryCardState extends State { decoration: BoxDecoration( color: isDark ? Colors.grey[800]!.withAlpha(80) - : AppConstants.primaryColor.withAlpha(20), + : themeColor.withAlpha(20), borderRadius: BorderRadius.circular(8), ), child: isLoading @@ -635,9 +631,7 @@ class _PoetryCardState extends State { height: 16, child: CircularProgressIndicator( strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, - ), + valueColor: AlwaysStoppedAnimation(themeColor), ), ), const SizedBox(width: 8), @@ -659,9 +653,7 @@ class _PoetryCardState extends State { style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, - color: isDark - ? Colors.grey[300] - : AppConstants.primaryColor, + color: isDark ? Colors.grey[300] : themeColor, ), ), const SizedBox(height: 8), @@ -680,7 +672,11 @@ class _PoetryCardState extends State { ); } - Widget _buildIntroductionSection(BuildContext context, bool isDark) { + Widget _buildIntroductionSection( + BuildContext context, + bool isDark, + Color themeColor, + ) { final isLoading = widget.sectionLoadingStates?['introduction'] ?? false; return Builder( @@ -710,9 +706,7 @@ class _PoetryCardState extends State { height: 20, child: CircularProgressIndicator( strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, - ), + valueColor: AlwaysStoppedAnimation(themeColor), ), ), const SizedBox(height: 8), diff --git a/lib/views/home/set/home_components.dart b/lib/views/home/set/home_components.dart index ff80553..b734002 100644 --- a/lib/views/home/set/home_components.dart +++ b/lib/views/home/set/home_components.dart @@ -12,6 +12,7 @@ import 'package:get/get.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; import '../../../constants/app_constants.dart'; +import '../../../services/get/theme_controller.dart'; import '../../../utils/http/poetry_api.dart'; import 'home-load.dart'; @@ -23,14 +24,14 @@ class LoadingWidget extends StatelessWidget { @override Widget build(BuildContext context) { + final themeController = Get.find(); + final themeColor = themeController.currentThemeColor; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, - ), + valueColor: AlwaysStoppedAnimation(themeColor), ), const SizedBox(height: 16), Text( @@ -145,7 +146,7 @@ class CustomErrorWidget extends StatelessWidget { ElevatedButton( onPressed: onRetry, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: Get.find().currentThemeColor, ), child: const Text('重试'), ), @@ -401,15 +402,17 @@ class FloatingShareButton extends StatelessWidget { @override Widget build(BuildContext context) { + final themeController = Get.find(); + final themeColor = themeController.currentThemeColor; return Container( width: 56, height: 56, decoration: BoxDecoration( - color: AppConstants.secondaryColor, + color: themeColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( - color: AppConstants.secondaryColor.withAlpha(76), + color: themeColor.withAlpha(76), blurRadius: 8, offset: const Offset(0, 4), ), @@ -470,7 +473,9 @@ class FloatingPreviousButton extends StatelessWidget { child: Center( child: Icon( Icons.arrow_back, - color: isDark ? Colors.grey[300] : AppConstants.primaryColor, + color: isDark + ? Colors.grey[300] + : Get.find().currentThemeColor, size: 28, ), ), @@ -518,7 +523,9 @@ class FloatingNextButton extends StatelessWidget { child: Center( child: Icon( Icons.arrow_forward, - color: isDark ? Colors.grey[300] : AppConstants.primaryColor, + color: isDark + ? Colors.grey[300] + : Get.find().currentThemeColor, size: 28, ), ), @@ -581,7 +588,9 @@ class FloatingLikeButton extends StatelessWidget { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - isDark ? Colors.grey[300]! : AppConstants.primaryColor, + isDark + ? Colors.grey[300]! + : Get.find().currentThemeColor, ), ), ) @@ -608,6 +617,8 @@ class StatsCard extends StatelessWidget { @override Widget build(BuildContext context) { + final themeController = Get.find(); + final themeColor = themeController.currentThemeColor; return Container( margin: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.all(16), @@ -631,7 +642,7 @@ class StatsCard extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, + color: themeColor, ), ), const SizedBox(height: 12), diff --git a/lib/views/profile/app-info.dart b/lib/views/profile/app-info.dart index f41523a..5d22e92 100644 --- a/lib/views/profile/app-info.dart +++ b/lib/views/profile/app-info.dart @@ -8,6 +8,7 @@ import 'package:platform_info/platform_info.dart'; import 'package:flutter_udid/flutter_udid.dart'; import '../../../config/app_config.dart'; import '../../../constants/app_constants.dart'; +import '../../../models/colors/theme_colors.dart'; import '../../../controllers/shared_preferences_storage_controller.dart'; import '../../../services/get/theme_controller.dart'; @@ -102,6 +103,7 @@ class _AppInfoPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -109,16 +111,13 @@ class _AppInfoPageState extends State { appBar: AppBar( title: Text( '应用信息', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), actions: [ @@ -139,15 +138,15 @@ class _AppInfoPageState extends State { body: ListView( padding: const EdgeInsets.all(16), children: [ - _buildHeaderCard(), + _buildHeaderCard(primaryColor), const SizedBox(height: 16), _buildTechStackCard(isDark), const SizedBox(height: 16), - _buildBuildInfoCard(context, isDark), + _buildBuildInfoCard(context, isDark, primaryColor), const SizedBox(height: 16), _buildServerInfoCard(isDark), const SizedBox(height: 16), - _buildDeviceInfoCard(context, isDark), + _buildDeviceInfoCard(context, isDark, primaryColor), const SizedBox(height: 16), _buildUpdateLogCard(isDark), const SizedBox(height: 16), @@ -160,7 +159,7 @@ class _AppInfoPageState extends State { }); } - Widget _buildHeaderCard() { + Widget _buildHeaderCard(Color primaryColor) { return ClipRRect( borderRadius: BorderRadius.circular(16), child: BackdropFilter( @@ -170,9 +169,9 @@ class _AppInfoPageState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withValues(alpha: 0.66), - AppConstants.primaryColor.withValues(alpha: 0.7), - AppConstants.primaryColor.withValues(alpha: 0.99), + primaryColor.withValues(alpha: 0.66), + primaryColor.withValues(alpha: 0.7), + primaryColor.withValues(alpha: 0.99), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -184,7 +183,7 @@ class _AppInfoPageState extends State { ), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.35), + color: primaryColor.withValues(alpha: 0.35), blurRadius: 20, offset: const Offset(0, 4), ), @@ -386,7 +385,11 @@ class _AppInfoPageState extends State { ); } - Widget _buildBuildInfoCard(BuildContext context, bool isDark) { + Widget _buildBuildInfoCard( + BuildContext context, + bool isDark, + Color primaryColor, + ) { String buildSdk = 'Unknown'; try { final String osName = io.Platform.operatingSystem; @@ -435,10 +438,10 @@ class _AppInfoPageState extends State { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.green.withValues(alpha: 0.1), + color: primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), - child: Icon(Icons.build, color: Colors.green[700], size: 20), + child: Icon(Icons.build, color: primaryColor, size: 20), ), const SizedBox(width: 12), Text( @@ -474,25 +477,25 @@ class _AppInfoPageState extends State { isDark, ), _buildInfoItem('Build SDK', buildSdk, Icons.new_releases, isDark), - _buildLicenseItem(context, isDark), + _buildLicenseItem(context, isDark, primaryColor), ], ), ); } - Widget _buildLicenseItem(BuildContext context, bool isDark) { + Widget _buildLicenseItem( + BuildContext context, + bool isDark, + Color primaryColor, + ) { return InkWell( - onTap: () => _showFlutterLicense(context, isDark), + onTap: () => _showFlutterLicense(context, isDark, primaryColor), borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ - Icon( - Icons.gavel, - size: 20, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), + Icon(Icons.gavel, size: 20, color: primaryColor), const SizedBox(width: 12), Expanded( child: Column( @@ -528,7 +531,11 @@ class _AppInfoPageState extends State { ); } - void _showFlutterLicense(BuildContext context, bool isDark) { + void _showFlutterLicense( + BuildContext context, + bool isDark, + Color primaryColor, + ) { final licenses = [ {'name': 'Flutter SDK', 'license': 'BSD 3-Clause'}, {'name': 'OpenHarmony SDK', 'license': 'Apache 2.0'}, @@ -545,7 +552,7 @@ class _AppInfoPageState extends State { backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, title: Row( children: [ - Icon(Icons.description, color: AppConstants.primaryColor), + Icon(Icons.description, color: primaryColor), const SizedBox(width: 8), Text( '开源框架', @@ -574,14 +581,10 @@ class _AppInfoPageState extends State { Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(6), ), - child: Icon( - Icons.widgets, - size: 16, - color: AppConstants.primaryColor, - ), + child: Icon(Icons.widgets, size: 16, color: primaryColor), ), const SizedBox(width: 12), Expanded( @@ -618,10 +621,7 @@ class _AppInfoPageState extends State { actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text( - '关闭', - style: TextStyle(color: AppConstants.primaryColor), - ), + child: Text('关闭', style: TextStyle(color: primaryColor)), ), ], ), @@ -678,7 +678,11 @@ class _AppInfoPageState extends State { ); } - Widget _buildDeviceInfoCard(BuildContext context, bool isDark) { + Widget _buildDeviceInfoCard( + BuildContext context, + bool isDark, + Color primaryColor, + ) { final platform = Platform.instance; bool isHarmonyOS = false; @@ -793,14 +797,10 @@ class _AppInfoPageState extends State { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.purple.withValues(alpha: 0.1), + color: primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), - child: Icon( - Icons.devices, - color: Colors.purple[700], - size: 20, - ), + child: Icon(Icons.devices, color: primaryColor, size: 20), ), const SizedBox(width: 12), Text( @@ -830,6 +830,7 @@ class _AppInfoPageState extends State { platformName, Icons.phone_iphone, isDark, + primaryColor, ), if (!isHarmonyOS) ...[ _buildGridInfoItem( @@ -837,17 +838,37 @@ class _AppInfoPageState extends State { designStyle, Icons.palette, isDark, + primaryColor, ), ], - _buildGridInfoItem('设备类型', deviceType, Icons.devices, isDark), - _buildGridInfoItem('构建模式', buildMode, Icons.build, isDark), - _buildGridInfoItem('运行环境', runtimeEnv, Icons.code, isDark), + _buildGridInfoItem( + '设备类型', + deviceType, + Icons.devices, + isDark, + primaryColor, + ), + _buildGridInfoItem( + '构建模式', + buildMode, + Icons.build, + isDark, + primaryColor, + ), + _buildGridInfoItem( + '运行环境', + runtimeEnv, + Icons.code, + isDark, + primaryColor, + ), _buildGridCopyableItem( context, 'Flutter UUID', _udid, Icons.perm_identity, isDark, + primaryColor, ), ], ), @@ -1181,6 +1202,7 @@ class _AppInfoPageState extends State { String value, IconData icon, bool isDark, + Color primaryColor, ) { return Container( padding: const EdgeInsets.all(12), @@ -1198,7 +1220,7 @@ class _AppInfoPageState extends State { children: [ Row( children: [ - Icon(icon, size: 18, color: AppConstants.primaryColor), + Icon(icon, size: 18, color: primaryColor), const SizedBox(width: 8), Expanded( child: Text( @@ -1236,6 +1258,7 @@ class _AppInfoPageState extends State { String value, IconData icon, bool isDark, + Color primaryColor, ) { return InkWell( onTap: () => _copyToClipboard(context, value), @@ -1257,11 +1280,7 @@ class _AppInfoPageState extends State { children: [ Row( children: [ - Icon( - icon, - size: 16, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), + Icon(icon, size: 16, color: primaryColor), const SizedBox(width: 6), Expanded( child: Text( @@ -1277,7 +1296,7 @@ class _AppInfoPageState extends State { Icon( Icons.content_copy, size: 14, - color: AppConstants.primaryColor.withValues(alpha: 0.6), + color: primaryColor.withValues(alpha: 0.6), ), ], ), @@ -1397,6 +1416,7 @@ class _AppInfoPageState extends State { void _copyToClipboard(BuildContext context, String text) { Clipboard.setData(ClipboardData(text: text)); + final primaryColor = _themeController.currentThemeColor; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( @@ -1406,7 +1426,7 @@ class _AppInfoPageState extends State { Text('$text 已复制到剪贴板'), ], ), - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), duration: const Duration(seconds: 2), diff --git a/lib/views/profile/components/bug_list_page.dart b/lib/views/profile/components/bug_list_page.dart index 428465e..daa2f3f 100644 --- a/lib/views/profile/components/bug_list_page.dart +++ b/lib/views/profile/components/bug_list_page.dart @@ -1,13 +1,13 @@ /// 时间: 2026-03-30 /// 功能: 已知bug列表页面 /// 介绍: 显示应用已知bug、解决方法和解决时间的底部弹窗页面 -/// 最新变化: 新增bug列表页面,支持下拉刷新和滚动查看 +/// 最新变化: 新增bug列表页面,支持下拉刷新和滚动查看, 支持动态主题色 import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; +import '../../../models/colors/app_colors.dart'; import '../../../services/get/theme_controller.dart'; class BugListPage extends StatefulWidget { @@ -70,7 +70,7 @@ class _BugListPageState extends State { 'description': '暂未适配横屏', 'severity': 'high', 'status': 'pending', - 'solution': '增加重试机制和离线缓存功能', + 'solution': '预计下个月适配横屏', 'reproduction': '1. 开启屏幕旋转,手机横屏', 'resolveTime': '适配中', 'reportTime': '2026-03-22', @@ -108,7 +108,7 @@ class _BugListPageState extends State { }, { 'id': 7, - 'title': '主页点击“上一条” 显示无上一条', + 'title': '主页点击"上一条" 显示无上一条', 'description': '未读取到历史记录', 'severity': 'high', 'status': 'in_progress', @@ -149,6 +149,20 @@ class _BugListPageState extends State { 'expanded': false, // 解决方案展开状态 'reproductionExpanded': false, // 复现步骤展开状态 }, + { + 'id': 12, + 'title': '显示错误的分享', + 'description': '点击分享后,取消分享,依旧显示分享成功', + 'severity': 'low', + 'status': 'pending', + 'solution': '全部触发', + 'reproduction': '主页 点击分享 取消分享 显示分享成功', + 'resolveTime': '暂无修复计划', + 'reportTime': '2026-03-18', + 'affectedUsers': '多数用户', + 'expanded': false, // 解决方案展开状态 + 'reproductionExpanded': false, // 复现步骤展开状态 + }, { 'id': 10, @@ -156,7 +170,7 @@ class _BugListPageState extends State { 'description': '未读取到历史记录', 'severity': 'low', 'status': '', - 'solution': '用户短时间内多次刷新获取api数据,导致服务器启动防止cc自我保护机制,不会此ip下放数据', + 'solution': '用户短时间内多次刷新获取api数据,导致服务器启动防止cc自我保护机制,不会对此ip下放数据', 'reproduction': '天气频繁切换,导致温度显示异常999', 'resolveTime': '下个版本', 'reportTime': '2026-03', @@ -214,24 +228,22 @@ class _BugListPageState extends State { Color _getSeverityColor(String severity) { switch (severity) { case 'high': - return Colors.red; + return AppColors.iosRed; case 'medium': - return Colors.orange; + return AppColors.iosOrange; case 'low': - return Colors.green; + return AppColors.iosGreen; default: - return Colors.grey; + return AppColors.iosGray; } } String _getSeverityText(String severity) { switch (severity) { case 'high': - // 高优先级默认红色 return '高'; case 'medium': return '中'; - case 'low': return '低'; default: @@ -242,17 +254,13 @@ class _BugListPageState extends State { Color _getStatusColor(String status) { switch (status) { case 'resolved': - // 已解决状态默认绿色 - return Colors.green; + return AppColors.iosGreen; case 'in_progress': - // 解决中状态默认蓝色 - return Colors.blue; + return AppColors.iosBlue; case 'pending': - // 待解决状态默认橙色 - return Colors.orange; + return AppColors.iosOrange; default: - return Colors.grey; - // 未知状态默认灰色 + return AppColors.iosGray; } } @@ -270,9 +278,7 @@ class _BugListPageState extends State { } Future _refresh() async { - // 模拟网络请求延迟 await Future.delayed(const Duration(seconds: 1)); - HapticFeedback.lightImpact(); } @@ -282,18 +288,16 @@ class _BugListPageState extends State { final isDark = _themeController.isDarkMode; return Container( decoration: BoxDecoration( - color: isDark ? const Color(0xFF1A1A1A) : Colors.white, + color: AppColors.background, borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( children: [ - // 顶部拖拽条和标题 _buildHeader(isDark), - // bug列表 Expanded( child: RefreshIndicator( onRefresh: _refresh, - color: AppConstants.primaryColor, + color: AppColors.primary, child: ListView.builder( controller: _scrollController, physics: const AlwaysScrollableScrollPhysics(), @@ -318,24 +322,22 @@ class _BugListPageState extends State { Widget _buildHeader(bool isDark) { return Column( children: [ - // 拖拽条 Container( width: 40, height: 4, margin: const EdgeInsets.only(top: 8), decoration: BoxDecoration( - color: isDark ? Colors.grey[600] : Colors.grey[300], + color: AppColors.divider, borderRadius: BorderRadius.circular(2), ), ), - // 标题栏 Container( padding: const EdgeInsets.all(16), child: Row( children: [ Icon( Icons.bug_report, - color: AppConstants.primaryColor, + color: AppColors.primary, size: 24, ), const SizedBox(width: 12), @@ -345,7 +347,7 @@ class _BugListPageState extends State { style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, + color: AppColors.primary, ), ), ), @@ -353,13 +355,13 @@ class _BugListPageState extends State { onPressed: () => Navigator.pop(context), child: Text( '关闭', - style: TextStyle(color: isDark ? Colors.white : null), + style: TextStyle(color: AppColors.primaryText), ), ), ], ), ), - Divider(height: 1, color: isDark ? Colors.grey[700] : null), + Divider(height: 1, color: AppColors.divider), ], ); } @@ -375,7 +377,7 @@ class _BugListPageState extends State { Container( width: 40, height: 1, - color: isDark ? Colors.grey[600] : Colors.grey[300], + color: AppColors.divider, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -383,14 +385,14 @@ class _BugListPageState extends State { '已经到底了', style: TextStyle( fontSize: 13, - color: isDark ? Colors.grey[400] : Colors.grey[500], + color: AppColors.tertiaryText, ), ), ), Container( width: 40, height: 1, - color: isDark ? Colors.grey[600] : Colors.grey[300], + color: AppColors.divider, ), ], ), @@ -399,7 +401,7 @@ class _BugListPageState extends State { '共 ${_bugs.length} 个已知问题', style: TextStyle( fontSize: 12, - color: isDark ? Colors.grey[500] : Colors.grey[400], + color: AppColors.tertiaryText, ), ), ], @@ -413,10 +415,10 @@ class _BugListPageState extends State { return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all( - color: isDark ? Colors.grey[700]! : Colors.grey[200]!, + color: AppColors.divider, ), boxShadow: [ BoxShadow( @@ -429,13 +431,11 @@ class _BugListPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // 顶部信息行 Container( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // 标题和状态标签 Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -445,7 +445,7 @@ class _BugListPageState extends State { style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black87, + color: AppColors.primaryText, ), ), ), @@ -477,17 +477,15 @@ class _BugListPageState extends State { ], ), const SizedBox(height: 8), - // 问题描述 Text( bug['description'] ?? '暂无描述', style: TextStyle( fontSize: 14, - color: isDark ? Colors.grey[400] : Colors.black54, + color: AppColors.secondaryText, height: 1.4, ), ), const SizedBox(height: 12), - // 严重程度和影响用户 Row( children: [ Container( @@ -525,20 +523,19 @@ class _BugListPageState extends State { Icon( Icons.people, size: 14, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), const SizedBox(width: 4), Text( bug['affectedUsers'] ?? '未知用户', style: TextStyle( fontSize: 12, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), ), ], ), const SizedBox(height: 12), - // 解决方案和复现步骤按钮 Row( children: [ Expanded( @@ -553,18 +550,14 @@ class _BugListPageState extends State { style: const TextStyle(fontSize: 14), ), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor.withValues( - alpha: 0.1, - ), - foregroundColor: AppConstants.primaryColor, + backgroundColor: AppColors.primaryWithAlpha(25), + foregroundColor: AppColors.primary, elevation: 0, padding: const EdgeInsets.symmetric(vertical: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( - color: AppConstants.primaryColor.withValues( - alpha: 0.3, - ), + color: AppColors.primaryWithAlpha(76), ), ), ), @@ -585,17 +578,14 @@ class _BugListPageState extends State { style: const TextStyle(fontSize: 14), ), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.secondaryColor - .withValues(alpha: 0.1), - foregroundColor: const Color(0xFF018786), // 更深的青色 + backgroundColor: AppColors.accentWithAlpha(25), + foregroundColor: AppColors.accent, elevation: 0, padding: const EdgeInsets.symmetric(vertical: 8), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( - color: const Color( - 0xFF018786, - ).withValues(alpha: 0.3), + color: AppColors.accentWithAlpha(76), ), ), ), @@ -606,13 +596,12 @@ class _BugListPageState extends State { ], ), ), - // 解决方案区域(可展开/收起) if (isExpanded) ...[ - Divider(height: 1, color: isDark ? Colors.grey[700] : null), + Divider(height: 1, color: AppColors.divider), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF333333) : Colors.grey[50], + color: AppColors.card, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), @@ -625,7 +614,7 @@ class _BugListPageState extends State { children: [ Icon( Icons.lightbulb_outline, - color: AppConstants.primaryColor, + color: AppColors.primary, size: 16, ), const SizedBox(width: 8), @@ -634,7 +623,7 @@ class _BugListPageState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: AppColors.primary, ), ), ], @@ -644,39 +633,38 @@ class _BugListPageState extends State { bug['solution'] ?? '暂无解决方案', style: TextStyle( fontSize: 13, - color: isDark ? Colors.grey[400] : Colors.black54, + color: AppColors.secondaryText, height: 1.4, ), ), const SizedBox(height: 12), - // 时间信息 Row( children: [ Icon( Icons.schedule, size: 14, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), const SizedBox(width: 4), Text( '预计解决: ${bug['resolveTime'] ?? '待定'}', style: TextStyle( fontSize: 12, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), ), const SizedBox(width: 16), Icon( Icons.report, size: 14, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), const SizedBox(width: 4), Text( '报告时间: ${bug['reportTime'] ?? '未知'}', style: TextStyle( fontSize: 12, - color: isDark ? Colors.grey[400] : Colors.grey[600], + color: AppColors.secondaryText, ), ), ], @@ -685,13 +673,12 @@ class _BugListPageState extends State { ), ), ], - // 复现步骤区域(可展开/收起) if (bug['reproductionExpanded']) ...[ - Divider(height: 1, color: isDark ? Colors.grey[700] : null), + Divider(height: 1, color: AppColors.divider), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF333333) : Colors.grey[50], + color: AppColors.card, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), @@ -704,7 +691,7 @@ class _BugListPageState extends State { children: [ Icon( Icons.replay, - color: const Color(0xFF018786), // 更深的青色 + color: AppColors.accent, size: 16, ), const SizedBox(width: 8), @@ -713,7 +700,7 @@ class _BugListPageState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: const Color(0xFF018786), // 更深的青色 + color: AppColors.accent, ), ), ], @@ -723,7 +710,7 @@ class _BugListPageState extends State { bug['reproduction'] ?? '暂无复现步骤', style: TextStyle( fontSize: 13, - color: isDark ? Colors.grey[400] : Colors.black54, + color: AppColors.secondaryText, height: 1.4, ), ), @@ -742,9 +729,9 @@ void showBugListBottomSheet(BuildContext context) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, - isScrollControlled: true, // 允许弹窗占据全屏高度 + isScrollControlled: true, builder: (context) => Container( - height: MediaQuery.of(context).size.height * 0.85, // 设置弹窗高度为屏幕的85% + height: MediaQuery.of(context).size.height * 0.85, child: const BugListPage(), ), ); diff --git a/lib/views/profile/components/entire_page.dart b/lib/views/profile/components/entire_page.dart index 34e397a..646a87a 100644 --- a/lib/views/profile/components/entire_page.dart +++ b/lib/views/profile/components/entire_page.dart @@ -1,13 +1,14 @@ /// 时间: 2026-04-01 /// 功能: 全站统计页面 /// 介绍: 展示网站统计数据,包括收录数量、热度统计、热门内容等 -/// 最新变化: 新建页面,iOS风格设计 +/// 最新变化: 支持动态主题色设置 + library; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; +import '../../../models/colors/app_colors.dart'; import '../../../utils/http/http_client.dart'; import '../../../services/network_listener_service.dart'; import '../../../services/get/theme_controller.dart'; @@ -88,12 +89,16 @@ class _EntirePageState extends State context: context, barrierDismissible: false, builder: (BuildContext context) { - return const AlertDialog( + return AlertDialog( + backgroundColor: AppColors.surface, content: Row( children: [ - CircularProgressIndicator(), - SizedBox(width: 16), - Text('正在检测网络状态...'), + CircularProgressIndicator(color: AppColors.primary), + const SizedBox(width: 16), + Text( + '正在检测网络状态...', + style: TextStyle(color: AppColors.primaryText), + ), ], ), ); @@ -132,9 +137,7 @@ class _EntirePageState extends State return AnnotatedRegion( value: isDark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark, child: Scaffold( - backgroundColor: isDark - ? const Color(0xFF1A1A1A) - : const Color(0xFFF2F2F7), + backgroundColor: AppColors.background, appBar: _buildAppBar(isDark), body: _buildBody(isDark), ), @@ -144,19 +147,19 @@ class _EntirePageState extends State PreferredSizeWidget _buildAppBar(bool isDark) { return AppBar( - backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, + backgroundColor: AppColors.surface, elevation: 0, leading: IconButton( icon: Icon( Icons.arrow_back_ios, - color: isDark ? Colors.white : AppConstants.primaryColor, + color: AppColors.primary, ), onPressed: () => Navigator.pop(context), ), title: Text( '全站统计', style: TextStyle( - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, fontSize: 17, fontWeight: FontWeight.w600, ), @@ -166,7 +169,7 @@ class _EntirePageState extends State IconButton( icon: Icon( Icons.info_outline, - color: isDark ? Colors.white : AppConstants.primaryColor, + color: AppColors.primary, ), onPressed: _showServerInfo, tooltip: '服务器信息', @@ -176,7 +179,7 @@ class _EntirePageState extends State preferredSize: const Size.fromHeight(0.5), child: Container( height: 0.5, - color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA), + color: AppColors.divider, ), ), ); @@ -204,7 +207,7 @@ class _EntirePageState extends State width: width, height: height, decoration: BoxDecoration( - color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA), + color: isDark ? Colors.grey[700] : AppColors.iosLightGray, borderRadius: BorderRadius.circular(radius), ), ); @@ -235,7 +238,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: isDark ? Colors.grey[700] : const Color(0xFFE5E5EA), + color: isDark ? Colors.grey[700] : AppColors.iosLightGray, borderRadius: BorderRadius.circular(12), ), child: Column( @@ -273,7 +276,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -320,7 +323,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: isDark ? const Color(0xFF333333) : const Color(0xFFF2F2F7), + color: isDark ? AppColors.darkCard : AppColors.iosLightGray, borderRadius: BorderRadius.circular(12), ), child: Column( @@ -362,7 +365,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -402,12 +405,12 @@ class _EntirePageState extends State width: 64, height: 64, decoration: BoxDecoration( - color: const Color(0xFFFF3B30).withValues(alpha: 0.1), + color: AppColors.error.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(32), ), - child: const Icon( + child: Icon( Icons.error_outline, - color: Color(0xFFFF3B30), + color: AppColors.error, size: 32, ), ), @@ -415,7 +418,7 @@ class _EntirePageState extends State Text( _errorMessage ?? '加载失败', style: TextStyle( - color: isDark ? Colors.grey[400] : const Color(0xFF8E8E93), + color: AppColors.tertiaryText, fontSize: 14, ), textAlign: TextAlign.center, @@ -424,7 +427,7 @@ class _EntirePageState extends State ElevatedButton( onPressed: _loadStatsData, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: AppColors.primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 32, @@ -446,7 +449,7 @@ class _EntirePageState extends State return FadeTransition( opacity: _fadeAnimation, child: RefreshIndicator( - color: AppConstants.primaryColor, + color: AppColors.primary, onRefresh: _loadStatsData, child: ListView( padding: const EdgeInsets.all(16), @@ -473,8 +476,8 @@ class _EntirePageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withValues(alpha: 0.8), + AppColors.primary, + AppColors.primary.withValues(alpha: 0.8), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -482,7 +485,7 @@ class _EntirePageState extends State borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: AppColors.primary.withValues(alpha: 0.3), blurRadius: 12, offset: const Offset(0, 4), ), @@ -591,56 +594,56 @@ class _EntirePageState extends State 'label': '项目', 'value': _statsData?['count_category'] ?? 0, 'icon': Icons.category, - 'color': const Color(0xFF007AFF), + 'color': AppColors.iosBlue, 'showIcon': true, }, { 'label': '收录诗句', 'value': _statsData?['count_site'] ?? 0, 'icon': Icons.article, - 'color': const Color(0xFF34C759), + 'color': AppColors.iosGreen, 'showIcon': false, }, { 'label': '审核中', 'value': _statsData?['count_apply'] ?? 0, 'icon': Icons.pending, - 'color': const Color(0xFFFF9500), + 'color': AppColors.iosOrange, 'showIcon': true, }, { 'label': '已拒审', 'value': _statsData?['count_apply_reject'] ?? 0, 'icon': Icons.block, - 'color': const Color(0xFFFF3B30), + 'color': AppColors.iosRed, 'showIcon': true, }, { 'label': '每日一句', 'value': _statsData?['count_article'] ?? 0, 'icon': Icons.wb_sunny, - 'color': const Color(0xFF5856D6), + 'color': AppColors.iosPurple, 'showIcon': true, }, { 'label': '文章分类', 'value': _statsData?['count_article_category'] ?? 0, 'icon': Icons.folder, - 'color': const Color(0xFFAF52DE), + 'color': AppColors.iosPink, 'showIcon': true, }, { 'label': '推送', 'value': _statsData?['count_notice'] ?? 0, 'icon': Icons.campaign, - 'color': const Color(0xFF32ADE6), + 'color': AppColors.iosTeal, 'showIcon': true, }, { 'label': '开发者', 'value': _statsData?['count_link'] ?? 0, 'icon': Icons.people, - 'color': const Color(0xFFFF2D55), + 'color': AppColors.iosRed, 'showIcon': true, }, { @@ -687,7 +690,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -699,7 +702,6 @@ class _EntirePageState extends State ), child: Column( children: [ - // 上行:icon和数据,比例2:1(有icon时1:1,无icon时数据占满) Expanded( flex: 2, child: Row( @@ -723,7 +725,7 @@ class _EntirePageState extends State style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, ), textAlign: TextAlign.center, ), @@ -732,7 +734,6 @@ class _EntirePageState extends State ), ), const SizedBox(height: 4), - // 下行:描述 Expanded( flex: 1, child: Center( @@ -740,7 +741,7 @@ class _EntirePageState extends State label, style: TextStyle( fontSize: 12, - color: isDark ? Colors.grey[400] : const Color(0xFF3C3C43), + color: AppColors.secondaryText, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -759,7 +760,7 @@ class _EntirePageState extends State '累计热度', _statsData?['cumulative_hits']?.toString() ?? '0', Icons.local_fire_department, - const Color(0xFFFF9500), + AppColors.iosOrange, isDark, ), const SizedBox(height: 12), @@ -767,7 +768,7 @@ class _EntirePageState extends State '累计点赞', _statsData?['cumulative_likes']?.toString() ?? '0', Icons.favorite, - const Color(0xFFFF2D55), + AppColors.iosRed, isDark, ), ], isDark); @@ -783,7 +784,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -813,7 +814,7 @@ class _EntirePageState extends State label, style: TextStyle( fontSize: 14, - color: isDark ? Colors.grey[400] : const Color(0xFF8E8E93), + color: AppColors.secondaryText, ), ), const SizedBox(height: 4), @@ -822,7 +823,7 @@ class _EntirePageState extends State style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, ), ), ], @@ -839,7 +840,7 @@ class _EntirePageState extends State '今日热门', _statsData?['top_hits_day'], Icons.today, - const Color(0xFFFF9500), + AppColors.iosOrange, isDark, ), const SizedBox(height: 12), @@ -847,7 +848,7 @@ class _EntirePageState extends State '本月热门', _statsData?['top_hits_month'], Icons.calendar_month, - const Color(0xFF007AFF), + AppColors.iosBlue, isDark, ), const SizedBox(height: 12), @@ -855,7 +856,7 @@ class _EntirePageState extends State '历史最热', _statsData?['top_hits_total'], Icons.history, - const Color(0xFF5856D6), + AppColors.iosPurple, isDark, ), const SizedBox(height: 12), @@ -863,7 +864,7 @@ class _EntirePageState extends State '最高点赞', _statsData?['top_like'], Icons.thumb_up, - const Color(0xFF34C759), + AppColors.iosGreen, isDark, ), ], isDark); @@ -882,7 +883,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -914,7 +915,7 @@ class _EntirePageState extends State style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, ), ), const SizedBox(height: 8), @@ -923,8 +924,8 @@ class _EntirePageState extends State style: TextStyle( fontSize: 13, color: hasData - ? (isDark ? Colors.grey[400] : const Color(0xFF3C3C43)) - : (isDark ? Colors.grey[500] : const Color(0xFF8E8E93)), + ? AppColors.secondaryText + : AppColors.tertiaryText, height: 1.5, ), maxLines: 3, @@ -954,7 +955,7 @@ class _EntirePageState extends State return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -970,12 +971,12 @@ class _EntirePageState extends State width: 40, height: 40, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: AppColors.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), - child: const Icon( + child: Icon( Icons.cake, - color: AppConstants.primaryColor, + color: AppColors.primary, size: 20, ), ), @@ -989,7 +990,7 @@ class _EntirePageState extends State style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, ), ), const SizedBox(height: 4), @@ -999,9 +1000,7 @@ class _EntirePageState extends State buildTime, style: TextStyle( fontSize: 16, - color: isDark - ? Colors.grey[400] - : const Color(0xFF3C3C43), + color: AppColors.secondaryText, ), ), const SizedBox(width: 8), @@ -1011,14 +1010,14 @@ class _EntirePageState extends State vertical: 2, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: AppColors.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(10), ), child: Text( '已运行 $days 天', - style: const TextStyle( + style: TextStyle( fontSize: 12, - color: AppConstants.primaryColor, + color: AppColors.primary, fontWeight: FontWeight.w500, ), ), @@ -1041,7 +1040,7 @@ class _EntirePageState extends State ) { return Container( decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -1058,14 +1057,14 @@ class _EntirePageState extends State padding: const EdgeInsets.all(16), child: Row( children: [ - Icon(icon, color: AppConstants.primaryColor, size: 20), + Icon(icon, color: AppColors.primary, size: 20), const SizedBox(width: 8), Text( title, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: isDark ? Colors.white : Colors.black, + color: AppColors.primaryText, ), ), ], diff --git a/lib/views/profile/components/login_register_dialog.dart b/lib/views/profile/components/login_register_dialog.dart index ef65b44..c7aa648 100644 --- a/lib/views/profile/components/login_register_dialog.dart +++ b/lib/views/profile/components/login_register_dialog.dart @@ -1,9 +1,12 @@ /// 时间: 2026-03-29 /// 功能: 填写投票凭证弹窗组件 /// 介绍: 提供投票功能的用户凭证填写功能 +/// 最新变化: 支持动态主题色设置 import 'package:flutter/material.dart'; -import '../../../constants/app_constants.dart'; +import 'package:get/get.dart'; +import '../../../models/colors/app_colors.dart'; +import '../../../services/get/theme_controller.dart'; import '../../../utils/http/vote_api.dart'; class LoginRegisterDialog extends StatefulWidget { @@ -16,6 +19,7 @@ class LoginRegisterDialog extends StatefulWidget { } class _LoginRegisterDialogState extends State { + final ThemeController _themeController = Get.find(); final _formKey = GlobalKey(); final _usernameController = TextEditingController(); bool _isLoading = false; @@ -63,9 +67,9 @@ class _LoginRegisterDialogState extends State { Navigator.pop(context); widget.onLoginSuccess?.call(); ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('验证成功'), - backgroundColor: AppConstants.successColor, + SnackBar( + content: const Text('验证成功'), + backgroundColor: AppColors.success, ), ); } @@ -80,9 +84,9 @@ class _LoginRegisterDialogState extends State { Navigator.pop(context); widget.onLoginSuccess?.call(); ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('注册并验证成功'), - backgroundColor: AppConstants.successColor, + SnackBar( + content: const Text('注册并验证成功'), + backgroundColor: AppColors.success, ), ); } @@ -92,7 +96,7 @@ class _LoginRegisterDialogState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toString().replaceAll('Exception: ', '')), - backgroundColor: AppConstants.errorColor, + backgroundColor: AppColors.error, ), ); } @@ -107,80 +111,101 @@ class _LoginRegisterDialogState extends State { @override Widget build(BuildContext context) { - return Dialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - child: Container( - padding: const EdgeInsets.all(20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Text( - '填写 投票凭证', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), - IconButton( - icon: const Icon(Icons.close), - onPressed: () => Navigator.pop(context), - ), - ], - ), - // const SizedBox(height: 8), - // 副标题 - const Text( - '微信号或手机号或邮箱作为投票凭证,\n任何人都可以填写,限时开放投票,\n投票凭证仅用于投票,不会泄露隐私.\n结束后删除会所有凭证,仅保留投票结果', - style: TextStyle(fontSize: 14, color: Colors.grey), - textAlign: TextAlign.center, - ), - const SizedBox(height: 2), - Form( - key: _formKey, - child: Column( + return Obx(() { + final isDark = _themeController.isDarkMode; + return Dialog( + backgroundColor: AppColors.surface, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + child: Container( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextFormField( - controller: _usernameController, - decoration: const InputDecoration( - labelText: '点击填写', - hintText: '手机号/邮箱/微信号', - border: OutlineInputBorder(), - prefixIcon: Icon(Icons.person), + Text( + '填写 投票凭证', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: AppColors.primaryText, ), - validator: _validateUsername, ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: _isLoading ? null : _submit, - style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: _isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - Colors.white, - ), - ), - ) - : const Text('验证', style: TextStyle(fontSize: 16)), - ), + IconButton( + icon: Icon(Icons.close, color: AppColors.tertiaryText), + onPressed: () => Navigator.pop(context), ), ], ), - ), - ], + Text( + '微信号或手机号或邮箱作为投票凭证,\n任何人都可以填写,限时开放投票,\n投票凭证仅用于投票,不会泄露隐私.\n结束后删除会所有凭证,仅保留投票结果', + style: TextStyle( + fontSize: 14, + color: AppColors.secondaryText, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 2), + Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + controller: _usernameController, + style: TextStyle(color: AppColors.primaryText), + decoration: InputDecoration( + labelText: '点击填写', + hintText: '手机号/邮箱/微信号', + labelStyle: TextStyle(color: AppColors.secondaryText), + hintStyle: TextStyle(color: AppColors.tertiaryText), + border: OutlineInputBorder( + borderSide: BorderSide(color: AppColors.divider), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: AppColors.divider), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: AppColors.primary), + ), + prefixIcon: Icon(Icons.person, color: AppColors.primary), + ), + validator: _validateUsername, + ), + const SizedBox(height: 24), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _isLoading ? null : _submit, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.primary, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: _isLoading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation( + Colors.white, + ), + ), + ) + : const Text('验证', style: TextStyle(fontSize: 16)), + ), + ), + ], + ), + ), + ], + ), ), - ), - ); + ); + }); } } diff --git a/lib/views/profile/components/pop-menu.dart b/lib/views/profile/components/pop-menu.dart index e0d0cc4..b81738c 100644 --- a/lib/views/profile/components/pop-menu.dart +++ b/lib/views/profile/components/pop-menu.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:share_plus/share_plus.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; +import '../../../models/colors/app_colors.dart'; import '../../../services/isweb/wakelock_service.dart'; import '../../../services/get/theme_controller.dart'; import '../guide/beginner_page.dart'; @@ -91,12 +91,13 @@ class PopMenu extends StatelessWidget { showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('提示'), - content: Text(errorMessage), + backgroundColor: AppColors.surface, + title: Text('提示', style: TextStyle(color: AppColors.primaryText)), + content: Text(errorMessage, style: TextStyle(color: AppColors.secondaryText)), actions: [ TextButton( onPressed: () => Navigator.pop(context), - child: const Text('确定'), + child: Text('确定', style: TextStyle(color: AppColors.primary)), ), ], ), @@ -134,7 +135,7 @@ class PopMenu extends StatelessWidget { return Container( width: double.infinity, decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + color: AppColors.surface, borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), boxShadow: [ BoxShadow( @@ -162,7 +163,7 @@ class PopMenu extends StatelessWidget { height: 4, margin: const EdgeInsets.only(top: 8), decoration: BoxDecoration( - color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + color: AppColors.divider, borderRadius: BorderRadius.circular(2), ), ), @@ -208,16 +209,14 @@ class PopMenu extends StatelessWidget { IconData icon, VoidCallback? onTap, ) { - final isDark = _themeController.isDarkMode; - return ListTile( leading: Icon( icon, - color: isDark ? Colors.white70 : AppConstants.primaryColor, + color: AppColors.primary, ), title: Text( title, - style: TextStyle(color: isDark ? Colors.white70 : Colors.black87), + style: TextStyle(color: AppColors.primaryText), ), onTap: () { Navigator.pop(context); diff --git a/lib/views/profile/components/server_info_dialog.dart b/lib/views/profile/components/server_info_dialog.dart index 6d59199..fe48d5f 100644 --- a/lib/views/profile/components/server_info_dialog.dart +++ b/lib/views/profile/components/server_info_dialog.dart @@ -1,7 +1,9 @@ library; import 'package:flutter/material.dart'; -import '../../../constants/app_constants.dart'; +import 'package:get/get.dart'; +import '../../../models/colors/app_colors.dart'; +import '../../../services/get/theme_controller.dart'; class ServerInfoDialog { static Future show(BuildContext context, {Map? data}) { @@ -13,236 +15,241 @@ class ServerInfoDialog { final latency = network?['latency'] as List?; final serverResponseTime = network?['server_response_time']; + final ThemeController themeController = Get.find(); + return showDialog( context: context, builder: (BuildContext context) { - return Dialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - child: Container( - constraints: const BoxConstraints(maxWidth: 340), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: AppConstants.primaryColor, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(16), + return Obx(() { + final isDark = themeController.isDarkMode; + return Dialog( + backgroundColor: AppColors.surface, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Container( + constraints: const BoxConstraints(maxWidth: 340), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColors.primary, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(16), + ), ), - ), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.2), - borderRadius: BorderRadius.circular(8), - ), - child: const Icon( - Icons.cloud_outlined, - color: Colors.white, - size: 20, - ), - ), - const SizedBox(width: 12), - const Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '广州 server-ls', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 2), - Text( - '服务器信息', - style: TextStyle( - color: Colors.white70, - fontSize: 12, - ), - ), - ], - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - _buildInfoCard( - icon: Icons.schedule, - iconColor: const Color(0xFF007AFF), - title: '服务器时间', - content: timestamp?['datetime'] ?? '--', - ), - const SizedBox(height: 12), - _buildInfoCard( - icon: Icons.speed, - iconColor: const Color(0xFF34C759), - title: '服务器负载', - content: - '1分钟: ${_formatLoad(load?['1min'])}\n5分钟: ${_formatLoad(load?['5min'])}\n15分钟: ${_formatLoad(load?['15min'])}', - ), - const SizedBox(height: 12), - _buildInfoCard( - icon: Icons.bolt, - iconColor: const Color(0xFFFF9500), - title: '服务器响应', - content: '${serverResponseTime ?? '--'} ms', - trailing: _buildResponseTimeIndicator( - serverResponseTime, - ), - ), - if (latency != null && latency.isNotEmpty) ...[ - const SizedBox(height: 16), + child: Row( + children: [ Container( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: const Color(0xFFF2F2F7), - borderRadius: BorderRadius.circular(12), + color: Colors.white.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(8), ), + child: const Icon( + Icons.cloud_outlined, + color: Colors.white, + size: 20, + ), + ), + const SizedBox(width: 12), + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Icon( - Icons.public, - size: 16, - color: Colors.grey[600], - ), - const SizedBox(width: 8), - Text( - '网络延迟', - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: Colors.grey[700], - ), - ), - ], + const Text( + '广州 server-ls', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 2), + Text( + '服务器信息', + style: TextStyle( + color: Colors.white.withValues(alpha: 0.7), + fontSize: 12, + ), ), - const SizedBox(height: 12), - ...latency.map((item) { - final host = item['host'] as String?; - final ip = item['ip'] as String?; - final lat = item['latency']; - final status = item['status'] as String?; - final isOnline = status == 'online'; - - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: isOnline - ? const Color(0xFF34C759) - : const Color(0xFFFF3B30), - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - host ?? '--', - style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.w500, - ), - ), - Text( - ip ?? '--', - style: TextStyle( - fontSize: 11, - color: Colors.grey[500], - ), - ), - ], - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - color: isOnline - ? const Color( - 0xFF34C759, - ).withValues(alpha: 0.1) - : const Color( - 0xFFFF3B30, - ).withValues(alpha: 0.1), - borderRadius: BorderRadius.circular( - 8, - ), - ), - child: Text( - isOnline ? '$lat ms' : '离线', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: isOnline - ? const Color(0xFF34C759) - : const Color(0xFFFF3B30), - ), - ), - ), - ], - ), - ); - }), ], ), ), ], - ], + ), ), - ), - Padding( - padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), - child: SizedBox( - width: double.infinity, - child: TextButton( - onPressed: () => Navigator.of(context).pop(), - style: TextButton.styleFrom( - backgroundColor: const Color(0xFFF2F2F7), - padding: const EdgeInsets.symmetric(vertical: 14), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + _buildInfoCard( + icon: Icons.schedule, + iconColor: AppColors.iosBlue, + title: '服务器时间', + content: timestamp?['datetime'] ?? '--', ), - ), - child: const Text( - '关闭', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Color(0xFF007AFF), + const SizedBox(height: 12), + _buildInfoCard( + icon: Icons.speed, + iconColor: AppColors.iosGreen, + title: '服务器负载', + content: + '1分钟: ${_formatLoad(load?['1min'])}\n5分钟: ${_formatLoad(load?['5min'])}\n15分钟: ${_formatLoad(load?['15min'])}', + ), + const SizedBox(height: 12), + _buildInfoCard( + icon: Icons.bolt, + iconColor: AppColors.iosOrange, + title: '服务器响应', + content: '${serverResponseTime ?? '--'} ms', + trailing: _buildResponseTimeIndicator( + serverResponseTime, + ), + ), + if (latency != null && latency.isNotEmpty) ...[ + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColors.card, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon( + Icons.public, + size: 16, + color: AppColors.tertiaryText, + ), + const SizedBox(width: 8), + Text( + '网络延迟', + style: TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + color: AppColors.secondaryText, + ), + ), + ], + ), + const SizedBox(height: 12), + ...latency.map((item) { + final host = item['host'] as String?; + final ip = item['ip'] as String?; + final lat = item['latency']; + final status = item['status'] as String?; + final isOnline = status == 'online'; + + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: isOnline + ? AppColors.iosGreen + : AppColors.iosRed, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + host ?? '--', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: AppColors.primaryText, + ), + ), + Text( + ip ?? '--', + style: TextStyle( + fontSize: 11, + color: AppColors.tertiaryText, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: isOnline + ? AppColors.iosGreen + .withValues(alpha: 0.1) + : AppColors.iosRed + .withValues(alpha: 0.1), + borderRadius: BorderRadius.circular( + 8, + ), + ), + child: Text( + isOnline ? '$lat ms' : '离线', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: isOnline + ? AppColors.iosGreen + : AppColors.iosRed, + ), + ), + ), + ], + ), + ); + }), + ], + ), + ), + ], + ], + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + child: SizedBox( + width: double.infinity, + child: TextButton( + onPressed: () => Navigator.of(context).pop(), + style: TextButton.styleFrom( + backgroundColor: AppColors.card, + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: Text( + '关闭', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: AppColors.primary, + ), ), ), ), ), - ), - ], + ], + ), ), - ), - ); + ); + }); }, ); } @@ -257,7 +264,7 @@ class ServerInfoDialog { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: const Color(0xFFF2F2F7), + color: AppColors.card, borderRadius: BorderRadius.circular(12), ), child: Row( @@ -277,14 +284,18 @@ class ServerInfoDialog { children: [ Text( title, - style: TextStyle(fontSize: 12, color: Colors.grey[600]), + style: TextStyle( + fontSize: 12, + color: AppColors.tertiaryText, + ), ), const SizedBox(height: 2), Text( content, - style: const TextStyle( + style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, + color: AppColors.primaryText, ), ), ], @@ -327,16 +338,16 @@ class ServerInfoDialog { Color color; String label; if (time < 100) { - color = const Color(0xFF34C759); + color = AppColors.iosGreen; label = '极快'; } else if (time < 300) { - color = const Color(0xFF34C759); + color = AppColors.iosGreen; label = '快速'; } else if (time < 500) { - color = const Color(0xFFFF9500); + color = AppColors.iosOrange; label = '正常'; } else { - color = const Color(0xFFFF3B30); + color = AppColors.iosRed; label = '较慢'; } diff --git a/lib/views/profile/expand/manu-script.dart b/lib/views/profile/expand/manu-script.dart index a7380cc..6ed21eb 100644 --- a/lib/views/profile/expand/manu-script.dart +++ b/lib/views/profile/expand/manu-script.dart @@ -1,9 +1,11 @@ import 'dart:io' as io; import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; import '../../../utils/http/http_client.dart'; +import '../../../services/get/theme_controller.dart'; import 'tougao.dart'; /// 时间: 2026-03-30 @@ -24,6 +26,7 @@ class _ManuscriptPageState extends State { final _urlController = TextEditingController(); final _keywordsController = TextEditingController(); final _introduceController = TextEditingController(); + final ThemeController _themeController = Get.find(); List> _categories = []; String? _selectedCategory; @@ -356,26 +359,28 @@ class _ManuscriptPageState extends State { @override Widget build(BuildContext context) { + final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; + return Scaffold( - backgroundColor: const Color(0xFFF5F5F5), + backgroundColor: isDark + ? const Color(0xFF1A1A1A) + : const Color(0xFFF5F5F5), appBar: AppBar( - title: const Text( + title: Text( '📝 诗词投稿', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), - backgroundColor: Colors.white, + backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: const Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), actions: [ IconButton( - icon: const Icon(Icons.history, color: AppConstants.primaryColor), + icon: Icon(Icons.history, color: primaryColor), tooltip: '投稿记录', onPressed: () { Navigator.push( @@ -405,14 +410,14 @@ class _ManuscriptPageState extends State { } Widget _buildHeaderCard() { + final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; + return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - AppConstants.primaryColor.withAlpha(30), - AppConstants.primaryColor.withAlpha(10), - ], + colors: [primaryColor.withAlpha(30), primaryColor.withAlpha(10)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), @@ -423,28 +428,31 @@ class _ManuscriptPageState extends State { Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.white, + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(12), ), - child: const Icon( - Icons.edit_note, - color: AppConstants.primaryColor, - size: 32, - ), + child: Icon(Icons.edit_note, color: primaryColor, size: 32), ), const SizedBox(width: 16), - const Expanded( + Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '收录经典诗词', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), ), - SizedBox(height: 4), + const SizedBox(height: 4), Text( '支持原创和古诗,传承中华文化', - style: TextStyle(fontSize: 14, color: Colors.grey), + style: TextStyle( + fontSize: 14, + color: isDark ? Colors.grey[400] : Colors.grey, + ), ), ], ), @@ -455,13 +463,15 @@ class _ManuscriptPageState extends State { } Widget _buildFormCard() { + final isDark = _themeController.isDarkMode; + return Container( decoration: BoxDecoration( - color: Colors.white, + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withAlpha(10), + color: Colors.black.withAlpha(isDark ? 30 : 10), blurRadius: 10, offset: const Offset(0, 2), ), @@ -493,13 +503,19 @@ class _ManuscriptPageState extends State { } Widget _buildSectionHeader(String title) { + final isDark = _themeController.isDarkMode; + return Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Text( title, - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), ), ], ), @@ -507,14 +523,20 @@ class _ManuscriptPageState extends State { } Widget _buildNameField() { + final isDark = _themeController.isDarkMode; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ - const Text( + Text( '参考语句', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black87, + ), ), const Text(' *', style: TextStyle(color: AppConstants.errorColor)), const Spacer(), @@ -531,7 +553,22 @@ class _ManuscriptPageState extends State { controller: _nameController, decoration: InputDecoration( hintText: '如:纤云弄巧,飞星传恨', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + hintStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: _themeController.currentThemeColor, + width: 2, + ), + ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, @@ -545,6 +582,7 @@ class _ManuscriptPageState extends State { ) : null, ), + style: TextStyle(color: isDark ? Colors.white : Colors.black87), validator: (value) { if (value == null || value.trim().isEmpty) { return '请输入参考语句'; @@ -594,8 +632,15 @@ class _ManuscriptPageState extends State { ), TextButton.icon( onPressed: _isCheckingName ? null : _checkName, - icon: const Icon(Icons.search, size: 18), - label: const Text('检测是否存在'), + icon: Icon( + Icons.search, + size: 18, + color: _themeController.currentThemeColor, + ), + label: Text( + '检测是否存在', + style: TextStyle(color: _themeController.currentThemeColor), + ), ), ], ), @@ -642,16 +687,22 @@ class _ManuscriptPageState extends State { } Widget _buildCategoryField() { + final isDark = _themeController.isDarkMode; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Row( + Row( children: [ Text( '分类', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black87, + ), ), - Text(' *', style: TextStyle(color: AppConstants.errorColor)), + const Text(' *', style: TextStyle(color: AppConstants.errorColor)), ], ), const SizedBox(height: 8), @@ -659,7 +710,22 @@ class _ManuscriptPageState extends State { value: _selectedCategory, decoration: InputDecoration( hintText: '请选择分类', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + hintStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: _themeController.currentThemeColor, + width: 2, + ), + ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, @@ -668,12 +734,17 @@ class _ManuscriptPageState extends State { items: _categories.map((cat) { return DropdownMenuItem( value: cat['catename'] as String, - child: Text(cat['catename'] as String), + child: Text( + cat['catename'] as String, + style: TextStyle(color: isDark ? Colors.white : Colors.black87), + ), ); }).toList(), onChanged: (value) { setState(() => _selectedCategory = value); }, + dropdownColor: isDark ? const Color(0xFF333333) : Colors.white, + style: TextStyle(color: isDark ? Colors.white : Colors.black87), validator: (value) { if (value == null || value.isEmpty) { return '请选择分类'; @@ -686,16 +757,22 @@ class _ManuscriptPageState extends State { } Widget _buildUrlField() { + final isDark = _themeController.isDarkMode; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Row( + Row( children: [ Text( '诗人和标题', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black87, + ), ), - Text(' *', style: TextStyle(color: AppConstants.errorColor)), + const Text(' *', style: TextStyle(color: AppConstants.errorColor)), ], ), const SizedBox(height: 8), @@ -703,12 +780,28 @@ class _ManuscriptPageState extends State { controller: _urlController, decoration: InputDecoration( hintText: '如:李白 静夜思', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + hintStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: _themeController.currentThemeColor, + width: 2, + ), + ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), + style: TextStyle(color: isDark ? Colors.white : Colors.black87), validator: (value) { if (value == null || value.trim().isEmpty) { return '请输入诗人和标题'; @@ -721,16 +814,22 @@ class _ManuscriptPageState extends State { } Widget _buildKeywordsField() { + final isDark = _themeController.isDarkMode; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Row( + Row( children: [ Text( '关键词', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black87, + ), ), - Text(' *', style: TextStyle(color: AppConstants.errorColor)), + const Text(' *', style: TextStyle(color: AppConstants.errorColor)), ], ), const SizedBox(height: 8), @@ -738,12 +837,28 @@ class _ManuscriptPageState extends State { controller: _keywordsController, decoration: InputDecoration( hintText: '用逗号分隔,如:思乡,月亮,唐诗', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + hintStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: _themeController.currentThemeColor, + width: 2, + ), + ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12, ), ), + style: TextStyle(color: isDark ? Colors.white : Colors.black87), validator: (value) { if (value == null || value.trim().isEmpty) { return '请输入关键词'; @@ -756,16 +871,22 @@ class _ManuscriptPageState extends State { } Widget _buildIntroduceField() { + final isDark = _themeController.isDarkMode; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Row( + Row( children: [ Text( '诗词介绍', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black87, + ), ), - Text(' *', style: TextStyle(color: AppConstants.errorColor)), + const Text(' *', style: TextStyle(color: AppConstants.errorColor)), ], ), const SizedBox(height: 8), @@ -774,9 +895,25 @@ class _ManuscriptPageState extends State { maxLines: 5, decoration: InputDecoration( hintText: '会说就多说几句...', - border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), + hintStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey[400], + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: isDark ? Colors.grey[600]! : Colors.grey[300]!, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide( + color: _themeController.currentThemeColor, + width: 2, + ), + ), contentPadding: const EdgeInsets.all(16), ), + style: TextStyle(color: isDark ? Colors.white : Colors.black87), validator: (value) { if (value == null || value.trim().isEmpty) { return '请输入诗词介绍'; @@ -789,19 +926,18 @@ class _ManuscriptPageState extends State { } Widget _buildSubmitButton() { + final primaryColor = _themeController.currentThemeColor; + return Container( height: 56, decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(200), - ], + colors: [primaryColor, primaryColor.withAlpha(200)], ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withAlpha(50), + color: primaryColor.withAlpha(50), blurRadius: 10, offset: const Offset(0, 4), ), @@ -845,10 +981,13 @@ class _ManuscriptPageState extends State { } Widget _buildTipsCard() { + final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; + return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.blue[50], + color: isDark ? primaryColor.withAlpha(20) : primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(12), ), child: Column( @@ -856,14 +995,14 @@ class _ManuscriptPageState extends State { children: [ Row( children: [ - Icon(Icons.lightbulb_outline, color: Colors.blue[700], size: 20), + Icon(Icons.lightbulb_outline, color: primaryColor, size: 20), const SizedBox(width: 8), Text( '投稿提示', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, - color: Colors.blue[700], + color: primaryColor, ), ), ], @@ -873,7 +1012,7 @@ class _ManuscriptPageState extends State { '• 支持原创诗词和经典古诗\n• 相似度超过80%将无法提交\n• 提交后等待审核通过\n• 平台信息自动识别:${_getPlatform()}', style: TextStyle( fontSize: 13, - color: Colors.blue[700], + color: isDark ? Colors.grey[300] : primaryColor, height: 1.5, ), ), diff --git a/lib/views/profile/expand/tougao.dart b/lib/views/profile/expand/tougao.dart index b9d24ef..f35c930 100644 --- a/lib/views/profile/expand/tougao.dart +++ b/lib/views/profile/expand/tougao.dart @@ -145,7 +145,7 @@ class _TougaoPageState extends State { appBar: AppBar( title: Text( '投稿记录', - style: TextStyle(color: isDark ? Colors.white : Colors.black87), + style: TextStyle(color: _themeController.currentThemeColor), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, @@ -154,7 +154,7 @@ class _TougaoPageState extends State { IconButton( icon: Icon( Icons.delete_sweep_outlined, - color: isDark ? Colors.white : Colors.black87, + color: _themeController.currentThemeColor, ), onPressed: _clearAllRecords, tooltip: '清空记录', @@ -230,14 +230,16 @@ class _TougaoPageState extends State { Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.2), + color: _themeController.currentThemeColor.withValues( + alpha: 0.2, + ), borderRadius: BorderRadius.circular(8), ), child: Text( record.catename, style: TextStyle( fontSize: 12, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.w500, ), ), diff --git a/lib/views/profile/expand/vote.dart b/lib/views/profile/expand/vote.dart index c14a43b..7d70a91 100644 --- a/lib/views/profile/expand/vote.dart +++ b/lib/views/profile/expand/vote.dart @@ -158,7 +158,7 @@ class _VotePageState extends State { ), backgroundColor: isDark ? const Color(0xFF2A2A2A) - : AppConstants.primaryColor, + : _themeController.currentThemeColor, elevation: 0, actions: [ if (_isLoggedIn) @@ -216,7 +216,7 @@ class _VotePageState extends State { onPressed: _loadVoteList, style: ElevatedButton.styleFrom( backgroundColor: - AppConstants.primaryColor, + _themeController.currentThemeColor, ), child: const Text('刷新'), ), @@ -321,14 +321,14 @@ class _VotePageState extends State { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( vote.isSingleChoice ? Icons.radio_button_checked : Icons.check_box, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 20, ), ), @@ -805,7 +805,7 @@ class _VoteDetailPageState extends State { ), backgroundColor: isDark ? const Color(0xFF2A2A2A) - : AppConstants.primaryColor, + : _themeController.currentThemeColor, elevation: 0, ), body: _isLoading @@ -821,10 +821,10 @@ class _VoteDetailPageState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withValues( + _themeController.currentThemeColor.withValues( alpha: isDark ? 0.3 : 0.1, ), - AppConstants.primaryColor.withValues( + _themeController.currentThemeColor.withValues( alpha: isDark ? 0.15 : 0.05, ), ], @@ -841,7 +841,7 @@ class _VoteDetailPageState extends State { Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues( + color: _themeController.currentThemeColor.withValues( alpha: 0.15, ), borderRadius: BorderRadius.circular(10), @@ -850,7 +850,7 @@ class _VoteDetailPageState extends State { widget.vote.isSingleChoice ? Icons.radio_button_checked : Icons.check_box, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 24, ), ), @@ -1134,13 +1134,13 @@ class _VoteDetailPageState extends State { decoration: BoxDecoration( border: Border.all( color: isSelected - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.grey[600]! : Colors.grey[300]!), width: 2, ), borderRadius: BorderRadius.circular(12), color: isSelected - ? AppConstants.primaryColor.withValues(alpha: 0.05) + ? _themeController.currentThemeColor.withValues(alpha: 0.05) : (isDark ? const Color(0xFF2A2A2A) : Colors.white), ), child: InkWell( @@ -1159,7 +1159,7 @@ class _VoteDetailPageState extends State { ? Icons.check_box : Icons.check_box_outline_blank), color: isSelected - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.grey[400] : Colors.grey), ), const SizedBox(width: 12), @@ -1175,7 +1175,7 @@ class _VoteDetailPageState extends State { ? FontWeight.bold : FontWeight.normal, color: isSelected - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.white : Colors.black), ), ), @@ -1207,7 +1207,7 @@ class _VoteDetailPageState extends State { child: ElevatedButton( onPressed: _isSubmitting ? null : _submitVote, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -1309,7 +1309,7 @@ class _VoteDetailPageState extends State { icon: Icons.poll, label: '总票数', value: '${_voteResult!.totalVotes}', - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, isDark: isDark, ), Container( @@ -1446,7 +1446,7 @@ class _VoteDetailPageState extends State { decoration: BoxDecoration( color: isVoted ? AppConstants.successColor.withValues(alpha: 0.1) - : AppConstants.primaryColor.withValues(alpha: 0.1), + : _themeController.currentThemeColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Text( @@ -1454,7 +1454,7 @@ class _VoteDetailPageState extends State { style: TextStyle( color: isVoted ? AppConstants.successColor - : AppConstants.primaryColor, + : _themeController.currentThemeColor, fontSize: 14, fontWeight: FontWeight.bold, ), @@ -1476,7 +1476,7 @@ class _VoteDetailPageState extends State { valueColor: AlwaysStoppedAnimation( isVoted ? AppConstants.successColor - : AppConstants.primaryColor, + : _themeController.currentThemeColor, ), minHeight: 8, ), diff --git a/lib/views/profile/guide/app-data.dart b/lib/views/profile/guide/app-data.dart index 7f698cf..518c67b 100644 --- a/lib/views/profile/guide/app-data.dart +++ b/lib/views/profile/guide/app-data.dart @@ -205,7 +205,7 @@ class _AppDataPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('配置数据已清空,请重新启动应用'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, duration: const Duration(seconds: 3), ), ); @@ -348,7 +348,7 @@ class _AppDataPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('缓存已清空'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -415,7 +415,7 @@ class _AppDataPageState extends State { title.contains('⚠️') ? Icons.warning : Icons.help_outline, color: title.contains('⚠️') ? Colors.orange - : AppConstants.primaryColor, + : _themeController.currentThemeColor, ), const SizedBox(width: 8), Expanded(child: Text(title, style: const TextStyle(fontSize: 18))), @@ -432,7 +432,7 @@ class _AppDataPageState extends State { style: ElevatedButton.styleFrom( backgroundColor: title.contains('危险') || title.contains('再次') ? Colors.red - : AppConstants.primaryColor, + : _themeController.currentThemeColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -489,7 +489,7 @@ class _AppDataPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -498,6 +498,7 @@ class _AppDataPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark @@ -508,9 +509,7 @@ class _AppDataPageState extends State { '应用数据', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), - backgroundColor: isDark - ? const Color(0xFF2A2A2A) - : AppConstants.primaryColor, + backgroundColor: isDark ? const Color(0xFF2A2A2A) : primaryColor, iconTheme: IconThemeData(color: Colors.white), ), body: _isLoading @@ -551,14 +550,14 @@ class _AppDataPageState extends State { Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withAlpha(10), borderRadius: const BorderRadius.vertical( top: Radius.circular(16), ), ), child: Row( children: [ - Icon(Icons.storage, color: AppConstants.primaryColor), + Icon(Icons.storage, color: _themeController.currentThemeColor), const SizedBox(width: 8), const Text( '数据概览', diff --git a/lib/views/profile/guide/beginner_page.dart b/lib/views/profile/guide/beginner_page.dart index 3e0fe5f..a0802ca 100644 --- a/lib/views/profile/guide/beginner_page.dart +++ b/lib/views/profile/guide/beginner_page.dart @@ -24,7 +24,7 @@ class _BeginnerPageState extends State 'title': '首页功能', 'icon': Icons.home, 'emoji': '🏠', - 'color': AppConstants.primaryColor, + 'color': Colors.blue, 'features': [ '精美卡片展示', '智能推荐:根据时间和情景推荐合适的诗词', @@ -271,6 +271,7 @@ class _BeginnerPageState extends State Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.grey[50], body: Stack( @@ -286,13 +287,13 @@ class _BeginnerPageState extends State style: TextStyle( fontWeight: FontWeight.bold, fontSize: 17, - color: AppConstants.primaryColor, + color: primaryColor, ), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, - foregroundColor: AppConstants.primaryColor, + foregroundColor: primaryColor, elevation: 0, centerTitle: true, floating: true, @@ -301,7 +302,7 @@ class _BeginnerPageState extends State actions: [ IconButton( icon: const Icon(Icons.help_outline), - color: AppConstants.primaryColor, + color: primaryColor, onPressed: () { Navigator.push( context, @@ -497,7 +498,7 @@ class _BeginnerPageState extends State Icon( Icons.visibility_outlined, size: 16, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), const SizedBox(width: 6), Text( @@ -505,7 +506,7 @@ class _BeginnerPageState extends State style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), ], @@ -532,13 +533,13 @@ class _BeginnerPageState extends State width: 32, height: 32, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.book, size: 18, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), const SizedBox(width: 10), @@ -689,7 +690,7 @@ class _BeginnerPageState extends State width: 48, height: 48, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.2), + color: _themeController.currentThemeColor.withAlpha(20), borderRadius: BorderRadius.circular(24), ), child: const Center( @@ -760,14 +761,14 @@ class _BeginnerPageState extends State color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: _themeController.currentThemeColor.withAlpha(30), ), ), child: Text( text, style: TextStyle( fontSize: 12, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.w500, ), ), @@ -812,7 +813,7 @@ class _BeginnerPageState extends State style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), const SizedBox(height: 2), @@ -873,12 +874,12 @@ class _BeginnerPageState extends State width: 8, height: 40, decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, borderRadius: BorderRadius.circular(4), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues( - alpha: 0.3, + color: _themeController.currentThemeColor.withAlpha( + 30, ), blurRadius: 8, offset: const Offset(0, 2), @@ -895,11 +896,11 @@ class _BeginnerPageState extends State duration: const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.2), + color: _themeController.currentThemeColor.withAlpha(20), blurRadius: 4, offset: const Offset(0, 2), ), diff --git a/lib/views/profile/guide/permission.dart b/lib/views/profile/guide/permission.dart index 0971a12..8ac560d 100644 --- a/lib/views/profile/guide/permission.dart +++ b/lib/views/profile/guide/permission.dart @@ -41,6 +41,7 @@ class _PermissionPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -49,7 +50,7 @@ class _PermissionPageState extends State { title: Text( '权限管理', style: TextStyle( - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : primaryColor, fontWeight: FontWeight.bold, ), ), @@ -59,7 +60,7 @@ class _PermissionPageState extends State { leading: IconButton( icon: Icon( Icons.arrow_back, - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : primaryColor, ), onPressed: () => Navigator.pop(context), ), @@ -67,7 +68,7 @@ class _PermissionPageState extends State { IconButton( icon: Icon( Icons.info_outline, - color: isDark ? Colors.white : AppConstants.primaryColor, + color: isDark ? Colors.white : primaryColor, ), onPressed: _showPermissionInfoDialog, ), @@ -118,6 +119,14 @@ class _PermissionPageState extends State { null, isDark, ), + _buildPermissionItem( + '设备标识', + '获取设备唯一标识', + Icons.person, + _clipboardEnabled, + null, + isDark, + ), ], isDark), const SizedBox(height: 16), _buildPermissionGroup('权限说明', [ @@ -126,6 +135,7 @@ class _PermissionPageState extends State { _buildInfoItem('剪切板', '用于复制诗词内容,方便用户分享和记录。', isDark), _buildInfoItem('播放声音', '用于主页点击提示音,提升用户体验。', isDark), _buildInfoItem('分享能力', '用于分享诗词内容到社交媒体平台。', isDark), + _buildInfoItem('设备标识', '用于唯一标识设备,确保用户数据安全。', isDark), ], isDark), const SizedBox(height: 16), _buildSandboxInfoCard(isDark), @@ -161,14 +171,14 @@ class _PermissionPageState extends State { children: [ Icon( Icons.security, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 20, ), const SizedBox(width: 8), Text( title, style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -199,10 +209,14 @@ class _PermissionPageState extends State { width: 40, height: 40, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withAlpha(10), borderRadius: BorderRadius.circular(12), ), - child: Icon(icon, color: AppConstants.primaryColor, size: 20), + child: Icon( + icon, + color: _themeController.currentThemeColor, + size: 20, + ), ), const SizedBox(width: 12), Expanded( @@ -271,7 +285,7 @@ class _PermissionPageState extends State { height: 4, margin: const EdgeInsets.only(top: 6), decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, borderRadius: BorderRadius.circular(2), ), ), @@ -325,12 +339,16 @@ class _PermissionPageState extends State { padding: const EdgeInsets.all(16), child: Row( children: [ - Icon(Icons.build, color: AppConstants.primaryColor, size: 20), + Icon( + Icons.build, + color: _themeController.currentThemeColor, + size: 20, + ), const SizedBox(width: 8), Text( '项目补充完善', style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -389,10 +407,14 @@ class _PermissionPageState extends State { width: 40, height: 40, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withAlpha(10), borderRadius: BorderRadius.circular(12), ), - child: Icon(icon, color: AppConstants.primaryColor, size: 20), + child: Icon( + icon, + color: _themeController.currentThemeColor, + size: 20, + ), ), const SizedBox(width: 12), Expanded( @@ -435,7 +457,7 @@ class _PermissionPageState extends State { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.feedback, color: AppConstants.primaryColor), + Icon(Icons.feedback, color: _themeController.currentThemeColor), const SizedBox(width: 8), const Text('用户反馈'), ], @@ -456,7 +478,7 @@ class _PermissionPageState extends State { TextSpan( text: '情景诗词', style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.bold, ), ), @@ -469,7 +491,7 @@ class _PermissionPageState extends State { '记得五星好评 ⭐', style: TextStyle( fontSize: 14, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.w500, ), ), @@ -480,7 +502,7 @@ class _PermissionPageState extends State { onPressed: () => Navigator.pop(context), child: Text( '确定', - style: TextStyle(color: AppConstants.primaryColor), + style: TextStyle(color: _themeController.currentThemeColor), ), ), ], @@ -495,7 +517,7 @@ class _PermissionPageState extends State { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.lightbulb, color: AppConstants.primaryColor), + Icon(Icons.lightbulb, color: _themeController.currentThemeColor), const SizedBox(width: 8), const Text('功能建议'), ], @@ -516,7 +538,7 @@ class _PermissionPageState extends State { TextSpan( text: '情景诗词', style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.bold, ), ), @@ -529,7 +551,7 @@ class _PermissionPageState extends State { '记得五星好评 ⭐', style: TextStyle( fontSize: 14, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontWeight: FontWeight.w500, ), ), @@ -540,7 +562,7 @@ class _PermissionPageState extends State { onPressed: () => Navigator.pop(context), child: Text( '确定', - style: TextStyle(color: AppConstants.primaryColor), + style: TextStyle(color: _themeController.currentThemeColor), ), ), ], @@ -555,7 +577,7 @@ class _PermissionPageState extends State { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.info, color: AppConstants.primaryColor), + Icon(Icons.info, color: _themeController.currentThemeColor), const SizedBox(width: 8), const Text('基础权限说明'), ], @@ -569,7 +591,7 @@ class _PermissionPageState extends State { onPressed: () => Navigator.pop(context), child: Text( '确定', - style: TextStyle(color: AppConstants.primaryColor), + style: TextStyle(color: _themeController.currentThemeColor), ), ), ], @@ -599,12 +621,12 @@ class _PermissionPageState extends State { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.shield, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, size: 20, ), ), @@ -612,7 +634,7 @@ class _PermissionPageState extends State { Text( '沙盒运行说明', style: TextStyle( - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -652,14 +674,14 @@ class _PermissionPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - width: 4, - height: 4, - margin: const EdgeInsets.only(top: 8), - decoration: BoxDecoration( - color: AppConstants.primaryColor, - borderRadius: BorderRadius.circular(2), + width: 4, + height: 4, + margin: const EdgeInsets.only(top: 8), + decoration: BoxDecoration( + color: _themeController.currentThemeColor, + borderRadius: BorderRadius.circular(2), + ), ), - ), const SizedBox(width: 12), Expanded( child: Column( diff --git a/lib/views/profile/guide/sp-guide.dart b/lib/views/profile/guide/sp-guide.dart index a0416d1..e12ea22 100644 --- a/lib/views/profile/guide/sp-guide.dart +++ b/lib/views/profile/guide/sp-guide.dart @@ -38,7 +38,7 @@ class _SpGuidePageState extends State final int _totalPages = 3; - final List _pageTitles = ['欢迎使用', '双击中心区域查看协议', '了解软件功能']; + final List _pageTitles = ['欢迎使用', '双击中心区域可左右滑动查看', '了解软件功能']; @override void initState() { @@ -191,7 +191,7 @@ class _SpGuidePageState extends State _nextPage(); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -221,6 +221,7 @@ class _SpGuidePageState extends State Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return WillPopScope( onWillPop: () async { if (widget.fromSettings) { @@ -230,7 +231,7 @@ class _SpGuidePageState extends State }, child: Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.white, - appBar: _buildAppBar(isDark), + appBar: _buildAppBar(isDark, primaryColor), body: Stack( children: [ PageView( @@ -243,13 +244,13 @@ class _SpGuidePageState extends State }); }, children: [ - _buildWelcomePage(isDark), - _buildPrivacyPage(isDark), - _buildFeaturePage(isDark), + _buildWelcomePage(isDark, primaryColor), + _buildPrivacyPage(isDark, primaryColor), + _buildFeaturePage(isDark, primaryColor), ], ), - _buildPageIndicator(isDark), - _buildBottomNavigation(isDark), + _buildPageIndicator(isDark, primaryColor), + _buildBottomNavigation(isDark, primaryColor), ], ), ), @@ -257,7 +258,7 @@ class _SpGuidePageState extends State }); } - Widget _buildPageIndicator(bool isDark) { + Widget _buildPageIndicator(bool isDark, Color primaryColor) { double alignmentY; switch (_currentPage) { case 0: @@ -318,19 +319,17 @@ class _SpGuidePageState extends State decoration: BoxDecoration( shape: BoxShape.circle, color: isActive - ? AppConstants.primaryColor + ? primaryColor : isCompleted - ? AppConstants.primaryColor.withValues(alpha: 0.5) + ? primaryColor.withAlpha(50) : (isDark ? Colors.grey[600] : Colors.grey[300]), border: isActive - ? Border.all(color: AppConstants.primaryColor, width: 3) + ? Border.all(color: primaryColor, width: 3) : null, boxShadow: isActive ? [ BoxShadow( - color: AppConstants.primaryColor.withValues( - alpha: 0.3, - ), + color: primaryColor.withAlpha(30), blurRadius: 8, spreadRadius: 2, ), @@ -346,21 +345,18 @@ class _SpGuidePageState extends State ); } - PreferredSizeWidget _buildAppBar(bool isDark) { + PreferredSizeWidget _buildAppBar(bool isDark, Color primaryColor) { return AppBar( title: Text( _pageTitles[_currentPage], - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: widget.fromSettings ? IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.pop(context), ) : null, @@ -368,7 +364,7 @@ class _SpGuidePageState extends State ); } - Widget _buildWelcomePage(bool isDark) { + Widget _buildWelcomePage(bool isDark, Color primaryColor) { return Container( padding: const EdgeInsets.all(32), child: Column( @@ -379,10 +375,7 @@ class _SpGuidePageState extends State height: 120, decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - AppConstants.primaryColor.withValues(alpha: 0.1), - AppConstants.primaryColor.withValues(alpha: 0.05), - ], + colors: [primaryColor.withAlpha(10), primaryColor.withAlpha(5)], ), borderRadius: BorderRadius.circular(30), ), @@ -405,7 +398,7 @@ class _SpGuidePageState extends State style: TextStyle( fontSize: 24, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: primaryColor, ), ), const SizedBox(height: 32), @@ -455,17 +448,10 @@ class _SpGuidePageState extends State ), ); }, - icon: Icon( - Icons.security, - size: 18, - color: AppConstants.primaryColor, - ), + icon: Icon(Icons.security, size: 18, color: primaryColor), label: Text( '了解软件权限', - style: TextStyle( - color: AppConstants.primaryColor, - fontSize: 14, - ), + style: TextStyle(color: primaryColor, fontSize: 14), ), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric( @@ -474,9 +460,7 @@ class _SpGuidePageState extends State ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), - side: BorderSide( - color: AppConstants.primaryColor.withValues(alpha: 0.3), - ), + side: BorderSide(color: primaryColor.withAlpha(30)), ), ), ), @@ -536,7 +520,7 @@ class _SpGuidePageState extends State ? Icons.check_circle : Icons.info_outline, color: _showGuideOnStartup - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.grey[400] : Colors.grey[600]), size: 24, ), @@ -556,7 +540,7 @@ class _SpGuidePageState extends State padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: _showGuideOnStartup - ? AppConstants.primaryColor.withValues(alpha: 0.1) + ? _themeController.currentThemeColor.withAlpha(10) : (isDark ? const Color(0xFF2A2A2A) : Colors.grey[50]), borderRadius: BorderRadius.circular(12), ), @@ -567,7 +551,7 @@ class _SpGuidePageState extends State ? Icons.notifications_active : Icons.notifications_off, color: _showGuideOnStartup - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.grey[400] : Colors.grey[500]), size: 40, ), @@ -578,7 +562,7 @@ class _SpGuidePageState extends State fontSize: 16, fontWeight: FontWeight.w600, color: _showGuideOnStartup - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : (isDark ? Colors.white : Colors.grey[700]), ), ), @@ -600,7 +584,7 @@ class _SpGuidePageState extends State child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( @@ -617,7 +601,7 @@ class _SpGuidePageState extends State ); } - Widget _buildPrivacyPage(bool isDark) { + Widget _buildPrivacyPage(bool isDark, Color primaryColor) { _initTabController(); return Stack( children: [ @@ -627,11 +611,11 @@ class _SpGuidePageState extends State color: isDark ? const Color(0xFF2A2A2A) : Colors.white, child: TabBar( controller: _tabController!, - labelColor: AppConstants.primaryColor, + labelColor: primaryColor, unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], - indicatorColor: AppConstants.primaryColor, + indicatorColor: primaryColor, indicatorWeight: 2, tabs: const [ Tab(text: '《隐私政策》'), @@ -713,20 +697,14 @@ class _SpGuidePageState extends State left: 0, top: 0, bottom: 0, - child: Container( - width: 3, - color: AppConstants.primaryColor, - ), + child: Container(width: 3, color: primaryColor), ), if (_isAgreementFocused) Positioned( right: 0, top: 0, bottom: 0, - child: Container( - width: 3, - color: AppConstants.primaryColor, - ), + child: Container(width: 3, color: primaryColor), ), ], ), @@ -779,7 +757,7 @@ class _SpGuidePageState extends State _rejectAgreement(); } }, - activeColor: AppConstants.primaryColor, + activeColor: primaryColor, ), Expanded( child: GestureDetector( @@ -795,7 +773,7 @@ class _SpGuidePageState extends State style: TextStyle( fontSize: 14, color: _agreementAccepted - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[300] : Colors.grey[700]), @@ -814,7 +792,7 @@ class _SpGuidePageState extends State : _rejectAndExit, style: ElevatedButton.styleFrom( backgroundColor: _agreementAccepted - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[700] : Colors.grey[600]), foregroundColor: Colors.white, disabledBackgroundColor: isDark @@ -843,7 +821,7 @@ class _SpGuidePageState extends State ); } - Widget _buildFeaturePage(bool isDark) { + Widget _buildFeaturePage(bool isDark, Color primaryColor) { return Padding( padding: const EdgeInsets.fromLTRB(24, 16, 24, 100), child: Column( @@ -920,11 +898,7 @@ class _SpGuidePageState extends State ), child: Row( children: [ - Icon( - Icons.volunteer_activism, - color: AppConstants.primaryColor, - size: 18, - ), + Icon(Icons.volunteer_activism, color: primaryColor, size: 18), const SizedBox(width: 8), Expanded( child: GestureDetector( @@ -963,7 +937,7 @@ class _SpGuidePageState extends State Switch( value: _userPlanJoined, onChanged: _toggleUserPlan, - activeThumbColor: AppConstants.primaryColor, + activeThumbColor: primaryColor, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ), ], @@ -1044,7 +1018,7 @@ class _SpGuidePageState extends State child: ElevatedButton( onPressed: _finishGuide, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, padding: EdgeInsets.zero, shape: RoundedRectangleBorder( @@ -1127,7 +1101,7 @@ class _SpGuidePageState extends State ); } - Widget _buildBottomNavigation(bool isDark) { + Widget _buildBottomNavigation(bool isDark, Color primaryColor) { return Positioned( bottom: 0, left: 0, @@ -1143,6 +1117,7 @@ class _SpGuidePageState extends State label: '上一页', onPressed: _previousPage, isDark: isDark, + primaryColor: primaryColor, ) : const SizedBox(width: 100), _currentPage < _totalPages - 1 @@ -1153,12 +1128,14 @@ class _SpGuidePageState extends State ? null : _nextPage, isDark: isDark, + primaryColor: primaryColor, ) : _buildNavButton( icon: Icons.check, label: '完成', onPressed: _agreementAccepted ? _finishGuide : null, isDark: isDark, + primaryColor: primaryColor, ), ], ), @@ -1171,17 +1148,18 @@ class _SpGuidePageState extends State required String label, VoidCallback? onPressed, required bool isDark, + required Color primaryColor, }) { return Container( decoration: BoxDecoration( color: onPressed != null - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[700] : Colors.grey[300]), borderRadius: BorderRadius.circular(12), boxShadow: onPressed != null ? [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: primaryColor.withAlpha(30), blurRadius: 8, offset: const Offset(0, 2), ), diff --git a/lib/views/profile/history_page.dart b/lib/views/profile/history_page.dart index 212d8af..dac85c1 100644 --- a/lib/views/profile/history_page.dart +++ b/lib/views/profile/history_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../../constants/app_constants.dart'; +import '../../models/colors/theme_colors.dart'; import '../../services/get/history_controller.dart'; import '../../services/get/theme_controller.dart'; @@ -16,11 +17,12 @@ class HistoryPage extends StatelessWidget { return Obx(() { final isDark = themeController.isDarkMode; + final primaryColor = themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) : const Color(0xFFF2F2F7), - appBar: _buildAppBar(controller, isDark), + appBar: _buildAppBar(controller, isDark, primaryColor), body: Column( children: [ _buildSearchBar(controller, isDark), @@ -32,22 +34,26 @@ class HistoryPage extends StatelessWidget { ? _buildLoadingWidget(isDark) : controller.filteredHistoryList.isEmpty ? _buildEmptyWidget(isDark) - : _buildHistoryList(controller, isDark), + : _buildHistoryList(controller, isDark, primaryColor), ), ), - _buildPagination(controller, isDark), + _buildPagination(controller, isDark, primaryColor), ], ), ); }); } - PreferredSizeWidget _buildAppBar(HistoryController controller, bool isDark) { + PreferredSizeWidget _buildAppBar( + HistoryController controller, + bool isDark, + Color primaryColor, + ) { return AppBar( title: Text( '历史记录', style: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontWeight: FontWeight.w600, fontSize: 17, ), @@ -96,18 +102,12 @@ class HistoryPage extends StatelessWidget { CupertinoButton( padding: const EdgeInsets.symmetric(horizontal: 8), onPressed: controller.showStatsDialog, - child: const Icon( - CupertinoIcons.chart_bar, - color: AppConstants.primaryColor, - ), + child: Icon(CupertinoIcons.chart_bar, color: primaryColor), ), CupertinoButton( padding: const EdgeInsets.symmetric(horizontal: 8), onPressed: controller.exportHistory, - child: const Icon( - CupertinoIcons.share, - color: AppConstants.primaryColor, - ), + child: Icon(CupertinoIcons.share, color: primaryColor), ), ], ); @@ -361,7 +361,11 @@ class HistoryPage extends StatelessWidget { ); } - Widget _buildHistoryList(HistoryController controller, bool isDark) { + Widget _buildHistoryList( + HistoryController controller, + bool isDark, + Color primaryColor, + ) { final currentPageData = controller.getCurrentPageData(); return ListView.separated( @@ -380,6 +384,7 @@ class HistoryPage extends StatelessWidget { item, actualIndex, isDark, + primaryColor, ); }, ); @@ -391,6 +396,7 @@ class HistoryPage extends StatelessWidget { Map item, int actualIndex, bool isDark, + Color primaryColor, ) { return Container( decoration: BoxDecoration( @@ -412,7 +418,7 @@ class HistoryPage extends StatelessWidget { width: 44, height: 44, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(22), ), child: Center( @@ -420,7 +426,7 @@ class HistoryPage extends StatelessWidget { '${actualIndex + 1}', style: TextStyle( fontSize: 16, - color: AppConstants.primaryColor, + color: primaryColor, fontWeight: FontWeight.w600, ), ), @@ -526,7 +532,11 @@ class HistoryPage extends StatelessWidget { ); } - Widget _buildPagination(HistoryController controller, bool isDark) { + Widget _buildPagination( + HistoryController controller, + bool isDark, + Color primaryColor, + ) { return Obx( () => Visibility( visible: controller.totalPages.value > 1, @@ -555,7 +565,7 @@ class HistoryPage extends StatelessWidget { vertical: 8, ), color: controller.currentPage.value > 1 - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[800] : CupertinoColors.systemGrey5), borderRadius: BorderRadius.circular(8), child: Row( @@ -602,7 +612,7 @@ class HistoryPage extends StatelessWidget { ), color: controller.currentPage.value < controller.totalPages.value - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[800] : CupertinoColors.systemGrey5), borderRadius: BorderRadius.circular(8), child: Row( diff --git a/lib/views/profile/level/distinguish.dart b/lib/views/profile/level/distinguish.dart index c9676f4..70c09be 100644 --- a/lib/views/profile/level/distinguish.dart +++ b/lib/views/profile/level/distinguish.dart @@ -1,3 +1,8 @@ +/// 时间: 2026-03-28 +/// 功能: 答题记录页面 +/// 介绍: 显示用户的诗词答题记录列表,包括题目、标签、是否答对等信息 +/// 最新变化: 添加统计数据弹窗功能,支持主题色设置 + import 'dart:convert'; import 'package:flutter/material.dart'; @@ -5,17 +10,12 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; -import '../../../constants/app_constants.dart'; +import '../../../models/colors/app_colors.dart'; import '../../../controllers/shared_preferences_storage_controller.dart'; import '../../../controllers/history_controller.dart'; import '../../../services/network_listener_service.dart'; import '../../../services/get/theme_controller.dart'; -/// 时间: 2026-03-28 -/// 功能: 答题记录页面 -/// 介绍: 显示用户的诗词答题记录列表,包括题目、标签、是否答对等信息 -/// 最新变化: 添加统计数据弹窗功能 - class DistinguishPage extends StatefulWidget { const DistinguishPage({super.key}); @@ -142,239 +142,234 @@ class _DistinguishPageState extends State { } void _showStatisticsDialog() { - final isDark = _themeController.isDarkMode; showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, - builder: (context) => _buildStatisticsSheet(isDark), + builder: (context) => _buildStatisticsSheet(), ); } - Widget _buildStatisticsSheet(bool isDark) { - return Container( - decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, - borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: Container( - width: 40, - height: 4, - decoration: BoxDecoration( - color: isDark ? Colors.grey[600] : Colors.grey[300], - borderRadius: BorderRadius.circular(2), + Widget _buildStatisticsSheet() { + return Obx(() { + final isDark = _themeController.isDarkMode; + return Container( + decoration: BoxDecoration( + color: AppColors.surface, + borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: AppColors.divider, + borderRadius: BorderRadius.circular(2), + ), ), ), - ), - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(20), - borderRadius: BorderRadius.circular(10), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColors.primary.withAlpha(20), + borderRadius: BorderRadius.circular(10), + ), + child: Icon( + Icons.analytics_outlined, + color: AppColors.primary, + size: 24, + ), ), - child: Icon( - Icons.analytics_outlined, - color: AppConstants.primaryColor, - size: 24, - ), - ), - const SizedBox(width: 12), - Text( - '本次答题记录', - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black87, - ), - ), - ], - ), - if (_answerRecords.isNotEmpty) - Container( - decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(15), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: AppConstants.primaryColor.withAlpha(50), - width: 0.5, - ), - ), - child: TextButton.icon( - onPressed: _copyStatisticsContent, - icon: Icon( - Icons.copy, - size: 16, - color: Colors.orange[700], - ), - label: Text( - '添加笔记', + const SizedBox(width: 12), + Text( + '本次答题记录', style: TextStyle( - fontSize: 12, + fontSize: 22, + fontWeight: FontWeight.bold, + color: AppColors.primaryText, + ), + ), + ], + ), + if (_answerRecords.isNotEmpty) + Container( + decoration: BoxDecoration( + color: AppColors.primary.withAlpha(15), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: AppColors.primary.withAlpha(50), + width: 0.5, + ), + ), + child: TextButton.icon( + onPressed: _copyStatisticsContent, + icon: Icon( + Icons.copy, + size: 16, color: Colors.orange[700], ), - ), - style: TextButton.styleFrom( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, + label: Text( + '添加笔记', + style: TextStyle( + fontSize: 12, + color: Colors.orange[700], + ), + ), + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), ), - ), - ], - ), - const SizedBox(height: 24), - Container( - width: double.infinity, - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - AppConstants.primaryColor.withAlpha(10), - isDark ? const Color(0xFF2A2A2A) : Colors.white, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: AppConstants.primaryColor.withAlpha(30), - width: 1, - ), - ), - child: Column( - children: [ - _buildStatRow('已答题', '$_totalQuestions 题', isDark), - _buildStatRow( - '正确', - '$_correctAnswers 题', - isDark, - isGreen: true, - ), - _buildStatRow( - '错误', - '$_wrongAnswers 题', - isDark, - isRed: true, - ), - _buildStatRow( - '正确率', - '${_correctRate.toStringAsFixed(1)}%', - isDark, - isGreen: _correctRate >= 60, - ), - _buildStatRow( - '错误率', - '${_wrongRate.toStringAsFixed(1)}%', - isDark, - isRed: _wrongRate > 40, - ), - _buildStatRow( - '平均用时', - '${_averageTime.toStringAsFixed(1)} 秒', - isDark, - ), - _buildStatRow('提示次数', '$_hintCount 次', isDark), - _buildStatRow('跳过次数', '$_skipCount 次', isDark), - Divider( - height: 24, - color: isDark ? Colors.grey[700] : Colors.grey[300], - ), - _buildStatRow( - '诗词水平', - _poetryLevel, - isDark, - isHighlight: true, - ), ], ), - ), - const SizedBox(height: 24), - SizedBox( - width: double.infinity, - child: Container( + const SizedBox(height: 24), + Container( + width: double.infinity, + padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(200), + AppColors.primary.withAlpha(10), + AppColors.surface, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: AppConstants.primaryColor.withAlpha(80), - blurRadius: 12, - offset: const Offset(0, 4), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: AppColors.primary.withAlpha(30), + width: 1, + ), + ), + child: Column( + children: [ + _buildStatRow('已答题', '$_totalQuestions 题'), + _buildStatRow( + '正确', + '$_correctAnswers 题', + isGreen: true, + ), + _buildStatRow( + '错误', + '$_wrongAnswers 题', + isRed: true, + ), + _buildStatRow( + '正确率', + '${_correctRate.toStringAsFixed(1)}%', + isGreen: _correctRate >= 60, + ), + _buildStatRow( + '错误率', + '${_wrongRate.toStringAsFixed(1)}%', + isRed: _wrongRate > 40, + ), + _buildStatRow( + '平均用时', + '${_averageTime.toStringAsFixed(1)} 秒', + ), + _buildStatRow('提示次数', '$_hintCount 次'), + _buildStatRow('跳过次数', '$_skipCount 次'), + Divider( + height: 24, + color: AppColors.divider, + ), + _buildStatRow( + '诗词水平', + _poetryLevel, + isHighlight: true, ), ], ), - child: ElevatedButton( - onPressed: _copyStatisticsToClipboard, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), + ), + const SizedBox(height: 24), + SizedBox( + width: double.infinity, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColors.primary, + AppColors.primary.withAlpha(200), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, ), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.copy, color: Colors.white, size: 20), - SizedBox(width: 8), - Text( - '复制数据发送给AI评估', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white, - ), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColors.primary.withAlpha(80), + blurRadius: 12, + offset: const Offset(0, 4), ), ], ), + child: ElevatedButton( + onPressed: _copyStatisticsToClipboard, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.copy, color: Colors.white, size: 20), + SizedBox(width: 8), + Text( + '复制数据发送给AI评估', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ], + ), + ), ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), - ), - ); + ); + }); } Widget _buildStatRow( String label, - String value, - bool isDark, { + String value, { bool isGreen = false, bool isRed = false, bool isHighlight = false, }) { - Color valueColor = isDark ? Colors.white : Colors.black87; - if (isGreen) valueColor = Colors.green; - if (isRed) valueColor = Colors.red; - if (isHighlight) valueColor = AppConstants.primaryColor; + Color valueColor = AppColors.primaryText; + if (isGreen) valueColor = AppColors.iosGreen; + if (isRed) valueColor = AppColors.iosRed; + if (isHighlight) valueColor = AppColors.primary; return Padding( padding: const EdgeInsets.symmetric(vertical: 8), @@ -385,7 +380,7 @@ class _DistinguishPageState extends State { label, style: TextStyle( fontSize: 15, - color: isDark ? Colors.grey[400] : Colors.grey[700], + color: AppColors.secondaryText, ), ), Text( @@ -456,16 +451,17 @@ $_poetryLevel final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text('确认清空'), - content: const Text('确定要清空所有答题记录吗?此操作不可恢复。'), + backgroundColor: AppColors.surface, + title: Text('确认清空', style: TextStyle(color: AppColors.primaryText)), + content: Text('确定要清空所有答题记录吗?此操作不可恢复。', style: TextStyle(color: AppColors.secondaryText)), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), - child: const Text('取消'), + child: Text('取消', style: TextStyle(color: AppColors.primary)), ), TextButton( onPressed: () => Navigator.pop(context, true), - child: const Text('确定', style: TextStyle(color: Colors.red)), + child: Text('确定', style: TextStyle(color: AppColors.iosRed)), ), ], ), @@ -511,18 +507,18 @@ $_poetryLevel style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, - color: isDark ? Colors.white : Colors.white, + color: Colors.white, ), ), - backgroundColor: AppConstants.primaryColor, + backgroundColor: AppColors.primary, foregroundColor: Colors.white, elevation: 0, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(180), + AppColors.primary, + AppColors.primary.withAlpha(180), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -544,239 +540,246 @@ $_poetryLevel ], ), body: Container( - color: isDark ? const Color(0xFF1A1A1A) : Colors.grey[50], + color: AppColors.background, child: SafeArea( child: _isLoading ? const Center(child: CircularProgressIndicator()) : _answerRecords.isEmpty - ? _buildEmptyView(isDark) - : _buildRecordList(isDark), + ? _buildEmptyView() + : _buildRecordList(), ), ), ); }); } - Widget _buildEmptyView(bool isDark) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.menu_book_outlined, - size: 80, - color: isDark ? Colors.grey[600] : Colors.grey[300], - ), - const SizedBox(height: 16), - Text( - '暂无答题记录', - style: TextStyle( - fontSize: 18, - color: isDark ? Colors.grey[400] : Colors.grey[500], - fontWeight: FontWeight.w500, + Widget _buildEmptyView() { + return Obx(() { + final isDark = _themeController.isDarkMode; + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.menu_book_outlined, + size: 80, + color: AppColors.tertiaryText, ), - ), - const SizedBox(height: 8), - Text( - '快去答题吧!', - style: TextStyle( - fontSize: 14, - color: isDark ? Colors.grey[500] : Colors.grey[400], + const SizedBox(height: 16), + Text( + '暂无答题记录', + style: TextStyle( + fontSize: 18, + color: AppColors.secondaryText, + fontWeight: FontWeight.w500, + ), ), - ), - ], - ), - ); + const SizedBox(height: 8), + Text( + '快去答题吧!', + style: TextStyle( + fontSize: 14, + color: AppColors.tertiaryText, + ), + ), + ], + ), + ); + }); } - Widget _buildRecordList(bool isDark) { - return ListView.builder( - padding: const EdgeInsets.all(16), - itemCount: _answerRecords.length, - itemBuilder: (context, index) { - final record = _answerRecords[index]; - return _buildRecordCard(record, index, isDark); - }, - ); + Widget _buildRecordList() { + return Obx(() { + final isDark = _themeController.isDarkMode; + return ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: _answerRecords.length, + itemBuilder: (context, index) { + final record = _answerRecords[index]; + return _buildRecordCard(record, index); + }, + ); + }); } - Widget _buildRecordCard(Map record, int index, bool isDark) { + Widget _buildRecordCard(Map record, int index) { final question = record['question'] ?? '未知题目'; final author = record['author'] ?? '未知作者'; final tags = (record['tags'] as List?)?.cast() ?? []; final isCorrect = record['isCorrect'] ?? false; final answerTime = _formatTime(record['answerTime']); - return Container( - margin: const EdgeInsets.only(bottom: 12), - decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: isDark - ? Colors.black.withAlpha(30) - : Colors.black.withAlpha(10), - blurRadius: 8, - offset: const Offset(0, 2), - ), - ], - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 28, - height: 28, - decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(20), - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - '${index + 1}', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, - ), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - question, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: isDark ? Colors.white : Colors.black87, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - const SizedBox(height: 4), - Text( - '—— $author', - style: TextStyle( - fontSize: 12, - color: isDark ? Colors.grey[400] : Colors.grey[600], - fontStyle: FontStyle.italic, - ), - ), - ], - ), - ), - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 4, - ), - decoration: BoxDecoration( - color: isCorrect - ? Colors.green.withAlpha(isDark ? 40 : 20) - : Colors.red.withAlpha(isDark ? 40 : 20), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - isCorrect ? Icons.check_circle : Icons.cancel, - size: 14, - color: isCorrect ? Colors.green : Colors.red, - ), - const SizedBox(width: 4), - Text( - isCorrect ? '答对' : '答错', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: isCorrect ? Colors.green : Colors.red, - ), - ), - ], - ), - ), - ], - ), - const SizedBox(height: 12), - Row( - children: [ - Expanded( - child: tags.isNotEmpty - ? Wrap( - spacing: 6, - runSpacing: 6, - children: tags.map((tag) { - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 3, - ), - decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(15), - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: AppConstants.primaryColor.withAlpha( - 50, - ), - width: 0.5, - ), - ), - child: Text( - tag, - style: TextStyle( - fontSize: 11, - color: AppConstants.primaryColor, - fontWeight: FontWeight.w500, - ), - ), - ); - }).toList(), - ) - : Text( - '暂无标签', - style: TextStyle( - fontSize: 12, - color: isDark ? Colors.grey[500] : Colors.grey[400], - fontStyle: FontStyle.italic, - ), - ), - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.access_time, - size: 12, - color: isDark ? Colors.grey[500] : Colors.grey[400], - ), - const SizedBox(width: 4), - Text( - answerTime, - style: TextStyle( - fontSize: 12, - color: isDark ? Colors.grey[400] : Colors.grey[500], - ), - ), - ], - ), - ], + return Obx(() { + final isDark = _themeController.isDarkMode; + return Container( + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: AppColors.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(isDark ? 30 : 10), + blurRadius: 8, + offset: const Offset(0, 2), ), ], ), - ), - ); + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 28, + height: 28, + decoration: BoxDecoration( + color: AppColors.primary.withAlpha(20), + borderRadius: BorderRadius.circular(8), + ), + child: Center( + child: Text( + '${index + 1}', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: AppColors.primary, + ), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + question, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColors.primaryText, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + '—— $author', + style: TextStyle( + fontSize: 12, + color: AppColors.secondaryText, + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + decoration: BoxDecoration( + color: isCorrect + ? AppColors.iosGreen.withAlpha(20) + : AppColors.iosRed.withAlpha(20), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + isCorrect ? Icons.check_circle : Icons.cancel, + size: 14, + color: isCorrect ? AppColors.iosGreen : AppColors.iosRed, + ), + const SizedBox(width: 4), + Text( + isCorrect ? '答对' : '答错', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: isCorrect ? AppColors.iosGreen : AppColors.iosRed, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: tags.isNotEmpty + ? Wrap( + spacing: 6, + runSpacing: 6, + children: tags.map((tag) { + return Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 3, + ), + decoration: BoxDecoration( + color: AppColors.primary.withAlpha(15), + borderRadius: BorderRadius.circular(6), + border: Border.all( + color: AppColors.primary.withAlpha( + 50, + ), + width: 0.5, + ), + ), + child: Text( + tag, + style: TextStyle( + fontSize: 11, + color: AppColors.primary, + fontWeight: FontWeight.w500, + ), + ), + ); + }).toList(), + ) + : Text( + '暂无标签', + style: TextStyle( + fontSize: 12, + color: AppColors.tertiaryText, + fontStyle: FontStyle.italic, + ), + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.access_time, + size: 12, + color: AppColors.tertiaryText, + ), + const SizedBox(width: 4), + Text( + answerTime, + style: TextStyle( + fontSize: 12, + color: AppColors.secondaryText, + ), + ), + ], + ), + ], + ), + ], + ), + ), + ); + }); } // 写入统计数据到笔记 diff --git a/lib/views/profile/level/flow-anim.dart b/lib/views/profile/level/flow-anim.dart index c1b7a1f..56398f9 100644 --- a/lib/views/profile/level/flow-anim.dart +++ b/lib/views/profile/level/flow-anim.dart @@ -1,8 +1,9 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; +import '../../../services/get/theme_controller.dart'; /// 流动边框装饰器 class FlowingBorderDecoration extends Decoration { @@ -61,7 +62,7 @@ class _FlowingBorderPainter extends BoxPainter { class FlowingBorderContainer extends StatefulWidget { final Widget child; final Duration duration; - final Color color; + final Color? color; final double width; final bool autoStart; @@ -69,7 +70,7 @@ class FlowingBorderContainer extends StatefulWidget { super.key, required this.child, this.duration = const Duration(seconds: 10), - this.color = AppConstants.primaryColor, + this.color, this.width = 4.0, this.autoStart = true, }); @@ -82,6 +83,7 @@ class _FlowingBorderContainerState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; + final ThemeController _themeController = Get.find(); @override void initState() { @@ -105,19 +107,22 @@ class _FlowingBorderContainerState extends State @override Widget build(BuildContext context) { - return AnimatedBuilder( - animation: _animation, - builder: (context, child) { - return Container( - padding: EdgeInsets.all(widget.width), - decoration: FlowingBorderDecoration( - animation: _animation, - color: widget.color, - width: widget.width, - ), - child: widget.child, - ); - }, - ); + return Obx(() { + final color = widget.color ?? _themeController.currentThemeColor; + return AnimatedBuilder( + animation: _animation, + builder: (context, child) { + return Container( + padding: EdgeInsets.all(widget.width), + decoration: FlowingBorderDecoration( + animation: _animation, + color: color, + width: widget.width, + ), + child: widget.child, + ); + }, + ); + }); } } diff --git a/lib/views/profile/level/poetry.dart b/lib/views/profile/level/poetry.dart index 4f374e0..74ff29e 100644 --- a/lib/views/profile/level/poetry.dart +++ b/lib/views/profile/level/poetry.dart @@ -1,10 +1,15 @@ +/// 时间: 2026-03-28 +/// 功能: 诗词答题页面 +/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示 +/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器,支持主题色设置 + import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; +import '../../../models/colors/app_colors.dart'; import '../../../controllers/shared_preferences_storage_controller.dart'; import '../../../services/get/theme_controller.dart'; import '../guide/tongji.dart'; @@ -13,11 +18,6 @@ import 'flow-anim.dart'; import 'distinguish.dart'; import '../settings/offline-data.dart'; -/// 时间: 2026-03-28 -/// 功能: 诗词答题页面 -/// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示 -/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器 - class PoetryLevelPage extends StatefulWidget { const PoetryLevelPage({super.key}); @@ -137,7 +137,7 @@ class _PoetryLevelPageState extends State ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(initResult.message ?? '已加载离线缓存'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: AppColors.primary, duration: const Duration(seconds: 2), ), ); @@ -153,14 +153,15 @@ class _PoetryLevelPageState extends State context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text('提示'), - content: const Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。'), + backgroundColor: AppColors.surface, + title: Text('提示', style: TextStyle(color: AppColors.primaryText)), + content: Text('当前无网络连接且无离线缓存数据,请先下载数据或检查网络设置。', style: TextStyle(color: AppColors.secondaryText)), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, - child: const Text('取消'), + child: Text('取消', style: TextStyle(color: AppColors.primary)), ), TextButton( onPressed: () { @@ -171,7 +172,7 @@ class _PoetryLevelPageState extends State MaterialPageRoute(builder: (_) => const OfflineDataPage()), ); }, - child: const Text('去下载'), + child: Text('去下载', style: TextStyle(color: AppColors.primary)), ), ], ); @@ -464,7 +465,7 @@ class _PoetryLevelPageState extends State return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(20), + color: AppColors.primary.withAlpha(20), borderRadius: BorderRadius.circular(4), ), child: Column( @@ -474,7 +475,7 @@ class _PoetryLevelPageState extends State label, style: TextStyle( fontSize: 10, - color: AppConstants.primaryColor, + color: AppColors.primary, fontWeight: FontWeight.w600, ), ), @@ -482,7 +483,7 @@ class _PoetryLevelPageState extends State value, style: TextStyle( fontSize: 12, - color: Colors.black87, + color: AppColors.primaryText, fontWeight: FontWeight.w500, ), ), @@ -500,150 +501,152 @@ class _PoetryLevelPageState extends State final isWrong = _showFeedback && !_isAnswerCorrect && _selectedAnswer == optionNum; - return AnimatedContainer( - duration: const Duration(milliseconds: 300), - child: Container( - decoration: BoxDecoration( - gradient: isSelected - ? LinearGradient( - colors: isCorrect - ? [Colors.green[400]!, Colors.green[300]!] - : isWrong - ? [Colors.red[400]!, Colors.red[300]!] - : [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(200), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : null, - color: isSelected ? null : Colors.white, - borderRadius: BorderRadius.circular(12), - border: Border.all( - color: isSelected - ? Colors.transparent - : AppConstants.primaryColor.withAlpha(50), - width: 2, - ), - boxShadow: isSelected - ? [ - BoxShadow( - color: - (isCorrect - ? Colors.green - : isWrong - ? Colors.red - : AppConstants.primaryColor) - .withAlpha(80), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ] - : [ - BoxShadow( - color: Colors.black.withAlpha(5), - blurRadius: 8, - offset: const Offset(0, 2), - ), - ], - ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: _isSubmitting || (_showFeedback && _isAnswerCorrect) - ? null - : () { - if (_showFeedback) { - // 重置状态,允许重新选择 - setState(() { - _showFeedback = false; - _selectedAnswer = null; - _feedbackMessage = null; - }); - } - _submitAnswer(optionNum); - }, + return Obx(() { + final isDark = _themeController.isDarkMode; + return AnimatedContainer( + duration: const Duration(milliseconds: 300), + child: Container( + decoration: BoxDecoration( + gradient: isSelected + ? LinearGradient( + colors: isCorrect + ? [AppColors.iosGreen, AppColors.iosGreen.withAlpha(200)] + : isWrong + ? [AppColors.iosRed, AppColors.iosRed.withAlpha(200)] + : [ + AppColors.primary, + AppColors.primary.withAlpha(200), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + color: isSelected ? null : AppColors.surface, borderRadius: BorderRadius.circular(12), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - AnimatedContainer( - duration: const Duration(milliseconds: 300), - width: 32, - height: 32, - decoration: BoxDecoration( - gradient: isSelected - ? LinearGradient( - colors: isCorrect - ? [Colors.white, Colors.white.withAlpha(230)] - : isWrong - ? [Colors.white, Colors.white.withAlpha(230)] - : [Colors.white, Colors.white.withAlpha(230)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : null, - color: isSelected - ? null - : AppConstants.primaryColor.withAlpha(20), - shape: BoxShape.circle, - boxShadow: isSelected - ? [ - BoxShadow( - color: Colors.black.withAlpha(20), - blurRadius: 4, - offset: const Offset(0, 2), - ), - ] - : null, + border: Border.all( + color: isSelected + ? Colors.transparent + : AppColors.primary.withAlpha(50), + width: 2, + ), + boxShadow: isSelected + ? [ + BoxShadow( + color: (isCorrect + ? AppColors.iosGreen + : isWrong + ? AppColors.iosRed + : AppColors.primary) + .withAlpha(80), + blurRadius: 12, + offset: const Offset(0, 4), ), - child: Center( - child: Text( - '$optionNum', - style: TextStyle( - color: isSelected - ? (isCorrect - ? Colors.green + ] + : [ + BoxShadow( + color: Colors.black.withAlpha(isDark ? 10 : 5), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: _isSubmitting || (_showFeedback && _isAnswerCorrect) + ? null + : () { + if (_showFeedback) { + // 重置状态,允许重新选择 + setState(() { + _showFeedback = false; + _selectedAnswer = null; + _feedbackMessage = null; + }); + } + _submitAnswer(optionNum); + }, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 300), + width: 32, + height: 32, + decoration: BoxDecoration( + gradient: isSelected + ? LinearGradient( + colors: isCorrect + ? [Colors.white, Colors.white.withAlpha(230)] : isWrong - ? Colors.red - : AppConstants.primaryColor) - : AppConstants.primaryColor, - fontWeight: FontWeight.bold, - fontSize: 16, + ? [Colors.white, Colors.white.withAlpha(230)] + : [Colors.white, Colors.white.withAlpha(230)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + color: isSelected + ? null + : AppColors.primary.withAlpha(20), + shape: BoxShape.circle, + boxShadow: isSelected + ? [ + BoxShadow( + color: Colors.black.withAlpha(20), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ] + : null, + ), + child: Center( + child: Text( + '$optionNum', + style: TextStyle( + color: isSelected + ? (isCorrect + ? AppColors.iosGreen + : isWrong + ? AppColors.iosRed + : AppColors.primary) + : AppColors.primary, + fontWeight: FontWeight.bold, + fontSize: 16, + ), ), ), ), - ), - const SizedBox(width: 16), - Expanded( - child: Text( - option['content'] ?? option['text'] ?? '', - style: TextStyle( - fontSize: 17, - fontWeight: FontWeight.w500, - color: isSelected ? Colors.white : Colors.black87, + const SizedBox(width: 16), + Expanded( + child: Text( + option['content'] ?? option['text'] ?? '', + style: TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: isSelected ? Colors.white : AppColors.primaryText, + ), ), ), - ), - if (isSelected) - Icon( - isCorrect - ? Icons.check_circle - : isWrong - ? Icons.cancel - : Icons.radio_button_checked, - color: Colors.white, - size: 28, - ), - ], + if (isSelected) + Icon( + isCorrect + ? Icons.check_circle + : isWrong + ? Icons.cancel + : Icons.radio_button_checked, + color: Colors.white, + size: 28, + ), + ], + ), ), ), ), ), - ), - ); + ); + }); } @override @@ -660,15 +663,15 @@ class _PoetryLevelPageState extends State color: Colors.white, ), ), - backgroundColor: AppConstants.primaryColor, + backgroundColor: AppColors.primary, foregroundColor: Colors.white, elevation: 0, flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(180), + AppColors.primary, + AppColors.primary.withAlpha(180), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -707,7 +710,7 @@ class _PoetryLevelPageState extends State ], ), body: Container( - color: isDark ? const Color(0xFF1A1A1A) : Colors.white, + color: AppColors.background, child: SafeArea( child: Padding( padding: const EdgeInsets.only( @@ -737,8 +740,8 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha(200), + AppColors.primary, + AppColors.primary.withAlpha(200), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -746,7 +749,7 @@ class _PoetryLevelPageState extends State borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withAlpha( + color: AppColors.primary.withAlpha( 80, ), blurRadius: 12, @@ -841,7 +844,7 @@ class _PoetryLevelPageState extends State children: [ CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, + AppColors.primary, ), strokeWidth: 3, ), @@ -850,9 +853,7 @@ class _PoetryLevelPageState extends State '加载题目中...', style: TextStyle( fontSize: 16, - color: isDark - ? Colors.grey[400] - : Colors.grey, + color: AppColors.tertiaryText, ), ), ], @@ -870,14 +871,14 @@ class _PoetryLevelPageState extends State padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: isDark - ? Colors.red[900]!.withAlpha(30) - : Colors.red[50], + ? AppColors.iosRed.withAlpha(30) + : AppColors.iosRed.withAlpha(10), shape: BoxShape.circle, ), child: Icon( Icons.error_outline, size: 64, - color: Colors.red[400], + color: AppColors.iosRed, ), ), const SizedBox(height: 24), @@ -886,9 +887,7 @@ class _PoetryLevelPageState extends State textAlign: TextAlign.center, style: TextStyle( fontSize: 16, - color: isDark - ? Colors.red[300] - : Colors.red, + color: AppColors.iosRed, ), ), const SizedBox(height: 32), @@ -896,8 +895,8 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withAlpha( + AppColors.primary, + AppColors.primary.withAlpha( 200, ), ], @@ -905,7 +904,7 @@ class _PoetryLevelPageState extends State borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor + color: AppColors.primary .withAlpha(80), blurRadius: 8, offset: const Offset(0, 4), @@ -967,15 +966,9 @@ class _PoetryLevelPageState extends State BorderRadius.circular( 16, ), - color: isDark - ? const Color( - 0xFF2A2A2A, - ) - : Colors.white, + color: AppColors.surface, ), ), - color: AppConstants - .primaryColor, width: 4, ), ), @@ -986,19 +979,10 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - isDark - ? const Color( - 0xFF2A2A2A, - ) - : Colors.white, - AppConstants - .primaryColor + AppColors.surface, + AppColors.primary .withAlpha(5), - isDark - ? const Color( - 0xFF2A2A2A, - ) - : Colors.white, + AppColors.surface, ], begin: Alignment.topLeft, end: @@ -1023,8 +1007,8 @@ class _PoetryLevelPageState extends State width: 4, height: 20, decoration: BoxDecoration( - color: AppConstants - .primaryColor, + color: AppColors + .primary, borderRadius: BorderRadius.circular( 2, @@ -1041,8 +1025,8 @@ class _PoetryLevelPageState extends State fontWeight: FontWeight .w600, - color: AppConstants - .primaryColor, + color: AppColors + .primary, ), ), ], @@ -1058,9 +1042,7 @@ class _PoetryLevelPageState extends State fontWeight: FontWeight.bold, height: 1.5, - color: isDark - ? Colors.white - : Colors.black87, + color: AppColors.primaryText, ), ), // 标签信息 @@ -1082,8 +1064,8 @@ class _PoetryLevelPageState extends State 12, ), decoration: BoxDecoration( - color: AppConstants - .primaryColor + color: AppColors + .primary .withAlpha( 10, ), @@ -1141,7 +1123,7 @@ class _PoetryLevelPageState extends State width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.surface, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( @@ -1162,8 +1144,8 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - Colors.white, - Colors.grey[50]!, + AppColors.surface, + AppColors.background, ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -1171,7 +1153,7 @@ class _PoetryLevelPageState extends State borderRadius: BorderRadius.circular(12), border: Border.all( - color: AppConstants.primaryColor + color: AppColors.primary .withAlpha(50), width: 1, ), @@ -1195,18 +1177,18 @@ class _PoetryLevelPageState extends State children: [ Icon( Icons.arrow_back, - color: AppConstants - .primaryColor, + color: AppColors + .primary, size: 20, ), const SizedBox(width: 8), - const Text( + Text( '上一题', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, - color: Colors.black87, + color: AppColors.primaryText, ), ), ], @@ -1221,24 +1203,20 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - Colors.white, - Colors.grey[50]!, + AppColors.primary, + AppColors.primary.withAlpha( + 200, + ), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), - border: Border.all( - color: - AppConstants.primaryColor, - width: 2, - ), boxShadow: [ BoxShadow( - color: AppConstants - .primaryColor - .withAlpha(30), + color: AppColors.primary + .withAlpha(80), blurRadius: 8, offset: const Offset(0, 4), ), @@ -1247,8 +1225,7 @@ class _PoetryLevelPageState extends State child: ElevatedButton( onPressed: _getHint, style: ElevatedButton.styleFrom( - backgroundColor: - Colors.transparent, + backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric( @@ -1263,10 +1240,9 @@ class _PoetryLevelPageState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( + const Icon( Icons.lightbulb_outline, - color: AppConstants - .primaryColor, + color: Colors.white, size: 20, ), const SizedBox(width: 8), @@ -1275,8 +1251,8 @@ class _PoetryLevelPageState extends State style: TextStyle( fontSize: 14, fontWeight: - FontWeight.w600, - color: Colors.black87, + FontWeight.w500, + color: Colors.white, ), ), ], @@ -1291,31 +1267,24 @@ class _PoetryLevelPageState extends State decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor - .withAlpha(200), + AppColors.surface, + AppColors.background, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: AppConstants - .primaryColor - .withAlpha(80), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ], + border: Border.all( + color: AppColors.primary + .withAlpha(50), + width: 1, + ), ), - child: ElevatedButton( + child: OutlinedButton( onPressed: _nextQuestion, - style: ElevatedButton.styleFrom( - backgroundColor: - Colors.transparent, - shadowColor: Colors.transparent, + style: OutlinedButton.styleFrom( + side: BorderSide.none, padding: const EdgeInsets.symmetric( vertical: 14, @@ -1329,19 +1298,20 @@ class _PoetryLevelPageState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text( + Text( '下一题', style: TextStyle( fontSize: 14, fontWeight: - FontWeight.w600, - color: Colors.white, + FontWeight.w500, + color: AppColors.primaryText, ), ), const SizedBox(width: 8), Icon( Icons.arrow_forward, - color: Colors.white, + color: AppColors + .primary, size: 20, ), ], @@ -1351,6 +1321,38 @@ class _PoetryLevelPageState extends State ), ], ), + if (_showFeedback && _feedbackMessage != null) + Padding( + padding: const EdgeInsets.only(top: 16), + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: _isAnswerCorrect + ? AppColors.iosGreen + .withAlpha(20) + : AppColors.iosRed + .withAlpha(20), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: _isAnswerCorrect + ? AppColors.iosGreen + : AppColors.iosRed, + width: 1, + ), + ), + child: Text( + _feedbackMessage!, + style: TextStyle( + color: _isAnswerCorrect + ? AppColors.iosGreen + : AppColors.iosRed, + fontSize: 14, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ), + ), ], ), ), @@ -1359,65 +1361,6 @@ class _PoetryLevelPageState extends State ), ], ), - // 反馈信息气泡(不占用布局) - if (_showFeedback && _feedbackMessage != null) - Positioned( - top: 0, - left: 16, - right: 16, - child: AnimatedContainer( - duration: const Duration(milliseconds: 500), - curve: Curves.easeOut, - transform: Matrix4.translationValues(0, 0, 0), - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 12, - ), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: _isAnswerCorrect - ? [Colors.green[400]!, Colors.green[300]!] - : [Colors.orange[400]!, Colors.orange[300]!], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: - (_isAnswerCorrect - ? Colors.green - : Colors.orange) - .withAlpha(80), - blurRadius: 12, - offset: const Offset(0, 4), - ), - ], - ), - child: Row( - children: [ - Icon( - _isAnswerCorrect - ? Icons.celebration - : Icons.lightbulb_outline, - color: Colors.white, - size: 24, - ), - const SizedBox(width: 12), - Expanded( - child: Text( - _feedbackMessage!, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ), - ], - ), - ), - ), ], ), ), diff --git a/lib/views/profile/per_card.dart b/lib/views/profile/per_card.dart index 2ad2a40..c93c42e 100644 --- a/lib/views/profile/per_card.dart +++ b/lib/views/profile/per_card.dart @@ -5,6 +5,8 @@ import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:get/get.dart'; import '../../constants/app_constants.dart'; +import '../../models/colors/theme_colors.dart'; +import '../../services/get/theme_controller.dart'; import '../../services/network_listener_service.dart'; import 'guide/tongji.dart'; @@ -43,6 +45,7 @@ class PersonalCardState extends State { bool _isUserPlanJoined = false; late TextEditingController _nicknameController; int _currentAvatarIndex = 0; + final ThemeController _themeController = Get.find(); // 累计数据 int _totalViews = 0; @@ -284,6 +287,7 @@ class PersonalCardState extends State { @override Widget build(BuildContext context) { + final primaryColor = _themeController.currentThemeColor; return Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( @@ -302,8 +306,8 @@ class PersonalCardState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withOpacity(0.95), - AppConstants.primaryColor.withOpacity(0.85), + primaryColor.withOpacity(0.95), + primaryColor.withOpacity(0.85), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -327,7 +331,7 @@ class PersonalCardState extends State { ), // 内容层 _isExpanded - ? _buildExpandedContent() + ? _buildExpandedContent(primaryColor) : _buildCollapsedContent(), ], ), @@ -453,7 +457,7 @@ class PersonalCardState extends State { ); } - Widget _buildExpandedContent() { + Widget _buildExpandedContent(Color primaryColor) { return Column( children: [ // 头部信息 @@ -520,18 +524,18 @@ class PersonalCardState extends State { child: _isEditingNickname ? TextField( controller: _nicknameController, - style: const TextStyle( - color: AppConstants.primaryColor, + style: TextStyle( + color: primaryColor, fontSize: 18, fontWeight: FontWeight.bold, ), - decoration: const InputDecoration( + decoration: InputDecoration( border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, hintText: '输入昵称', hintStyle: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontSize: 18, fontWeight: FontWeight.bold, ), @@ -682,8 +686,8 @@ class PersonalCardState extends State { Expanded( child: Text( '💡 $_currentTip', - style: const TextStyle( - color: AppConstants.primaryColor, + style: TextStyle( + color: primaryColor, fontSize: 14, fontWeight: FontWeight.w600, height: 1.3, @@ -698,7 +702,7 @@ class PersonalCardState extends State { onChanged: (value) { _toggleOnlineStatus(); }, - activeColor: AppConstants.primaryColor, + activeColor: primaryColor, inactiveTrackColor: Colors.grey.shade300, inactiveThumbColor: Colors.grey, ), diff --git a/lib/views/profile/profile_page.dart b/lib/views/profile/profile_page.dart index 23ca504..2fa5d03 100644 --- a/lib/views/profile/profile_page.dart +++ b/lib/views/profile/profile_page.dart @@ -12,6 +12,7 @@ import 'package:get/get.dart'; import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; +import '../../models/colors/theme_colors.dart'; import 'history_page.dart'; import 'per_card.dart'; import 'settings/app_fun.dart'; @@ -43,13 +44,14 @@ class ProfilePage extends StatelessWidget { return Obx(() { final isDark = themeController.isDarkMode; + final primaryColor = themeController.currentThemeColor; return GetBuilder( builder: (controller) { return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) : const Color(0xFFF5F5F5), - appBar: _buildAppBar(controller, isDark), + appBar: _buildAppBar(controller, isDark, primaryColor), body: GestureDetector( behavior: HitTestBehavior.opaque, onVerticalDragStart: (details) { @@ -77,9 +79,9 @@ class ProfilePage extends StatelessWidget { controller: pageController, onPageChanged: controller.onPageChanged, children: [ - _buildPage1(controller, isDark), - _buildPage2(controller, isDark), - _buildPage3(controller, isDark), + _buildPage1(controller, isDark, primaryColor), + _buildPage2(controller, isDark, primaryColor), + _buildPage3(controller, isDark, primaryColor), ], ), ), @@ -92,21 +94,22 @@ class ProfilePage extends StatelessWidget { }); } - PreferredSizeWidget _buildAppBar(ProfileController controller, bool isDark) { + PreferredSizeWidget _buildAppBar( + ProfileController controller, + bool isDark, + Color primaryColor, + ) { return AppBar( title: Text( '个人', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, actions: [ IconButton( - icon: Icon(Icons.more_horiz, color: AppConstants.primaryColor), + icon: Icon(Icons.more_horiz, color: primaryColor), onPressed: () => _showMoreOptions(controller), ), ], @@ -141,7 +144,11 @@ class ProfilePage extends StatelessWidget { ); } - Widget _buildPage1(ProfileController controller, bool isDark) { + Widget _buildPage1( + ProfileController controller, + bool isDark, + Color primaryColor, + ) { return SingleChildScrollView( // 添加底部内边距,让内容延伸到导航栏下方,实现玻璃效果 padding: EdgeInsets.only( @@ -175,14 +182,14 @@ class ProfilePage extends StatelessWidget { children: [ Icon( Icons.analytics_outlined, - color: AppConstants.primaryColor, + color: primaryColor, size: 20, ), const SizedBox(width: 8), Text( '诗词挑战', style: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -199,16 +206,19 @@ class ProfilePage extends StatelessWidget { '今日答题', '${controller.todayQuestions.value}', isDark, + primaryColor, ), _buildInteractionItem( '本周答题', '${controller.weekQuestions.value}', isDark, + primaryColor, ), _buildInteractionItem( '答对次数', '${controller.correctAnswers.value}', isDark, + primaryColor, ), ], ); @@ -235,7 +245,7 @@ class ProfilePage extends StatelessWidget { Get.to(const PoetryLevelPage()); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -272,16 +282,12 @@ class ProfilePage extends StatelessWidget { children: [ Row( children: [ - Icon( - Icons.person_outline, - color: AppConstants.primaryColor, - size: 20, - ), + Icon(Icons.person_outline, color: primaryColor, size: 20), const SizedBox(width: 8), Text( '统计', style: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -350,7 +356,11 @@ class ProfilePage extends StatelessWidget { ); } - Widget _buildPage2(ProfileController controller, bool isDark) { + Widget _buildPage2( + ProfileController controller, + bool isDark, + Color primaryColor, + ) { return ListView( // 添加底部内边距,让内容延伸到导航栏下方,实现玻璃效果 padding: EdgeInsets.only( @@ -360,80 +370,109 @@ class ProfilePage extends StatelessWidget { bottom: AppConfig.liquidGlassTotalHeight + 16, ), children: [ - _buildSettingsGroup('软件设置', [ - _buildSettingsItem( - '功能设置', - Icons.verified_user, - () => Get.to(const AppFunSettingsPage()), - isDark, - ), - _buildSettingsItem( - '离线使用', - Icons.volunteer_activism, - () => Get.to(const OfflineDataPage()), - isDark, - ), - _buildSettingsItem( - '历史记录', - Icons.history, - () => Get.to(const HistoryPage()), - isDark, - ), - _buildSettingsItem( - '主题风格', - Icons.palette, - () => Get.to(const AppDiyPage()), - isDark, - ), - ], isDark), + _buildSettingsGroup( + '软件设置', + [ + _buildSettingsItem( + '功能设置', + Icons.verified_user, + () => Get.to(const AppFunSettingsPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '离线使用', + Icons.volunteer_activism, + () => Get.to(const OfflineDataPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '历史记录', + Icons.history, + () => Get.to(const HistoryPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '主题风格', + Icons.palette, + () => Get.to(const AppDiyPage()), + isDark, + primaryColor, + ), + ], + isDark, + primaryColor, + ), const SizedBox(height: 16), - _buildSettingsGroup('隐私设置', [ - _buildSettingsItem( - '权限管理', - Icons.block, - () => Get.to(const PermissionPage()), - isDark, - ), - _buildSettingsItem( - '应用数据', - Icons.security, - () => Get.to(const AppDataPage()), - isDark, - ), - _buildSettingsItem( - '软件协议', - Icons.description, - () => Get.to(const PrivacyPage()), - isDark, - ), - ], isDark), + _buildSettingsGroup( + '隐私设置', + [ + _buildSettingsItem( + '权限管理', + Icons.block, + () => Get.to(const PermissionPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '应用数据', + Icons.security, + () => Get.to(const AppDataPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '软件协议', + Icons.description, + () => Get.to(const PrivacyPage()), + isDark, + primaryColor, + ), + ], + isDark, + primaryColor, + ), const SizedBox(height: 16), - _buildSettingsGroup('软件信息', [ - _buildSettingsItem( - '应用信息', - Icons.phone_android, - () => Get.to(const AppInfoPage()), - isDark, - ), - _buildSettingsItem( - '了解我们', - Icons.info, - () => Get.to(const LearnUsPage()), - isDark, - ), - _buildSettingsItem( - '已知bug', - Icons.cleaning_services, - () => showBugListBottomSheet(Get.context!), - isDark, - ), - _buildScreenWakeItem(controller, isDark), - ], isDark), + _buildSettingsGroup( + '软件信息', + [ + _buildSettingsItem( + '应用信息', + Icons.phone_android, + () => Get.to(const AppInfoPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '了解我们', + Icons.info, + () => Get.to(const LearnUsPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '已知bug', + Icons.cleaning_services, + () => showBugListBottomSheet(Get.context!), + isDark, + primaryColor, + ), + _buildScreenWakeItem(controller, isDark, primaryColor), + ], + isDark, + primaryColor, + ), ], ); } - Widget _buildPage3(ProfileController controller, bool isDark) { + Widget _buildPage3( + ProfileController controller, + bool isDark, + Color primaryColor, + ) { return ListView( // 添加底部内边距,让内容延伸到导航栏下方,实现玻璃效果 padding: EdgeInsets.only( @@ -443,38 +482,48 @@ class ProfilePage extends StatelessWidget { bottom: AppConfig.liquidGlassTotalHeight + 16, ), children: [ - _buildSettingsGroup('用户体验计划(限免)', [ - _buildSettingsItem( - '加入体验', - Icons.edit, - () => Get.to(const UserPlanPage()), - isDark, - ), - _buildSettingsItem( - '参与投票', - Icons.how_to_vote, - () => Get.to(const VotePage()), - isDark, - ), - _buildSettingsItem( - '查看全站统计', - Icons.history, - () => Get.to(const EntirePage()), - isDark, - ), - _buildSettingsItem( - '开发计划', - Icons.analytics, - () => controller.showSnackBar('首个上线版本暂无计划,待收集整理用户建议'), - isDark, - ), - _buildSettingsItem( - '去投稿', - Icons.edit_note, - () => Get.to(const ManuscriptPage()), - isDark, - ), - ], isDark), + _buildSettingsGroup( + '用户体验计划(限免)', + [ + _buildSettingsItem( + '加入体验', + Icons.edit, + () => Get.to(const UserPlanPage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '参与投票', + Icons.how_to_vote, + () => Get.to(const VotePage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '查看全站统计', + Icons.history, + () => Get.to(const EntirePage()), + isDark, + primaryColor, + ), + _buildSettingsItem( + '开发计划', + Icons.analytics, + () => controller.showSnackBar('首个上线版本暂无计划,待收集整理用户建议'), + isDark, + primaryColor, + ), + _buildSettingsItem( + '去投稿', + Icons.edit_note, + () => Get.to(const ManuscriptPage()), + isDark, + primaryColor, + ), + ], + isDark, + primaryColor, + ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(20), @@ -496,12 +545,12 @@ class ProfilePage extends StatelessWidget { children: [ Row( children: [ - Icon(Icons.info, color: AppConstants.primaryColor, size: 20), + Icon(Icons.info, color: primaryColor, size: 20), const SizedBox(width: 8), Text( '关于应用', style: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -568,7 +617,12 @@ class ProfilePage extends StatelessWidget { ); } - Widget _buildSettingsGroup(String title, List items, bool isDark) { + Widget _buildSettingsGroup( + String title, + List items, + bool isDark, + Color primaryColor, + ) { return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -590,16 +644,12 @@ class ProfilePage extends StatelessWidget { padding: const EdgeInsets.all(16), child: Row( children: [ - Icon( - Icons.settings_outlined, - color: AppConstants.primaryColor, - size: 20, - ), + Icon(Icons.settings_outlined, color: primaryColor, size: 20), const SizedBox(width: 8), Text( title, style: TextStyle( - color: AppConstants.primaryColor, + color: primaryColor, fontSize: 16, fontWeight: FontWeight.bold, ), @@ -619,9 +669,10 @@ class ProfilePage extends StatelessWidget { IconData icon, VoidCallback onTap, bool isDark, + Color primaryColor, ) { return ListTile( - leading: Icon(icon, color: AppConstants.primaryColor, size: 20), + leading: Icon(icon, color: primaryColor, size: 20), title: Text( title, style: TextStyle( @@ -641,17 +692,17 @@ class ProfilePage extends StatelessWidget { ); } - Widget _buildScreenWakeItem(ProfileController controller, bool isDark) { + Widget _buildScreenWakeItem( + ProfileController controller, + bool isDark, + Color primaryColor, + ) { if (kIsWeb) { return const SizedBox.shrink(); } return ListTile( - leading: Icon( - Icons.screen_lock_rotation, - color: AppConstants.primaryColor, - size: 20, - ), + leading: Icon(Icons.screen_lock_rotation, color: primaryColor, size: 20), title: Text( '屏幕常亮', style: TextStyle( @@ -680,7 +731,7 @@ class ProfilePage extends StatelessWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: primaryColor, ), ), content: Column( @@ -713,7 +764,7 @@ class ProfilePage extends StatelessWidget { Get.back(result: true); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -734,22 +785,27 @@ class ProfilePage extends StatelessWidget { await controller.toggleScreenWake(value); } }, - activeColor: AppConstants.primaryColor, + activeColor: primaryColor, ), ), ); } - Widget _buildInteractionItem(String label, String value, bool isDark) { + Widget _buildInteractionItem( + String label, + String value, + bool isDark, + Color primaryColor, + ) { return Expanded( child: Column( children: [ Text( value, - style: const TextStyle( + style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, + color: primaryColor, ), ), const SizedBox(height: 4), diff --git a/lib/views/profile/settings/app_fun.dart b/lib/views/profile/settings/app_fun.dart index 9907274..31fdc4b 100644 --- a/lib/views/profile/settings/app_fun.dart +++ b/lib/views/profile/settings/app_fun.dart @@ -8,8 +8,7 @@ import '../../../services/get/tap_liquid_glass_controller.dart'; import '../../../utils/audio_manager.dart'; import './widgets.dart'; import '../../home/set/home-load.dart'; -import '../../profile/theme/app-diy.dart'; -import '../../footprint/collect_notes.dart'; +import '../../../controllers/settings/suggestions.dart'; import '../../../controllers/load/locally.dart'; /// 时间: 2026-03-26 @@ -127,6 +126,7 @@ class _AppFunSettingsPageState extends State { // 显示震动提示对话框 void _showVibrationDialog() { + final primaryColor = _themeController.currentThemeColor; showDialog( context: context, builder: (context) => AlertDialog( @@ -146,10 +146,7 @@ class _AppFunSettingsPageState extends State { }); } }, - child: Text( - '确定', - style: TextStyle(color: AppConstants.primaryColor), - ), + child: Text('确定', style: TextStyle(color: primaryColor)), ), ], ), @@ -178,6 +175,7 @@ class _AppFunSettingsPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -185,16 +183,13 @@ class _AppFunSettingsPageState extends State { appBar: AppBar( title: Text( '功能设置', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), ), @@ -310,13 +305,14 @@ class _AppFunSettingsPageState extends State { } Widget _buildSettingsGroup(String title, List items, bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), + color: Colors.black.withAlpha(isDark ? 30 : 5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -332,7 +328,7 @@ class _AppFunSettingsPageState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, + color: primaryColor, ), ), ), @@ -350,14 +346,15 @@ class _AppFunSettingsPageState extends State { ValueChanged onChanged, bool isDark, ) { + final primaryColor = _themeController.currentThemeColor; return ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(icon, color: AppConstants.primaryColor, size: 20), + child: Icon(icon, color: primaryColor, size: 20), ), title: Text( title, @@ -377,20 +374,21 @@ class _AppFunSettingsPageState extends State { trailing: Switch( value: value, onChanged: onChanged, - activeThumbColor: AppConstants.primaryColor, + activeThumbColor: primaryColor, ), ); } Widget _buildFontSliderItem(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(Icons.widgets, color: AppConstants.primaryColor, size: 20), + child: Icon(Icons.widgets, color: primaryColor, size: 20), ), title: Text( '桌面卡片', @@ -419,7 +417,7 @@ class _AppFunSettingsPageState extends State { backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, title: Row( children: [ - Icon(Icons.info_outline, color: AppConstants.primaryColor), + Icon(Icons.info_outline, color: primaryColor), const SizedBox(width: 8), Text( '桌面卡片设置', @@ -491,7 +489,7 @@ class _AppFunSettingsPageState extends State { ); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, ), child: const Text('仍要进入'), @@ -505,6 +503,7 @@ class _AppFunSettingsPageState extends State { } Widget _buildTransparencyLevelItem(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Obx(() { final currentIndex = _glassController.transparencyLevelIndex; return Column( @@ -517,14 +516,10 @@ class _AppFunSettingsPageState extends State { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon( - Icons.opacity, - color: AppConstants.primaryColor, - size: 20, - ), + child: Icon(Icons.opacity, color: primaryColor, size: 20), ), const SizedBox(width: 12), Expanded( @@ -575,6 +570,7 @@ class _AppFunSettingsPageState extends State { bool isSelected, bool isDark, ) { + final primaryColor = _themeController.currentThemeColor; return Expanded( child: GestureDetector( onTap: () => _glassController.setTransparencyLevelByIndex(levelIndex), @@ -582,12 +578,12 @@ class _AppFunSettingsPageState extends State { padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[800] : Colors.grey[200]), borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[700]! : Colors.grey[300]!), width: 1.5, ), @@ -615,14 +611,15 @@ class _AppFunSettingsPageState extends State { VoidCallback onTap, bool isDark, ) { + final primaryColor = _themeController.currentThemeColor; return ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(icon, color: AppConstants.primaryColor, size: 20), + child: Icon(icon, color: primaryColor, size: 20), ), title: Text( title, @@ -648,70 +645,7 @@ class _AppFunSettingsPageState extends State { } Widget _buildVersionInfo(bool isDark) { - return Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), - blurRadius: 10, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - children: [ - Icon( - Icons.settings_suggest, - size: 40, - color: AppConstants.primaryColor, - ), - const SizedBox(height: 12), - Text( - '设置建议', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black, - ), - ), - const SizedBox(height: 4), - Text( - '是否在找,主题风格', - style: TextStyle( - fontSize: 13, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: _buildActionButton( - '主题风格', - '自定义应用主题', - Icons.palette, - Colors.blue, - () => Get.to(() => const AppDiyPage()), - ), - ), - const SizedBox(width: 12), - Expanded( - child: _buildActionButton( - '创建笔记', - '快速创建新笔记', - Icons.note_add, - Colors.green, - () => Get.to(() => const CollectNotesPage()), - ), - ), - ], - ), - ], - ), - ); + return const SuggestionsCard(); } Widget _buildActionButton( diff --git a/lib/views/profile/settings/learn-us.dart b/lib/views/profile/settings/learn-us.dart index 892ea2d..36836ea 100644 --- a/lib/views/profile/settings/learn-us.dart +++ b/lib/views/profile/settings/learn-us.dart @@ -19,6 +19,7 @@ class LearnUsPage extends StatelessWidget { return Obx(() { final isDark = themeController.isDarkMode; + final primaryColor = themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -26,16 +27,13 @@ class LearnUsPage extends StatelessWidget { appBar: AppBar( title: Text( '了解我们', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), ), @@ -62,14 +60,16 @@ class LearnUsPage extends StatelessWidget { } Widget _buildHeaderCard() { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( - gradient: const LinearGradient( + gradient: LinearGradient( colors: [ - Color.fromARGB(255, 143, 73, 228), - Color(0xFF6200EE), - Color(0xFF3700B3), + primaryColor.withAlpha(200), + primaryColor, + primaryColor.withAlpha(150), ], begin: Alignment.topLeft, end: Alignment.bottomRight, @@ -77,7 +77,7 @@ class LearnUsPage extends StatelessWidget { borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: primaryColor.withAlpha(30), blurRadius: 12, offset: const Offset(0, 4), ), @@ -155,6 +155,8 @@ class LearnUsPage extends StatelessWidget { } Widget _buildOfficialSiteCard(bool isDark) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -162,8 +164,8 @@ class LearnUsPage extends StatelessWidget { boxShadow: [ BoxShadow( color: isDark - ? Colors.black.withValues(alpha: 0.3) - : Colors.black.withValues(alpha: 0.05), + ? Colors.black.withAlpha(30) + : Colors.black.withAlpha(5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -179,14 +181,10 @@ class LearnUsPage extends StatelessWidget { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.blue.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon( - Icons.language, - color: Colors.blue[700], - size: 20, - ), + child: Icon(Icons.language, color: primaryColor, size: 20), ), const SizedBox(width: 12), Text( @@ -222,25 +220,18 @@ class LearnUsPage extends StatelessWidget { borderRadius: BorderRadius.circular(8), border: Border.all( color: isDark - ? Colors.grey[700]!.withValues(alpha: 0.2) - : Colors.grey.withValues(alpha: 0.2), + ? Colors.grey[700]!.withAlpha(20) + : Colors.grey.withAlpha(20), ), ), child: Row( children: [ - Icon( - Icons.link, - size: 16, - color: AppConstants.primaryColor, - ), + Icon(Icons.link, size: 16, color: primaryColor), const SizedBox(width: 8), Expanded( child: Text( 'https://poe.vogov.cn/app.html', - style: TextStyle( - fontSize: 14, - color: AppConstants.primaryColor, - ), + style: TextStyle(fontSize: 14, color: primaryColor), ), ), ], @@ -255,6 +246,8 @@ class LearnUsPage extends StatelessWidget { } Widget _buildQQGroupCard(BuildContext context, bool isDark) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -262,8 +255,8 @@ class LearnUsPage extends StatelessWidget { boxShadow: [ BoxShadow( color: isDark - ? Colors.black.withValues(alpha: 0.3) - : Colors.black.withValues(alpha: 0.05), + ? Colors.black.withAlpha(30) + : Colors.black.withAlpha(5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -279,10 +272,10 @@ class LearnUsPage extends StatelessWidget { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.blue.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(Icons.group, color: Colors.blue[700], size: 20), + child: Icon(Icons.group, color: primaryColor, size: 20), ), const SizedBox(width: 12), Text( @@ -319,25 +312,19 @@ class LearnUsPage extends StatelessWidget { decoration: BoxDecoration( color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[50], borderRadius: BorderRadius.circular(8), - border: Border.all( - color: AppConstants.primaryColor.withValues(alpha: 0.3), - ), + border: Border.all(color: primaryColor.withAlpha(30)), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.content_copy, - size: 16, - color: AppConstants.primaryColor, - ), + Icon(Icons.content_copy, size: 16, color: primaryColor), const SizedBox(width: 8), Text( '271129018', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, - color: AppConstants.primaryColor, + color: primaryColor, ), ), ], @@ -361,6 +348,8 @@ class LearnUsPage extends StatelessWidget { } void _copyQQGroupNumber(BuildContext context) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; Clipboard.setData(const ClipboardData(text: '271129018')); ScaffoldMessenger.of(context).showSnackBar( @@ -372,7 +361,7 @@ class LearnUsPage extends StatelessWidget { Text('QQ群号已复制到剪贴板'), ], ), - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), duration: const Duration(seconds: 2), @@ -381,6 +370,8 @@ class LearnUsPage extends StatelessWidget { } Widget _buildDeveloperCard(BuildContext context, bool isDark) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -388,8 +379,8 @@ class LearnUsPage extends StatelessWidget { boxShadow: [ BoxShadow( color: isDark - ? Colors.black.withValues(alpha: 0.3) - : Colors.black.withValues(alpha: 0.05), + ? Colors.black.withAlpha(30) + : Colors.black.withAlpha(5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -405,14 +396,10 @@ class LearnUsPage extends StatelessWidget { Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Colors.green.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon( - Icons.business, - color: Colors.green[700], - size: 20, - ), + child: Icon(Icons.business, color: primaryColor, size: 20), ), const SizedBox(width: 12), Text( @@ -437,8 +424,8 @@ class LearnUsPage extends StatelessWidget { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - AppConstants.primaryColor.withValues(alpha: 0.1), - AppConstants.primaryColor.withValues(alpha: 0.05), + primaryColor.withAlpha(10), + primaryColor.withAlpha(5), ], ), borderRadius: BorderRadius.circular(12), @@ -666,7 +653,7 @@ class LearnUsPage extends StatelessWidget { '尽毕生所学,取天下之诗集,只为逗她一笑', isDark, ), - _buildTeamMember('🎨', 'UI/UX/Testing', 'Ayk', '....', isDark), + _buildTeamMember('🎨', 'UI/UX/Testing', 'Ayk', '姥头乐也疯狂', isDark), _buildTeamMember('⚙️', '后端', '伯乐不相马', '真的吗,还是做不到吗?', isDark), _buildTeamMember('🔧', '技术支持', '闲言app', '闲言app原班人马打造', isDark), ], @@ -681,6 +668,8 @@ class LearnUsPage extends StatelessWidget { String signature, bool isDark, ) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( @@ -718,15 +707,12 @@ class LearnUsPage extends StatelessWidget { vertical: 2, ), decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(10), ), child: Text( name, - style: TextStyle( - fontSize: 11, - color: AppConstants.primaryColor, - ), + style: TextStyle(fontSize: 11, color: primaryColor), ), ), ], @@ -814,7 +800,7 @@ class LearnUsPage extends StatelessWidget { children: [ Expanded( child: Text( - '滇ICP备2022000863号-13', + '滇ICP备2022000863号-15A', style: TextStyle( fontSize: 14, color: isDark ? Colors.grey[300] : Colors.grey[700], diff --git a/lib/views/profile/settings/offline-data.dart b/lib/views/profile/settings/offline-data.dart index 7bb1136..d738700 100644 --- a/lib/views/profile/settings/offline-data.dart +++ b/lib/views/profile/settings/offline-data.dart @@ -153,7 +153,7 @@ class _OfflineDataPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('已保存 $_downloadedCount 条数据'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -265,7 +265,7 @@ class _OfflineDataPageState extends State { content: Text( '成功缓存 ${_selectedType == DownloadType.poetry ? '诗词' : '答题'} $_cachedCount 条数据', ), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -371,7 +371,7 @@ class _OfflineDataPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('已清空$typeName离线数据'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -401,9 +401,9 @@ class _OfflineDataPageState extends State { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('已清空所有离线数据'), - backgroundColor: AppConstants.primaryColor, + SnackBar( + content: const Text('已清空所有离线数据'), + backgroundColor: _themeController.currentThemeColor, ), ); } @@ -515,6 +515,7 @@ class _OfflineDataPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -522,24 +523,18 @@ class _OfflineDataPageState extends State { appBar: AppBar( title: Text( '离线使用', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), actions: [ IconButton( - icon: Icon( - Icons.cloud_outlined, - color: AppConstants.primaryColor, - ), + icon: Icon(Icons.cloud_outlined, color: primaryColor), onPressed: _showServerInfo, tooltip: '服务器信息', ), @@ -555,7 +550,7 @@ class _OfflineDataPageState extends State { borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), + color: Colors.black.withAlpha(isDark ? 30 : 5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -565,11 +560,7 @@ class _OfflineDataPageState extends State { children: [ Row( children: [ - Icon( - Icons.download_done, - color: AppConstants.primaryColor, - size: 24, - ), + Icon(Icons.download_done, color: primaryColor, size: 24), const SizedBox(width: 12), Text( '缓存状态', @@ -615,7 +606,7 @@ class _OfflineDataPageState extends State { borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), + color: Colors.black.withAlpha(isDark ? 30 : 5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -626,11 +617,7 @@ class _OfflineDataPageState extends State { children: [ Row( children: [ - Icon( - Icons.category, - color: AppConstants.primaryColor, - size: 20, - ), + Icon(Icons.category, color: primaryColor, size: 20), const SizedBox(width: 8), Text( '下载类型', @@ -663,7 +650,7 @@ class _OfflineDataPageState extends State { borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: Colors.black.withValues(alpha: isDark ? 0.3 : 0.05), + color: Colors.black.withAlpha(isDark ? 30 : 5), blurRadius: 10, offset: const Offset(0, 2), ), @@ -674,11 +661,7 @@ class _OfflineDataPageState extends State { children: [ Row( children: [ - Icon( - Icons.settings, - color: AppConstants.primaryColor, - size: 20, - ), + Icon(Icons.settings, color: primaryColor, size: 20), const SizedBox(width: 8), Text( '下载数量', @@ -720,9 +703,7 @@ class _OfflineDataPageState extends State { ? (_isCancelling ? null : _cancelDownload) : _downloadOfflineData, style: ElevatedButton.styleFrom( - backgroundColor: _isCancelling - ? Colors.red - : AppConstants.primaryColor, + backgroundColor: _isCancelling ? Colors.red : primaryColor, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), @@ -804,9 +785,7 @@ class _OfflineDataPageState extends State { backgroundColor: isDark ? Colors.grey[700] : Colors.grey[200], - valueColor: AlwaysStoppedAnimation( - AppConstants.primaryColor, - ), + valueColor: AlwaysStoppedAnimation(primaryColor), borderRadius: BorderRadius.circular(10), ), const SizedBox(height: 8), @@ -942,6 +921,7 @@ class _OfflineDataPageState extends State { Widget _buildTypeOption(DownloadType type, String label, bool isDark) { final isSelected = _selectedType == type; + final primaryColor = _themeController.currentThemeColor; return GestureDetector( onTap: () { setState(() { @@ -954,12 +934,12 @@ class _OfflineDataPageState extends State { padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), decoration: BoxDecoration( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[800] : Colors.grey[100]), borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[700]! : Colors.grey[300]!), ), ), @@ -979,6 +959,7 @@ class _OfflineDataPageState extends State { Widget _buildCountOption(int count, bool isDark) { final isSelected = _selectedCount == count; + final primaryColor = _themeController.currentThemeColor; return Stack( children: [ GestureDetector( @@ -991,12 +972,12 @@ class _OfflineDataPageState extends State { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[800] : Colors.grey[100]), borderRadius: BorderRadius.circular(8), border: Border.all( color: isSelected - ? AppConstants.primaryColor + ? primaryColor : (isDark ? Colors.grey[700]! : Colors.grey[300]!), ), ), diff --git a/lib/views/profile/settings/privacy.dart b/lib/views/profile/settings/privacy.dart index 192115e..cfd9688 100644 --- a/lib/views/profile/settings/privacy.dart +++ b/lib/views/profile/settings/privacy.dart @@ -52,6 +52,7 @@ class PrivacyPolicyContent extends StatelessWidget { _buildPermissionItem('网络权限', '用于获取诗词内容和更新应用信息'), _buildPermissionItem('震动权限', '用于在执行操作时提供反馈提示'), _buildPermissionItem('分享能力', '调用系统分享功能,分享您的笔记、收藏等本地数据'), + _buildPermissionItem('设备标识', '获取唯一标识设备的设备ID,确保用户数据安全。'), const SizedBox(height: 24), _buildSectionTitle('3. 管理您的个人信息'), const SizedBox(height: 16), @@ -125,6 +126,8 @@ class PrivacyPolicyContent extends StatelessWidget { } Widget _buildBulletPoint(String text) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( @@ -135,7 +138,7 @@ class PrivacyPolicyContent extends StatelessWidget { height: 6, margin: const EdgeInsets.only(top: 6, left: 8, right: 12), decoration: BoxDecoration( - color: AppConstants.primaryColor, + color: primaryColor, shape: BoxShape.circle, ), ), @@ -487,6 +490,7 @@ class _PrivacyPageState extends State Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -494,19 +498,16 @@ class _PrivacyPageState extends State appBar: AppBar( title: Text( '隐私与协议', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, bottom: TabBar( controller: _tabController, - labelColor: AppConstants.primaryColor, + labelColor: primaryColor, unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], - indicatorColor: AppConstants.primaryColor, + indicatorColor: primaryColor, indicatorWeight: 2, tabs: const [ Tab(text: '隐私政策'), @@ -514,12 +515,12 @@ class _PrivacyPageState extends State ], ), leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), actions: [ IconButton( - icon: Icon(Icons.link, color: AppConstants.primaryColor), + icon: Icon(Icons.link, color: primaryColor), onPressed: () => _showOnlineLinkDialog(isDark), tooltip: '在线版本', ), @@ -537,6 +538,7 @@ class _PrivacyPageState extends State } void _showOnlineLinkDialog(bool isDark) { + final primaryColor = _themeController.currentThemeColor; showDialog( context: context, builder: (context) => AlertDialog( @@ -544,7 +546,7 @@ class _PrivacyPageState extends State shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.public, color: AppConstants.primaryColor), + Icon(Icons.public, color: primaryColor), const SizedBox(width: 8), Text( '在线版本', @@ -577,7 +579,7 @@ class _PrivacyPageState extends State 'https://poe.vogov.cn/privacy.html', style: TextStyle( fontSize: 13, - color: AppConstants.primaryColor, + color: primaryColor, decoration: TextDecoration.underline, ), ), @@ -609,7 +611,7 @@ class _PrivacyPageState extends State ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('链接已复制到剪贴板'), - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -620,7 +622,7 @@ class _PrivacyPageState extends State icon: const Icon(Icons.copy, size: 18), label: const Text('复制链接'), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), diff --git a/lib/views/profile/settings/user-plan.dart b/lib/views/profile/settings/user-plan.dart index 27e2b1d..2656b7e 100644 --- a/lib/views/profile/settings/user-plan.dart +++ b/lib/views/profile/settings/user-plan.dart @@ -46,20 +46,23 @@ class _UserPlanPageState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(value ? '已加入用户体验计划' : '已退出用户体验计划'), - backgroundColor: value ? AppConstants.primaryColor : Colors.grey[600], + backgroundColor: value + ? _themeController.currentThemeColor + : Colors.grey[600], ), ); } } void _showJoinDialog() { + final primaryColor = _themeController.currentThemeColor; showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.volunteer_activism, color: AppConstants.primaryColor), + Icon(Icons.volunteer_activism, color: primaryColor), const SizedBox(width: 8), const Text('加入用户体验计划'), ], @@ -96,7 +99,7 @@ class _UserPlanPageState extends State { _toggleUserPlan(true); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), @@ -110,13 +113,14 @@ class _UserPlanPageState extends State { } void _showInfoPopup(BuildContext context) { + final primaryColor = _themeController.currentThemeColor; showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), title: Row( children: [ - Icon(Icons.info, color: AppConstants.primaryColor), + Icon(Icons.info, color: primaryColor), const SizedBox(width: 8), const Text('温馨提示'), ], @@ -192,6 +196,7 @@ class _UserPlanPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -199,16 +204,13 @@ class _UserPlanPageState extends State { appBar: AppBar( title: Text( '用户体验计划', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), ), @@ -235,21 +237,19 @@ class _UserPlanPageState extends State { } Widget _buildStatusCard(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( - colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withBlue(180), - ], + colors: [primaryColor, primaryColor.withBlue(180)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: primaryColor.withAlpha(30), blurRadius: 12, offset: const Offset(0, 4), ), @@ -531,6 +531,7 @@ class _UserPlanPageState extends State { itemCount: benefits.length, itemBuilder: (context, index) { final benefit = benefits[index]; + final primaryColor = _themeController.currentThemeColor; return Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( @@ -539,7 +540,7 @@ class _UserPlanPageState extends State { border: Border.all( color: isDark ? Colors.grey[700]! - : Colors.grey.withValues(alpha: 0.2), + : Colors.grey.withAlpha(20), ), ), child: Row( @@ -547,7 +548,7 @@ class _UserPlanPageState extends State { Icon( benefit['icon'] as IconData, size: 18, - color: AppConstants.primaryColor, + color: primaryColor, ), const SizedBox(width: 8), Expanded( @@ -660,6 +661,7 @@ class _UserPlanPageState extends State { } Widget _buildActionButton(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Container( width: double.infinity, height: 50, @@ -667,10 +669,7 @@ class _UserPlanPageState extends State { gradient: _isJoined ? null : LinearGradient( - colors: [ - AppConstants.primaryColor, - AppConstants.primaryColor.withBlue(180), - ], + colors: [primaryColor, primaryColor.withBlue(180)], ), color: _isJoined ? (isDark ? Colors.grey[700] : Colors.grey[300]) @@ -680,7 +679,7 @@ class _UserPlanPageState extends State { ? null : [ BoxShadow( - color: AppConstants.primaryColor.withValues(alpha: 0.3), + color: primaryColor.withAlpha(30), blurRadius: 8, offset: const Offset(0, 4), ), diff --git a/lib/views/profile/settings/widgets.dart b/lib/views/profile/settings/widgets.dart index 82b9100..94f06d6 100644 --- a/lib/views/profile/settings/widgets.dart +++ b/lib/views/profile/settings/widgets.dart @@ -27,6 +27,7 @@ class _WidgetsPageState extends State { Widget build(BuildContext context) { return Obx(() { final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; return Scaffold( backgroundColor: isDark ? const Color(0xFF1A1A1A) @@ -34,16 +35,13 @@ class _WidgetsPageState extends State { appBar: AppBar( title: Text( '桌面卡片设置', - style: TextStyle( - color: AppConstants.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), ), backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, centerTitle: true, leading: IconButton( - icon: Icon(Icons.arrow_back, color: AppConstants.primaryColor), + icon: Icon(Icons.arrow_back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), ), @@ -100,6 +98,7 @@ class _WidgetsPageState extends State { } Widget _buildSettingsGroup(String title, List items, bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -122,7 +121,7 @@ class _WidgetsPageState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, - color: AppConstants.primaryColor, + color: primaryColor, ), ), ), @@ -140,14 +139,15 @@ class _WidgetsPageState extends State { ValueChanged onChanged, bool isDark, ) { + final primaryColor = _themeController.currentThemeColor; return ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(10), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(icon, color: AppConstants.primaryColor, size: 20), + child: Icon(icon, color: primaryColor, size: 20), ), title: Text( title, @@ -167,20 +167,21 @@ class _WidgetsPageState extends State { trailing: Switch( value: value, onChanged: onChanged, - activeThumbColor: AppConstants.primaryColor, + activeThumbColor: primaryColor, ), ); } Widget _buildIntervalItem(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return ListTile( leading: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(10), + color: primaryColor.withAlpha(10), borderRadius: BorderRadius.circular(8), ), - child: Icon(Icons.refresh, color: AppConstants.primaryColor, size: 20), + child: Icon(Icons.refresh, color: primaryColor, size: 20), ), title: Text( '更新间隔', @@ -213,7 +214,7 @@ class _WidgetsPageState extends State { visualDensity: VisualDensity.compact, backgroundColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { - return AppConstants.primaryColor; + return primaryColor; } return isDark ? Colors.grey[700] : Colors.grey[200]; }), @@ -230,11 +231,12 @@ class _WidgetsPageState extends State { } Widget _buildPreviewCard(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: AppConstants.primaryColor.withAlpha(90), + color: primaryColor.withAlpha(90), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( @@ -303,19 +305,17 @@ class _WidgetsPageState extends State { } Widget _buildActionButton(bool isDark) { + final primaryColor = _themeController.currentThemeColor; return SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('桌面卡片设置已保存'), - backgroundColor: AppConstants.primaryColor, - ), + SnackBar(content: Text('桌面卡片设置已保存'), backgroundColor: primaryColor), ); }, style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), diff --git a/lib/views/profile/theme/app-diy.dart b/lib/views/profile/theme/app-diy.dart index eb923c8..8fae115 100644 --- a/lib/views/profile/theme/app-diy.dart +++ b/lib/views/profile/theme/app-diy.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../constants/app_constants.dart'; +import '../../../models/colors/theme_colors.dart'; import '../../../services/get/theme_controller.dart'; /// 时间: 2026-03-27 @@ -29,23 +30,10 @@ class _AppDiyPageState extends State { late Timer _scrollTimer; // 主题颜色选项 - final List _themeColors = [ - AppConstants.primaryColor, // 默认紫色 - Colors.blue, // 蓝色 - Colors.green, // 绿色 - Colors.orange, // 橙色 - Colors.red, // 红色 - Colors.teal, // 青色 - ]; + final List _themeColors = ThemeColors.themeColors; // 强调色选项 - final List _accentColors = [ - AppConstants.primaryColor, // 默认紫色 - Colors.yellow, // 黄色 - Colors.pink, // 粉色 - Colors.cyan, // 青色 - Colors.purple, // 深紫色 - ]; + final List _accentColors = ThemeColors.accentColors; // 字体大小选项 final List _fontSizes = ['小', '中', '大']; @@ -72,31 +60,68 @@ class _AppDiyPageState extends State { context: context, barrierDismissible: false, builder: (BuildContext context) { + final primaryColor = _themeController.currentThemeColor; + final isDark = _themeController.isDarkMode; + return AlertDialog( + backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), title: Row( children: [ - Icon(Icons.construction, color: AppConstants.primaryColor), + Icon(Icons.construction, color: primaryColor), const SizedBox(width: 8), - const Text('开发中'), + Text( + '开发中', + style: TextStyle(color: isDark ? Colors.white : Colors.black), + ), ], ), - content: const Column( + content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '个性化设置开发中', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: isDark ? Colors.white : Colors.black, + ), ), - SizedBox(height: 12), - Text('• 当前仅支持设置深色模式'), - Text('• 其他设置仅当前页面生效'), - Text('• 后续版本将陆续支持'), - Text('• 可提前预览主题风格设置'), - SizedBox(height: 12), + const SizedBox(height: 12), + Text( + '• ✅ 深色模式(已支持)', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.black87, + ), + ), + Text( + '• ✅ 主题色彩(已支持)', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.black87, + ), + ), + Text( + '• ⏳ 其他设置仅当前页面生效', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.black87, + ), + ), + Text( + '• ⏳ 后续版本将陆续支持', + style: TextStyle( + color: isDark ? Colors.grey[300] : Colors.black87, + ), + ), + const SizedBox(height: 12), Text( '感谢您的耐心等待!', - style: TextStyle(color: Colors.grey, fontSize: 12), + style: TextStyle( + color: isDark ? Colors.grey[400] : Colors.grey[600], + fontSize: 12, + ), ), ], ), @@ -104,8 +129,11 @@ class _AppDiyPageState extends State { ElevatedButton( onPressed: () => Navigator.of(context).pop(), style: ElevatedButton.styleFrom( - backgroundColor: AppConstants.primaryColor, + backgroundColor: primaryColor, foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), ), child: const Text('我知道了'), ), @@ -184,9 +212,11 @@ class _AppDiyPageState extends State { return Scaffold( appBar: AppBar( - title: const Text('个性化'), + title: Text( + '个性化', + style: TextStyle(color: _themeController.currentThemeColor), + ), backgroundColor: isDark ? Colors.grey[900] : Colors.white, - foregroundColor: isDark ? Colors.white : AppConstants.primaryColor, elevation: 0, ), backgroundColor: isDark ? Colors.grey[900] : Colors.grey[50], @@ -363,7 +393,7 @@ class _AppDiyPageState extends State { ], ), child: ListTile( - leading: Icon(icon, color: _themeColors[themeColorIdx]), + leading: Icon(icon, color: _themeController.currentThemeColor), title: Text( title, style: TextStyle(color: isDark ? Colors.white : Colors.black87), @@ -371,7 +401,7 @@ class _AppDiyPageState extends State { trailing: Switch( value: value, onChanged: onChanged, - activeThumbColor: _themeColors[themeColorIdx], + activeThumbColor: _themeController.currentThemeColor, ), ), ); @@ -400,7 +430,7 @@ class _AppDiyPageState extends State { ], ), child: ListTile( - leading: Icon(icon, color: _themeColors[themeColorIdx]), + leading: Icon(icon, color: _themeController.currentThemeColor), title: Text( title, style: TextStyle(color: isDark ? Colors.white : Colors.black87), @@ -428,6 +458,22 @@ class _AppDiyPageState extends State { ); } + // 颜色名称映射 + final Map _colorNames = { + AppConstants.primaryColor: '紫韵', + Colors.blue: '天蓝', + Colors.green: '翠绿', + Colors.orange: '橙光', + Colors.red: '朱红', + Colors.teal: '青碧', + const Color(0xFF8B4513): '书褐', + Colors.yellow: '明黄', + Colors.pink: '桃粉', + Colors.cyan: '湖青', + Colors.purple: '罗兰', + const Color(0xFFF5F5F0): '宣纸', + }; + Widget _buildColorSelector( String title, List colors, @@ -448,34 +494,103 @@ class _AppDiyPageState extends State { ), ], ), - child: ListTile( - title: Text( - title, - style: TextStyle(color: isDark ? Colors.white : Colors.black87), - ), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: colors.asMap().entries.map((entry) { - return GestureDetector( - onTap: () => onChanged(entry.key), - child: Container( - width: 32, - height: 32, - margin: const EdgeInsets.symmetric(horizontal: 4), - decoration: BoxDecoration( - color: entry.value, - shape: BoxShape.circle, - border: entry.key == selectedIndex - ? Border.all( - color: isDark ? Colors.white : Colors.black, - width: 2, - ) - : null, - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), + child: Text( + title, + style: TextStyle( + color: isDark ? Colors.white : Colors.black87, + fontSize: 16, + fontWeight: FontWeight.w500, ), - ); - }).toList(), - ), + ), + ), + SizedBox( + height: 80, + child: ListView.builder( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 12), + itemCount: colors.length, + itemBuilder: (context, index) { + final color = colors[index]; + final colorName = _colorNames[color] ?? '色彩${index + 1}'; + final isSelected = index == selectedIndex; + + return GestureDetector( + onTap: () => onChanged(index), + child: Container( + width: 60, + margin: const EdgeInsets.symmetric( + horizontal: 4, + vertical: 8, + ), + child: Column( + children: [ + Container( + width: 44, + height: 44, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + border: isSelected + ? Border.all( + color: isDark ? Colors.white : Colors.black, + width: 3, + ) + : Border.all( + color: isDark + ? Colors.grey[600]! + : Colors.grey[300]!, + width: 1, + ), + boxShadow: isSelected + ? [ + BoxShadow( + color: color.withAlpha(128), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ] + : null, + ), + child: isSelected + ? Icon( + Icons.check, + color: color.computeLuminance() > 0.5 + ? Colors.black + : Colors.white, + size: 24, + ) + : null, + ), + const SizedBox(height: 4), + Text( + colorName, + style: TextStyle( + fontSize: 11, + color: isSelected + ? (isDark ? Colors.white : Colors.black) + : (isDark + ? Colors.grey[400] + : Colors.grey[600]), + fontWeight: isSelected + ? FontWeight.w600 + : FontWeight.normal, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + }, + ), + ), + ], ), ); } @@ -543,7 +658,6 @@ class _AppDiyPageState extends State { Icons.style, isMd: true, isDark: isDark, - themeColorIdx: themeColorIdx, ), const SizedBox(width: 8), _buildStyleChip( @@ -551,28 +665,24 @@ class _AppDiyPageState extends State { Icons.auto_awesome, isMd: true, isDark: isDark, - themeColorIdx: themeColorIdx, ), const SizedBox(width: 8), _buildStyleChip( '透明毛玻璃', Icons.blur_on, isDark: isDark, - themeColorIdx: themeColorIdx, ), const SizedBox(width: 8), _buildStyleChip( '沉浸式渐变色', Icons.color_lens, isDark: isDark, - themeColorIdx: themeColorIdx, ), const SizedBox(width: 8), _buildStyleChip( '动态光感效果', Icons.lightbulb_outline, isDark: isDark, - themeColorIdx: themeColorIdx, ), const SizedBox(width: 8), ], @@ -586,8 +696,8 @@ class _AppDiyPageState extends State { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - _themeColors[themeColorIdx].withAlpha(10), - _themeColors[themeColorIdx].withAlpha(5), + _themeController.currentThemeColor.withAlpha(10), + _themeController.currentThemeColor.withAlpha(5), ], ), borderRadius: BorderRadius.circular(8), @@ -597,7 +707,7 @@ class _AppDiyPageState extends State { Icon( Icons.lightbulb_outline, size: 16, - color: _themeColors[themeColorIdx], + color: _themeController.currentThemeColor, ), const SizedBox(width: 8), Expanded( @@ -625,10 +735,9 @@ class _AppDiyPageState extends State { IconData icon, { bool isMd = false, required bool isDark, - required int themeColorIdx, }) { final color = isMd - ? _themeColors[themeColorIdx] + ? _themeController.currentThemeColor : isDark ? Colors.blue[400]! : Colors.blue[600]!; diff --git a/lib/views/responsive_home_page.dart b/lib/views/responsive_home_page.dart index f5c7877..f20f811 100644 --- a/lib/views/responsive_home_page.dart +++ b/lib/views/responsive_home_page.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../utils/responsive_layout.dart'; import '../widgets/responsive_widgets.dart'; import '../constants/app_constants.dart'; +import '../services/get/theme_controller.dart'; class ResponsiveHomePage extends StatefulWidget { const ResponsiveHomePage({super.key}); @@ -12,6 +14,7 @@ class ResponsiveHomePage extends StatefulWidget { class _ResponsiveHomePageState extends State { String _layoutMode = AppConstants.gridLayout; + final ThemeController _themeController = Get.find(); @override Widget build(BuildContext context) { @@ -64,18 +67,18 @@ class _ResponsiveHomePageState extends State { text: '网格布局', onPressed: () => _changeLayout(AppConstants.gridLayout), backgroundColor: _layoutMode == AppConstants.gridLayout - ? AppConstants.primaryColor - : Colors.grey[300], - textColor: _layoutMode == AppConstants.gridLayout - ? Colors.white - : Colors.black, + ? _themeController.currentThemeColor + : Colors.grey[300], + textColor: _layoutMode == AppConstants.gridLayout + ? Colors.white + : Colors.black, ), const SizedBox(width: 12), ResponsiveButton( text: '列表布局', onPressed: () => _changeLayout(AppConstants.listLayout), backgroundColor: _layoutMode == AppConstants.listLayout - ? AppConstants.primaryColor + ? _themeController.currentThemeColor : Colors.grey[300], textColor: _layoutMode == AppConstants.listLayout ? Colors.white @@ -133,13 +136,13 @@ class _ResponsiveHomePageState extends State { width: double.infinity, height: ResponsiveLayout.isMobile(context) ? 80 : 120, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.widgets, size: ResponsiveLayout.isMobile(context) ? 32 : 48, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), const SizedBox(height: 12), @@ -172,13 +175,13 @@ class _ResponsiveHomePageState extends State { width: ResponsiveLayout.isMobile(context) ? 60 : 80, height: ResponsiveLayout.isMobile(context) ? 60 : 80, decoration: BoxDecoration( - color: AppConstants.primaryColor.withValues(alpha: 0.1), + color: _themeController.currentThemeColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.widgets, size: ResponsiveLayout.isMobile(context) ? 24 : 32, - color: AppConstants.primaryColor, + color: _themeController.currentThemeColor, ), ), const SizedBox(width: 16), diff --git a/lib/widgets/care/care_mode_navigation.dart b/lib/widgets/care/care_mode_navigation.dart new file mode 100644 index 0000000..f4cc950 --- /dev/null +++ b/lib/widgets/care/care_mode_navigation.dart @@ -0,0 +1,219 @@ +/// 时间: 2026-04-02 +/// 功能: 关怀模式底部导航栏 +/// 介绍: 关怀模式下显示的简化底部导航栏,只包含诗词和答题两个入口 +/// 最新变化: 2026-04-02 初始创建 + +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../config/app_config.dart'; +import '../../services/get/theme_controller.dart'; + +class CareModeNavigation extends StatelessWidget { + final int currentIndex; + final Function(int) onTap; + + const CareModeNavigation({ + super.key, + required this.currentIndex, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + final themeController = Get.find(); + + return Obx(() { + final isDark = themeController.isDarkMode; + final enableBlur = themeController.enableBlurEffect; + final primaryColor = themeController.currentThemeColor; + + return _buildGlassBar(context, isDark, enableBlur, primaryColor); + }); + } + + Widget _buildGlassBar( + BuildContext context, + bool isDark, + bool enableBlur, + Color primaryColor, + ) { + return SafeArea( + top: false, + child: Container( + padding: EdgeInsets.only( + left: AppConfig.liquidGlassHorizontalMargin, + right: AppConfig.liquidGlassHorizontalMargin, + bottom: AppConfig.liquidGlassBottomMargin, + top: 8, + ), + child: Container( + height: AppConfig.liquidGlassHeight, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + AppConfig.liquidGlassCornerRadius, + ), + boxShadow: [ + BoxShadow( + color: isDark + ? Colors.black.withValues(alpha: 0.6) + : Colors.black.withValues(alpha: 0.15), + blurRadius: 35, + spreadRadius: -10, + offset: const Offset(0, 12), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular( + AppConfig.liquidGlassCornerRadius, + ), + child: enableBlur + ? BackdropFilter( + filter: ImageFilter.blur( + sigmaX: AppConfig.liquidGlassBlur, + sigmaY: AppConfig.liquidGlassBlur, + ), + child: _buildGlassContent(isDark, primaryColor), + ) + : _buildGlassContent(isDark, primaryColor), + ), + ), + ), + ); + } + + Widget _buildGlassContent(bool isDark, Color primaryColor) { + return Stack( + children: [ + Container( + decoration: BoxDecoration( + color: isDark + ? Colors.black.withValues(alpha: 0.4) + : Colors.white.withValues(alpha: 0.9), + borderRadius: BorderRadius.circular( + AppConfig.liquidGlassCornerRadius, + ), + ), + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + AppConfig.liquidGlassCornerRadius, + ), + border: Border.all( + color: isDark + ? Colors.white.withValues(alpha: 0.2) + : Colors.black.withValues(alpha: 0.1), + width: 0.6, + ), + ), + ), + _buildNavItems(primaryColor), + ], + ); + } + + Widget _buildNavItems(Color primaryColor) { + final items = [ + _NavItem(Icons.menu_book_rounded, '📖', '诗词', 0), + _NavItem(Icons.psychology_rounded, '🎯', '答题', 1), + ]; + + return Row( + children: List.generate(items.length, (index) { + return Expanded( + child: _buildNavItem( + items[index], + index == currentIndex, + primaryColor, + ), + ); + }), + ); + } + + Widget _buildNavItem(_NavItem item, bool isSelected, Color primaryColor) { + final themeController = Get.find(); + + return Obx(() { + final isDark = themeController.isDarkMode; + final enableAnimation = themeController.enableAnimation; + + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () => onTap(item.index), + splashColor: Colors.transparent, + highlightColor: Colors.transparent, + borderRadius: BorderRadius.circular( + AppConfig.liquidGlassCornerRadius, + ), + child: AnimatedContainer( + duration: enableAnimation + ? const Duration(milliseconds: 250) + : Duration.zero, + curve: Curves.easeOutCubic, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + enableAnimation + ? AnimatedScale( + scale: isSelected ? 1.1 : 1.0, + duration: const Duration(milliseconds: 200), + curve: Curves.easeOutCubic, + child: _buildIcon( + item, + isSelected, + isDark, + primaryColor, + ), + ) + : _buildIcon(item, isSelected, isDark, primaryColor), + const SizedBox(height: 3), + AnimatedDefaultTextStyle( + duration: enableAnimation + ? const Duration(milliseconds: 200) + : Duration.zero, + style: TextStyle( + fontSize: 12, + fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, + color: isSelected + ? primaryColor + : (isDark ? Colors.grey[400] : Colors.grey[600]), + letterSpacing: 0.15, + ), + child: Text(item.label), + ), + ], + ), + ), + ), + ); + }); + } + + Widget _buildIcon( + _NavItem item, + bool isSelected, + bool isDark, + Color primaryColor, + ) { + return Icon( + item.icon, + size: 24, + color: isSelected + ? primaryColor + : (isDark ? Colors.grey[400] : Colors.grey[600]), + ); + } +} + +class _NavItem { + final IconData icon; + final String emoji; + final String label; + final int index; + + _NavItem(this.icon, this.emoji, this.label, this.index); +} diff --git a/lib/widgets/common_widgets.dart b/lib/widgets/common_widgets.dart index 2704feb..16a1bd9 100644 --- a/lib/widgets/common_widgets.dart +++ b/lib/widgets/common_widgets.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../constants/app_constants.dart'; +import '../services/get/theme_controller.dart'; // 自定义按钮组件 class CustomButton extends StatelessWidget { @@ -28,13 +30,16 @@ class CustomButton extends StatelessWidget { @override Widget build(BuildContext context) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; + return SizedBox( width: width, height: height ?? 48, child: ElevatedButton( onPressed: isLoading ? null : onPressed, style: ElevatedButton.styleFrom( - backgroundColor: backgroundColor ?? AppConstants.primaryColor, + backgroundColor: backgroundColor ?? primaryColor, foregroundColor: textColor ?? Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(borderRadius ?? 8), @@ -180,13 +185,16 @@ class LoadingIndicator extends StatelessWidget { @override Widget build(BuildContext context) { + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; + return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( - color ?? AppConstants.primaryColor, + color ?? primaryColor, ), ), if (message != null) ...[ diff --git a/lib/widgets/main_navigation.dart b/lib/widgets/main_navigation.dart index 208c95e..ce1cfe0 100644 --- a/lib/widgets/main_navigation.dart +++ b/lib/widgets/main_navigation.dart @@ -1,15 +1,18 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../constants/app_constants.dart'; import '../views/home/home_page.dart'; import '../views/discover_page.dart'; import '../views/favorites_page.dart'; import '../views/profile/profile_page.dart'; +import '../views/profile/level/poetry.dart'; +import '../views/home/care/care_poetry_page.dart'; import '../services/get/main_navigation_controller.dart'; import '../services/get/profile_controller.dart'; import '../services/get/theme_controller.dart'; import '../services/get/tap_liquid_glass_controller.dart'; +import '../services/get/care_controller.dart'; import 'tap-liquid-glass.dart'; +import 'care/care_mode_navigation.dart'; /// 时间: 2025-03-21 /// 功能: 主导航页面,包含底部导航栏和4个主要页面 @@ -24,9 +27,11 @@ class MainNavigation extends StatelessWidget { // 初始化导航控制器(只初始化一次) Get.lazyPut(() => MainNavigationController()); Get.lazyPut(() => TapLiquidGlassController()); + Get.lazyPut(() => CareController()); final controller = Get.find(); final themeController = Get.find(); final glassController = Get.find(); + final careController = Get.find(); final List pages = [ HomePage(), @@ -35,25 +40,27 @@ class MainNavigation extends StatelessWidget { const ProfilePage(), ]; + final primaryColor = themeController.currentThemeColor; + final List bottomNavItems = [ - const BottomNavigationBarItem( - icon: Icon(Icons.home), - activeIcon: Icon(Icons.home, color: AppConstants.primaryColor), + BottomNavigationBarItem( + icon: const Icon(Icons.home), + activeIcon: Icon(Icons.home, color: primaryColor), label: '主页', ), - const BottomNavigationBarItem( - icon: Icon(Icons.explore), - activeIcon: Icon(Icons.explore, color: AppConstants.primaryColor), + BottomNavigationBarItem( + icon: const Icon(Icons.explore), + activeIcon: Icon(Icons.explore, color: primaryColor), label: '发现', ), - const BottomNavigationBarItem( - icon: Icon(Icons.favorite_border), - activeIcon: Icon(Icons.favorite, color: AppConstants.primaryColor), + BottomNavigationBarItem( + icon: const Icon(Icons.favorite_border), + activeIcon: Icon(Icons.favorite, color: primaryColor), label: '收藏', ), - const BottomNavigationBarItem( - icon: Icon(Icons.person_outline), - activeIcon: Icon(Icons.person, color: AppConstants.primaryColor), + BottomNavigationBarItem( + icon: const Icon(Icons.person_outline), + activeIcon: Icon(Icons.person, color: primaryColor), label: '个人', ), ]; @@ -61,11 +68,23 @@ class MainNavigation extends StatelessWidget { return Obx(() { final isDark = themeController.isDarkMode; final useGlass = glassController.isEnabled; + final isCareMode = careController.isCareModeEnabled; + + // 关怀模式开启时,使用关怀模式的导航栏 + if (isCareMode) { + return Scaffold(body: _buildCareModeBody(careController)); + } return Scaffold( body: useGlass ? _buildGlassBody(controller, pages) - : _buildClassicBody(controller, pages, isDark, bottomNavItems), + : _buildClassicBody( + controller, + pages, + isDark, + bottomNavItems, + primaryColor, + ), ); }); } @@ -79,10 +98,7 @@ class MainNavigation extends StatelessWidget { return Stack( children: [ // 页面内容 - 延伸到屏幕底部 - IndexedStack( - index: controller.currentIndex.value, - children: pages, - ), + IndexedStack(index: controller.currentIndex.value, children: pages), // 悬浮的液态玻璃导航栏 Positioned( left: 0, @@ -109,6 +125,7 @@ class MainNavigation extends StatelessWidget { List pages, bool isDark, List items, + Color primaryColor, ) { return Column( children: [ @@ -143,7 +160,7 @@ class MainNavigation extends StatelessWidget { } }, type: BottomNavigationBarType.fixed, - selectedItemColor: AppConstants.primaryColor, + selectedItemColor: primaryColor, unselectedItemColor: isDark ? Colors.grey[400] : Colors.grey[600], backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, elevation: 0, @@ -156,4 +173,34 @@ class MainNavigation extends StatelessWidget { ], ); } + + /// 构建关怀模式主体 + /// 使用 Stack 布局,让导航栏悬浮在页面内容上方 + Widget _buildCareModeBody(CareController careController) { + return Obx(() { + final carePages = [const CarePoetryPage(), const PoetryLevelPage()]; + + return Stack( + children: [ + // 页面内容 - 延伸到屏幕底部 + IndexedStack( + index: careController.careNavigationIndex, + children: carePages, + ), + // 悬浮的关怀模式导航栏 + Positioned( + left: 0, + right: 0, + bottom: 0, + child: CareModeNavigation( + currentIndex: careController.careNavigationIndex, + onTap: (index) { + careController.switchCareNavigation(index); + }, + ), + ), + ], + ); + }); + } } diff --git a/lib/widgets/responsive_widgets.dart b/lib/widgets/responsive_widgets.dart index c31e367..272af09 100644 --- a/lib/widgets/responsive_widgets.dart +++ b/lib/widgets/responsive_widgets.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../utils/responsive_layout.dart'; import '../constants/app_constants.dart'; +import '../services/get/theme_controller.dart'; class ResponsiveButton extends StatelessWidget { final String text; @@ -25,6 +27,8 @@ class ResponsiveButton extends StatelessWidget { @override Widget build(BuildContext context) { final buttonSize = size ?? (ResponsiveLayout.isMobile(context) ? ButtonSize.small : ButtonSize.medium); + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return SizedBox( width: ResponsiveLayout.isMobile(context) ? double.infinity : null, @@ -32,7 +36,7 @@ class ResponsiveButton extends StatelessWidget { child: ElevatedButton( onPressed: isLoading ? null : onPressed, style: ElevatedButton.styleFrom( - backgroundColor: backgroundColor ?? AppConstants.primaryColor, + backgroundColor: backgroundColor ?? primaryColor, foregroundColor: textColor ?? Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_getBorderRadius(buttonSize)), diff --git a/lib/widgets/tabbed_nav_app_bar.dart b/lib/widgets/tabbed_nav_app_bar.dart index fb715c9..5edcb85 100644 --- a/lib/widgets/tabbed_nav_app_bar.dart +++ b/lib/widgets/tabbed_nav_app_bar.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import '../constants/app_constants.dart'; +import '../services/get/theme_controller.dart'; /// 时间: 2026-03-22 /// 功能: 主导航内「标题 + Tab」共用 AppBar 构造 @@ -23,6 +25,8 @@ class TabbedNavAppBar { Color? foregroundColor, }) { final isDark = backgroundColor != null && backgroundColor != Colors.white; + final themeController = Get.find(); + final primaryColor = themeController.currentThemeColor; return AppBar( title: Text( @@ -55,10 +59,10 @@ class TabbedNavAppBar { dividerHeight: 0, dividerColor: Colors.transparent, tabs: tabLabels.map((String e) => Tab(text: e)).toList(), - labelColor: AppConstants.primaryColor, + labelColor: primaryColor, unselectedLabelColor: isDark ? Colors.grey[400] : Colors.grey[600], indicator: UnderlineTabIndicator( - borderSide: BorderSide(color: AppConstants.primaryColor, width: 3), + borderSide: BorderSide(color: primaryColor, width: 3), ), labelStyle: const TextStyle(fontWeight: FontWeight.bold), ), diff --git a/lib/widgets/tap-liquid-glass.dart b/lib/widgets/tap-liquid-glass.dart index 63a075a..99f7ab0 100644 --- a/lib/widgets/tap-liquid-glass.dart +++ b/lib/widgets/tap-liquid-glass.dart @@ -178,7 +178,7 @@ class TapLiquidGlassNavigation extends StatelessWidget { fontSize: 12, fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, color: isSelected - ? AppConstants.primaryColor + ? themeController.currentThemeColor : (isDark ? Colors.grey[400] : Colors.grey[600]), letterSpacing: 0.15, ), @@ -193,11 +193,13 @@ class TapLiquidGlassNavigation extends StatelessWidget { } Widget _buildIcon(_NavItem item, bool isSelected, bool isDark) { + final themeController = Get.find(); + return Icon( item.icon, size: 24, color: isSelected - ? AppConstants.primaryColor + ? themeController.currentThemeColor : (isDark ? Colors.grey[400] : Colors.grey[600]), ); } diff --git a/pubspec.lock b/pubspec.lock index 8f96d0c..9ac6ebf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -440,6 +440,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "7.0.2" + pinyin: + dependency: "direct main" + description: + name: pinyin + sha256: "240f271a3c71af20c8d2757756b5ee8e9d79a955d37abad4b3568fd406b22411" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.3.0" platform: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3768436..f76f46b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,8 +37,9 @@ dependencies: get: git: url: https://gitcode.com/openharmony-sig/fluttertpc_get + pinyin: ^3.3.0 + - dev_dependencies: flutter_test: sdk: flutter diff --git a/update_android_icons.py b/update_android_icons.py new file mode 100644 index 0000000..2f5eb24 --- /dev/null +++ b/update_android_icons.py @@ -0,0 +1,40 @@ +from PIL import Image +import os + +# 新的图片路径 +new_image_path = r"e:\project\flutter\f3\flutter_application_2\assets\IMG_20260402_172628.png" + +# 安卓端图标目录 +android_res_dir = r"e:\project\flutter\f3\flutter_application_2\android\app\src\main\res" + +# 安卓端图标尺寸配置 (density: (width, height)) +android_sizes = { + "mdpi": (48, 48), + "hdpi": (72, 72), + "xhdpi": (144, 144), + "xxhdpi": (96, 96), + "xxxhdpi": (192, 192), +} + +try: + # 打开新图片 + with Image.open(new_image_path) as img: + print(f"新图片尺寸: {img.size}") + + # 为每个密度生成图标 + for density, size in android_sizes.items(): + # 调整尺寸 + resized_img = img.resize(size, Image.Resampling.LANCZOS) + + # 构建输出路径 + output_dir = os.path.join(android_res_dir, f"mipmap-{density}") + os.makedirs(output_dir, exist_ok=True) + + output_path = os.path.join(output_dir, "ic_launcher.png") + resized_img.save(output_path) + print(f"已保存 {density} ({size[0]}x{size[1]}) 图标到: {output_path}") + + print("\n安卓端所有图标更新完成!") + +except Exception as e: + print(f"处理图片时出错: {e}")