diff --git a/CHANGELOG.md b/CHANGELOG.md index 7249418..58c7e43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,51 @@ All notable changes to this project will be documented in this file. --- +## [1.6.0] - 2026-04-18 + +### 优化 +- 🧹 **代码质量全面清理** + - 清理所有未使用的导入(app_constants.dart、theme_controller.dart等) + - 清理所有未使用的字段(_readAloudEnabled、_firstLaunch、_showGuideOnStartup、_isLoadingCategories等) + - 清理所有未使用的方法(_buildActionButton、_copyQQGroupNumber、_buildDesignStyleCard、_showGuideStatusPopup、_toggleShowGuide等) + - 清理未使用的局部变量(themeController等) + - 修复废弃API引用(withOpacity → withValues) + - 修复登录弹窗、服务器信息弹窗等组件的冗余依赖 + - 分析结果:0错误、0警告、164提示(均为info级别) + - 优先级:3 + +### 新增 +- 📋 **项目分析文档** + - 创建 `lib/PROJECT_ANALYSIS.md` 项目分析报告 + - 包含代码质量概览、需加强功能、现有问题分析、新增功能建议 + - 包含代码规范待改进项、开发进度追踪 + - 优先级:2 +- 🏷️ **主页标签点击跳转** + - 关键词标签(如"围炉夜话")点击后跳转到对应标签诗词列表页 + - 朝代标签(如"暂无朝代")点击后跳转到对应朝代诗词列表页 + - 长按仍保留复制功能 + - 涉及文件:`lib/views/home/home_part.dart` - _buildKeywordSection 方法 + - 优先级:3 + +--- + +## [1.4.8] - 2026-04-18 + +### 新增 +- ✨ **跟随系统深色模式开关** + - ThemeController 新增 `_followSystem` 响应式状态(默认开启) + - 实现 `WidgetsBindingObserver` 监听系统亮度变化(`didChangePlatformBrightness`) + - 跟随系统开启时,应用自动跟随 OS 深色/浅色模式切换 + - 跟随系统开启时,隐藏"深色模式"手动开关,界面更简洁 + - 跟随系统关闭时,显示"深色模式"手动开关,由用户手动控制 + - 状态持久化到 SharedPreferences + - 涉及文件: + - `lib/services/get/theme_controller.dart` - 新增 followSystem 状态、系统亮度监听、toggleFollowSystem 方法 + - `lib/views/profile/theme/app-diy.dart` - 新增跟随系统开关 UI + - 优先级:4 + +--- + ## [1.4.7] - 2026-04-09 ### 新增 @@ -119,186 +164,6 @@ All notable changes to this project will be documented in this file. --- -## [1.4.4] - 2026-04-09 - -### 新增 -- ✨ **创建公告信息页面** - - 新建 `lib/views/footprint/load/notice-page.dart` 文件 - - 从 `https://yy.vogov.cn/api/app/notice_api.php` 获取公告数据 - - 支持下拉刷新、加载状态、错误处理 - - 使用 iOS 风格 Cupertino 组件 - - 公告卡片显示公告编号、内容、作者、创建时间、更新时间 - - 支持可选显示导航栏(`showAppBar` 参数) - - 涉及文件: - - `lib/views/footprint/load/notice-page.dart` - 新增公告页面 - - `lib/views/favorites_page.dart` - 集成公告页面到推送标签 -- ✨ **在收藏页面添加推送标签功能** - - 在收藏页面的"推送"标签中显示公告列表 - - 公告页面嵌入到 TabBarView 中,不显示重复导航栏 - - 涉及文件: - - `lib/views/favorites_page.dart` - 添加推送标签处理 - - `lib/views/footprint/footprint_page.dart` - 移除通知按钮(公告已移至收藏页面) - ---- - -## [1.4.3] - 2026-04-04 - -### 修复 -- 🐛 **修复 Trae 环境下 WiFi 设备安装卡顿问题** - - 问题:在 Trae 中运行到三星平板时,一直显示 "Installing build\app\outputs\flutter-apk\app-debug.apk...",但 Android Studio 能正常安装 - - 根本原因:WiFi 连接的设备建立 VM Service 连接较慢,导致 Flutter 认为安装卡住 - - 解决方案: - - 在 VS Code launch.json 中为所有配置添加 `--device-timeout=60` 参数 - - 新增 WiFi 设备专用配置,使用 `--device-timeout=120` 和 `--device-connection=wireless` - - 新增 USB 设备专用配置,使用 `--device-timeout=30` 和 `--device-connection=attached` - - 创建 WiFi 设备连接辅助脚本(wifi_device_helper.bat 和 wifi_device_helper.ps1) - - 提供手动安装 APK 的选项,绕过 VM Service 连接等待 - - 涉及文件: - - `.vscode/launch.json` - 优化设备连接配置 - - `wifi_device_helper.bat` - Windows 批处理辅助脚本 - - `wifi_device_helper.ps1` - PowerShell 辅助脚本 - - 使用说明: - - 在 VS Code 中运行时,选择 "flutter_application_2 (WiFi Device)" 配置 - - 或使用辅助脚本 `wifi_device_helper.bat` 或 `wifi_device_helper.ps1` - - 如仍卡住,可选择选项 4 手动安装 APK - ---- - -## [1.4.2] - 2026-04-04 - -### 新增 -- ✨ **创建统一的平台判断工具类 PlatformUtils** - - 新建 `lib/controllers/settings/is_platform.dart` 文件 - - 统一管理平台判断逻辑,支持 Web、Android、iOS、HarmonyOS、Windows、macOS、Linux 等平台 - - 提供平台检测、操作系统信息获取、平台显示名称等功能 - - 所有平台判断方法都包含异常处理,确保在 Web 平台也能正常工作 - -### 重构 -- ♻️ **统一平台判断代码** - - 将分散在多个文件中的平台判断代码统一使用 PlatformUtils - - 移除了各文件中重复的 `import 'dart:io'` 和 `import 'package:flutter/foundation.dart'` - - 简化了平台判断逻辑,提高了代码可维护性 - - 涉及文件: - - `lib/views/profile/app-info.dart` - 使用 PlatformUtils 替代 io.Platform - - `lib/views/profile/expand/manu-script.dart` - 使用 PlatformUtils.platformDisplayName - - `lib/views/profile/profile_page.dart` - 使用 PlatformUtils.isWeb - - `lib/views/profile/components/pop-menu.dart` - 使用 PlatformUtils - - `lib/services/get/profile_controller.dart` - 使用 PlatformUtils - - `lib/views/profile/guide/app-data.dart` - 使用 PlatformUtils.pathSeparator - - `lib/utils/http/vote_api.dart` - 使用 PlatformUtils - -### 修复 -- 🐛 **修复三星平板卡 Logo 启动页的问题** - - 将屏幕适配从初始化阶段移到第一帧绘制后执行 - - 延迟 100ms 调用屏幕适配,避免在启动时阻塞 - - 为所有初始化步骤添加 try-catch 保护,即使某个初始化失败也能继续启动 - - 添加详细的调试日志,方便定位启动问题 - - 移除 AppInitializer 中的屏幕适配调用 - - 修改 MyApp 为 StatefulWidget,使用 WidgetsBindingObserver - - 涉及文件: - - `lib/main.dart` - 重构启动流程 - - `lib/utils/app_initializer.dart` - 优化初始化流程 - -## [1.4.1] - 2026-04-03 - -### 新增 -- ✨ **项目默认图标裁剪** - - 使用 Python PIL 库裁剪图片为正方形 - - 生成了多种尺寸的应用图标(1024x1024, 512x512, 256x256 等) - - 默认图标尺寸:512x512 - - 涉及文件: - - `assets/app_icon_default.png` - 项目默认图标(512x512) - - `assets/app_icon_square.png` - 正方形原图(1271x1271) - - `assets/app_icon_*.png` - 各种尺寸图标 - - `crop_image.py` - 图片裁剪脚本 -- ✨ **Web 图标替换** - - 替换了所有 web 平台的图标为新图片 - - 包括:favicon.png (32x32)、PWA 图标 (192x192, 512x512) - - 包含 maskable 图标版本 - - 涉及文件: - - `web/favicon.png` - 网站图标 - - `web/icons/Icon-192.png` - PWA 图标 - - `web/icons/Icon-512.png` - PWA 图标 - - `web/icons/Icon-maskable-192.png` - PWA 可遮罩图标 - - `web/icons/Icon-maskable-512.png` - PWA 可遮罩图标 - - `replace_web_icons.py` - Web 图标替换脚本 -- ✨ **从 pubspec.yaml 动态获取版本号** - - 使用 package_info_plus 插件动态获取应用版本号和版本代码 - - 在 AppConfig 中添加 init() 初始化方法和 appVersion、appVersionCode getter - - 在 main.dart 中应用启动时初始化 AppConfig - - 在 app-info.dart 中动态显示 appVersion 和 appVersionCode - - 涉及文件: - - `pubspec.yaml` - 使用官方 package_info_plus: ^9.0.1 - - `lib/config/app_config.dart` - 添加动态版本号获取 - - `lib/main.dart` - 初始化 AppConfig - - `lib/views/profile/app-info.dart` - 动态显示版本号 -- ✨ **软件更新日志卡片** - - 启用应用信息页面的软件更新日志卡片 - - 添加了版本 1.4.1 和 1.3.59 的更新内容 - - 涉及文件: - - `lib/views/profile/app-info.dart` - 启用更新日志 -- ✨ **开源框架列表添加 GetX** - - 在应用信息页面的开源框架列表中添加了 GetX - - GetX 协议:MIT - - 涉及文件: - - `lib/views/profile/app-info.dart` - 添加 GetX 到开源框架列表 -- ✨ **了解我们页面网站列表优化** - - 在官方网站卡片中添加了情景诗词在线版 - - 两个网站都添加了独立的复制按钮 - - 添加了网站标签显示(官方APP页/情景诗词在线版) - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 新增网站列表和复制按钮 - -### 优化 -- ⚡ **解决 package_info_plus 依赖冲突** - - 解决 wakelock_plus 与 package_info_plus 的版本冲突 - - 使用官方版本 package_info_plus: ^9.0.1 替代 git 版本 - - 同时保留鸿蒙适配版代码在 packages/flutter_plus_plugins/packages/package_info_plus 以备需要 - - 鸿蒙适配版包含完整的 ohos 平台实现 - - 涉及文件: - - `pubspec.yaml` - 移除 dependency_overrides,使用官方版本 - - `packages/flutter_plus_plugins/packages/package_info_plus` - 鸿蒙适配版本地备份 -- ⚡ **使用 Get.snackbar 替代 ScaffoldMessenger** - - 将应用信息页面中的所有 SnackBar 消息改为 Get.snackbar - - 背景色使用 Get.snackbar 默认颜色 - - 文字颜色使用动态主题色 - - 图标颜色也使用动态主题色(仅复制提示) - - 添加圆角和边距样式 - - 涉及文件: - - `lib/views/profile/app-info.dart` - SnackBar 改为 Get.snackbar -- ⚡ **了解我们页面消息提示优化** - - 将了解我们页面中的所有 SnackBar 消息改为 Get.snackbar - - 包括:QQ群号复制、微信公众号复制、网站链接复制 - - 背景色使用 Get.snackbar 默认颜色 - - 文字颜色使用动态主题色 - - 涉及文件: - - `lib/views/profile/settings/learn-us.dart` - 所有消息改为 Get.snackbar - -### 修复 -- 🐛 **修复版本号不显示的问题** - - 将 AppConfig 中的版本号改为 GetX 响应式变量 - - 在 app-info.dart 中使用 Obx 观察版本号变化 - - 更新默认版本号为 1.4.1 - - 涉及文件: - - `lib/config/app_config.dart` - 响应式版本号 - - `lib/views/profile/app-info.dart` - Obx 包裹版本号显示 - -### 删除 -- 🗑️ **移除设计风格卡片** - - 从应用信息页面移除了设计风格卡片 - - 涉及文件: - - `lib/views/profile/app-info.dart` - 移除 _buildDesignStyleCard 调用 - -## [1.3.59] - 2026-04-03 - -### 修复 -- 🐛 **修复出处字段被时间提示语遮挡的问题** - - 给诗词卡片内容添加了顶部内边距(60) - - 确保出处等内容不被浮动的时间提示语遮挡 - - 涉及文件: - - `lib/views/home/home_part.dart` - 添加顶部内边距 - - --- ## 软件特性功能 @@ -322,6 +187,14 @@ All notable changes to this project will be documented in this file. - ✅ 深色模式支持 - ✅ 液态玻璃导航栏 - ✅ 多页面主题色支持 +- ✅ WiFi设备安装优化 (v1.4.3) +- ✅ 统一平台判断工具类 PlatformUtils (v1.4.2) +- ✅ 三星平板启动页修复 (v1.4.2) +- ✅ 动态版本号获取 (v1.4.1) +- ✅ Web图标替换 (v1.4.1) +- ✅ 出处字段遮挡修复 (v1.3.59) +- ✅ 公告信息页面 (v1.4.4) +- ✅ 收藏页面推送标签 (v1.4.4) ### 开发中 - 🚧 更多功能优化 diff --git a/analyze_output.txt b/analyze_output.txt new file mode 100644 index 0000000..e02abfc --- /dev/null +++ b/analyze_output.txt @@ -0,0 +1 @@ + diff --git a/lib/PROJECT_ANALYSIS.md b/lib/PROJECT_ANALYSIS.md new file mode 100644 index 0000000..ee882f3 --- /dev/null +++ b/lib/PROJECT_ANALYSIS.md @@ -0,0 +1,264 @@ +# 情景诗词 - 项目分析报告 + +> 生成时间: 2026-04-18 +> 版本: 1.6.0+26041801 +> 分析工具: flutter analyze + +--- + +## 一、当前代码质量概览 + +| 指标 | 数量 | 说明 | +|------|------|------| +| ❌ 错误 (error) | 0 | 无编译错误 | +| ⚠️ 警告 (warning) | 0 | 已全部清理 | +| ℹ️ 提示 (info) | 164 | 需逐步优化 | +| 📁 文件名不规范 | 20 | 使用连字符命名 | +| 🔄 废弃API | 25 | withOpacity/activeColor等 | +| 🔀 异步上下文 | 10 | use_build_context_synchronously | + +--- + +## 二、需要加强的功能(按优先级排序) + +### 🔴 优先级 5 - 核心功能缺失 + +1. **☁️ 云端同步** + - 位置: `lib/views/profile/guide/app-data.dart:1059` + - 现状: 仅显示"云端同步功能开发中..." + - 建议: 实现用户数据云端备份与恢复,支持跨设备同步 + - 依赖: 需要后端API支持 + +2. **🔐 用户账号系统** + - 现状: 仅有投票凭证填写(`login_register_dialog.dart`),无完整账号体系 + - 建议: 实现注册/登录/个人信息管理,为云端同步和社交功能提供基础 + - 依赖: 后端用户系统API + +3. **📱 二维码能力** + - 现状: CHANGELOG中标记为开发中 + - 建议: 支持扫码分享诗词、扫码添加好友、生成诗词卡片二维码 + +### 🟠 优先级 4 - 体验优化 + +4. **📖 诗词详情页** + - 位置: `lib/views/active/popular_page.dart:616` (TODO) + - 现状: 热门诗词点击后跳转详情页未实现 + - 建议: 实现完整诗词详情页,包含原文/译文/赏析/作者信息 + +5. **🔍 搜索设置功能** + - 位置: `lib/views/active/active_search_page.dart:206` + - 现状: 搜索页面"搜索设置"标记为开发中 + - 建议: 支持搜索范围、搜索历史管理、搜索偏好设置 + +6. **📊 历史记录详情与分享** + - 位置: `lib/views/profile/history_page.dart:515-522` + - 现状: 分享功能和查看详情功能均标记为开发中 + - 建议: 实现历史记录的详情查看和分享功能 + +7. **🎨 个性化主题设置** + - 位置: `lib/views/profile/theme/app-diy.dart:84-96` + - 现状: 弹出"个性化设置开发中"提示 + - 建议: 实现自定义主题色、字体、背景等个性化设置 + +### 🟡 优先级 3 - 功能完善 + +8. **🏠 HarmonyOS桌面小组件** + - 现状: CHANGELOG中标记为开发中 + - 建议: 完善2x2/4x4布局,天气显示、每日诗句推送 + +9. **📝 笔记功能增强** + - 现状: 基础笔记功能已有,但缺少富文本、图片附件 + - 建议: 支持Markdown、插入图片、语音笔记 + +10. **🏆 诗词挑战增强** + - 现状: 基础答题功能已有 + - 建议: 增加排行榜、每日挑战、成就系统、错题本 + +--- + +## 三、现有问题分析 + +### 🐛 Bug类问题 + +| # | 问题 | 位置 | 严重度 | 状态 | +|---|------|------|--------|------| +| 1 | `withOpacity` 废弃API | 14处(per_card.dart等) | 低 | 待修复 | +| 2 | `activeColor` 废弃API | 10处(多个文件) | 低 | 待修复 | +| 3 | 异步上下文使用不当 | 10处 | 中 | 待修复 | +| 4 | 文件命名不规范 | 20个文件使用连字符 | 低 | 待修复 | +| 5 | `library;` 悬空文档注释 | 5个文件 | 低 | 待修复 | + +### 🏗️ 架构类问题 + +| # | 问题 | 说明 | 建议 | +|---|------|------|------| +| 1 | 状态管理不统一 | 部分页面用GetX,部分用setState | 统一使用GetX响应式管理 | +| 2 | 控制器职责过重 | ThemeController同时管理主题和系统监听 | 拆分为ThemeController和SystemController | +| 3 | 硬编码字符串 | 多处中文字符串直接写在代码中 | 提取为常量或国际化资源 | +| 4 | API调用分散 | HTTP请求散落在各个页面 | 统一封装为Repository层 | +| 5 | 缺少错误边界 | 页面级错误无统一处理 | 添加全局错误捕获和友好提示 | + +### 📦 依赖类问题 + +| # | 问题 | 说明 | 建议 | +|---|------|------|------| +| 1 | 多个本地路径依赖 | audioplayers/flutter_udid/share_plus/file_picker_ohos | 确保本地包版本与上游同步 | +| 2 | 多个git源依赖 | shared_preferences/get/wakelock_plus等 | 关注上游更新,适时切换为pub.dev | +| 3 | path_provider冲突 | 已通过git源解决 | 持续关注官方鸿蒙适配进度 | + +--- + +## 四、可新增功能建议 + +### 🌟 高价值功能 + +1. **🤖 AI诗词助手** + - 基于诗词内容的智能问答 + - 诗词创作辅助(对联、续写) + - 诗词意境解读 + +2. **👥 社交互动** + - 诗词评论与讨论 + - 好友系统与诗词分享 + - 诗词创作社区 + +3. **📅 每日推荐** + - 基于节气/节日推荐诗词 + - 个性化推荐算法 + - 每日一句推送通知 + +4. **🎮 趣味玩法** + - 诗词接龙 + - 飞花令 + - 诗词拼图 + - 填字游戏 + +### 🔧 实用功能 + +5. **🔊 朗读功能** + - TTS语音朗读诗词 + - 多种朗读风格选择 + - 背景音乐配合 + +6. **📖 学习模式** + - 诗词背诵模式(逐句隐藏) + - 诗词默写模式 + - 学习进度追踪 + +7. **📊 数据可视化** + - 个人阅读统计图表 + - 诗词偏好分析 + - 学习趋势报告 + +8. **🎯 智能收藏** + - 自动分类收藏 + - 标签管理系统 + - 智能去重 + +9. **🌙 番茄钟模式** + - 专注阅读计时 + - 阅读时长统计 + - 阅读目标设定 + +10. **📱 多端适配** + - iPad适配优化 + - 折叠屏适配 + - 手表端诗词推送 + +--- + +## 五、代码规范待改进项 + +### 文件命名(20个文件) + +当前使用连字符命名(`app-diy.dart`),Dart规范要求使用下划线命名(`app_diy.dart`): + +| 当前文件名 | 建议文件名 | +|------------|------------| +| `app-diy.dart` | `app_diy.dart` | +| `app-data.dart` | `app_data.dart` | +| `app_fun.dart` | `app_fun.dart` (已合规) | +| `learn-us.dart` | `learn_us.dart` | +| `offline-data.dart` | `offline_data.dart` | +| `user-plan.dart` | `user_plan.dart` | +| `care-page.dart` | `care_page.dart` | +| `care_poetry_page.dart` | (已合规) | +| `home-load.dart` | `home_load.dart` | +| `home-set.dart` | `home_set.dart` | +| `level-jilu.dart` | `level_jilu.dart` | +| `poetry-page.dart` | `poetry_page.dart` | +| `flow-anim.dart` | `flow_anim.dart` | +| `manu-script.dart` | `manu_script.dart` | +| `help-page.dart` | `help_page.dart` | +| `notice-page.dart` | `notice_page.dart` | +| `sp-guide.dart` | `sp_guide.dart` | +| `bug_list_page.dart` | (已合规) | +| `tap-liquid-glass.dart` | `tap_liquid_glass.dart` | +| `search_history_page.dart` | (已合规) | + +> ⚠️ 重命名文件需同步更新所有import引用,建议分批次进行 + +### 废弃API替换 + +| 废弃API | 替换API | 影响文件数 | +|---------|---------|-----------| +| `Color.withOpacity()` | `Color.withValues(alpha:)` | 2个文件14处 | +| `Switch.activeColor` | `Switch.activeThumbColor` | 5个文件10处 | + +### 异步上下文安全 + +10处 `use_build_context_synchronously` 警告需添加 `mounted` 检查: + +```dart +// 修复前 +Future _loadData() async { + final data = await api.fetch(); + Navigator.push(context, ...); // 可能不安全 +} + +// 修复后 +Future _loadData() async { + final data = await api.fetch(); + if (!mounted) return; // 安全检查 + Navigator.push(context, ...); +} +``` + +--- + +## 六、项目文件结构统计 + +| 目录 | 文件数 | 说明 | +|------|--------|------| +| `lib/views/` | ~45 | 页面文件 | +| `lib/services/get/` | 11 | GetX控制器 | +| `lib/models/` | 7 | 数据模型 | +| `lib/utils/` | 8 | 工具类 | +| `lib/controllers/` | 5 | 业务控制器 | +| `lib/widgets/` | 6 | 公共组件 | +| `lib/config/` | 1 | 应用配置 | +| `lib/constants/` | 1 | 常量定义 | +| `lib/routes/` | 1 | 路由配置 | + +--- + +## 七、开发进度追踪 + +| 功能 | 优先级 | 状态 | 备注 | +|------|--------|------|------| +| 云端同步 | 5 | 🔴 未开始 | 需后端支持 | +| 用户账号系统 | 5 | 🔴 未开始 | 需后端支持 | +| 二维码能力 | 4 | 🔴 未开始 | | +| 诗词详情页 | 4 | 🟡 部分完成 | 热门页跳转未实现 | +| 搜索设置 | 3 | 🟡 部分完成 | 设置搜索页已实现 | +| 个性化主题 | 4 | 🔴 未开始 | 弹窗提示开发中 | +| 历史详情/分享 | 3 | 🔴 未开始 | | +| HarmonyOS小组件 | 3 | 🟡 开发中 | 基础框架已有 | +| 朗读功能 | 3 | 🔴 未开始 | | +| 学习模式 | 2 | 🔴 未开始 | | +| 社交互动 | 2 | 🔴 未开始 | 需后端支持 | +| AI诗词助手 | 1 | 🔴 未开始 | 需AI接口 | + +--- + +*此文档由项目分析自动生成,供开发团队参考。每次重大更新后应同步更新此文档。* diff --git a/lib/controllers/settings/suggestions.dart b/lib/controllers/settings/suggestions.dart index 948c2be..36b99dd 100644 --- a/lib/controllers/settings/suggestions.dart +++ b/lib/controllers/settings/suggestions.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../services/get/theme_controller.dart'; @@ -11,6 +12,9 @@ import '../../views/profile/guide/beginner_page.dart'; import '../../views/active/active_search_page.dart'; import '../../views/active/rate.dart'; import '../../views/profile/components/entire_page.dart'; +import '../../views/profile/guide/permission.dart'; +import '../../views/profile/guide/app-data.dart'; +import '../../views/profile/settings/app_fun.dart'; class SuggestionsCard extends StatefulWidget { const SuggestionsCard({super.key}); @@ -75,7 +79,7 @@ class _SuggestionsCardState extends State { 'title': ' 搜索设置', 'subtitle': '搜索软件内的设置', 'icon': Icons.search, - 'page': const _PlaceholderPage(title: '搜索设置'), + 'page': const SettingsSearchPage(), }, { 'title': '统计', @@ -525,58 +529,334 @@ class _PageWithBackButtonState extends State<_PageWithBackButton> { } } -/// 占位页面 - 用于清理数据功能 -class _PlaceholderPage extends StatelessWidget { - final String title; +/// 设置搜索页面 - 支持搜索所有设置项并跳转 +class SettingsSearchPage extends StatefulWidget { + const SettingsSearchPage({super.key}); - const _PlaceholderPage({required this.title}); + @override + State createState() => _SettingsSearchPageState(); +} + +class _SettingsSearchPageState extends State { + final ThemeController _themeController = Get.find(); + final TextEditingController _searchController = TextEditingController(); + final FocusNode _focusNode = FocusNode(); + String _searchQuery = ''; + + late final List> _allSettings; + + @override + void initState() { + super.initState(); + _allSettings = [ + { + 'title': '主题风格', + 'subtitle': '自定义应用主题颜色、字体大小', + 'icon': Icons.palette, + 'page': const AppDiyPage(), + }, + { + 'title': '深色模式', + 'subtitle': '开启或关闭深色模式', + 'icon': Icons.dark_mode, + 'page': const AppDiyPage(), + }, + { + 'title': '跟随系统', + 'subtitle': '自动跟随系统深色模式', + 'icon': Icons.brightness_auto, + 'page': const AppDiyPage(), + }, + { + 'title': '自动刷新', + 'subtitle': '首页诗句自动刷新(5s)', + 'icon': Icons.refresh, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '调式信息', + 'subtitle': '开启后可加载更多信息', + 'icon': Icons.bug_report, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '预加载', + 'subtitle': '开启后优先使用本地缓存', + 'icon': Icons.storage, + 'page': const AppFunSettingsPage(), + }, + { + 'title': 'Tap沉浸光感', + 'subtitle': '开启后底栏显示类iOS26风格', + 'icon': Icons.dark_mode, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '隐藏次要按钮', + 'subtitle': '隐藏上一条和分享按钮', + 'icon': Icons.share, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '全局Tips开关', + 'subtitle': '显示一些使用技巧', + 'icon': Icons.lightbulb, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '声音反馈', + 'subtitle': '操作时播放提示音', + 'icon': Icons.volume_up, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '震动反馈', + 'subtitle': '操作时震动提示', + 'icon': Icons.vibration, + 'page': const AppFunSettingsPage(), + }, + { + 'title': '权限管理', + 'subtitle': '管理震动、网络、剪切板等权限', + 'icon': Icons.shield, + 'page': const PermissionPage(), + }, + { + 'title': '应用数据', + 'subtitle': '查看配置详情、导出导入数据', + 'icon': Icons.storage, + 'page': const AppDataPage(), + }, + { + 'title': '关怀模式', + 'subtitle': '大字简洁模式', + 'icon': Icons.favorite, + 'page': const CarePage(), + }, + { + 'title': '使用教程', + 'subtitle': '软件功能指南', + 'icon': Icons.menu_book, + 'page': const BeginnerPage(), + }, + { + 'title': '了解软件', + 'subtitle': '查看应用信息、版本号', + 'icon': Icons.info, + 'page': const AppInfoPage(), + }, + { + 'title': '全站统计', + 'subtitle': '查看网站统计数据', + 'icon': Icons.bar_chart, + 'page': const EntirePage(), + }, + { + 'title': '诗词搜索', + 'subtitle': '全站诗词搜索', + 'icon': Icons.search, + 'page': const ActiveSearchPage(), + }, + { + 'title': '创建笔记', + 'subtitle': '快速创建新笔记', + 'icon': Icons.note_add, + 'page': const CollectNotesPage(), + }, + { + 'title': '重置设置', + 'subtitle': '恢复默认设置', + 'icon': Icons.restore, + 'page': const AppFunSettingsPage(), + }, + ]; + } + + @override + void dispose() { + _searchController.dispose(); + _focusNode.dispose(); + super.dispose(); + } + + List> get _filteredSettings { + if (_searchQuery.isEmpty) return _allSettings; + final query = _searchQuery.toLowerCase(); + return _allSettings.where((item) { + final title = (item['title'] as String).toLowerCase(); + final subtitle = (item['subtitle'] as String).toLowerCase(); + return title.contains(query) || subtitle.contains(query); + }).toList(); + } @override Widget build(BuildContext context) { - final themeController = Get.find(); - return Obx(() { - final isDark = themeController.isDarkModeRx.value; - final themeColor = AppColors.primary; + final isDark = _themeController.isDarkModeRx.value; + final themeColor = _themeController.currentThemeColor; return Scaffold( + backgroundColor: isDark + ? const Color(0xFF121212) + : const Color(0xFFF2F2F7), appBar: AppBar( - title: Text(title), - backgroundColor: isDark ? const Color(0xFF1A1A1A) : Colors.white, - foregroundColor: isDark ? Colors.white : Colors.black, + backgroundColor: isDark ? const Color(0xFF1E1E1E) : Colors.white, elevation: 0, - ), - backgroundColor: isDark ? const Color(0xFF121212) : Colors.grey[50], - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.construction, - size: 64, - color: themeColor.withValues(alpha: 0.5), - ), - const SizedBox(height: 16), - Text( - '$title 功能开发中', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - color: isDark ? Colors.white : Colors.black87, - ), - ), - const SizedBox(height: 8), - Text( - '敬请期待', - style: TextStyle( - fontSize: 14, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), - ), - ], + title: Text( + '搜索设置', + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontWeight: FontWeight.w600, + fontSize: 17, + ), ), + centerTitle: true, + leading: IconButton( + icon: Icon(CupertinoIcons.back, color: themeColor), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Column( + children: [ + Container( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), + color: isDark ? const Color(0xFF1E1E1E) : Colors.white, + child: Container( + decoration: BoxDecoration( + color: isDark + ? const Color(0xFF2A2A2A) + : const Color(0xFFE5E5EA), + borderRadius: BorderRadius.circular(10), + ), + child: CupertinoTextField( + controller: _searchController, + focusNode: _focusNode, + placeholder: '搜索设置项…', + placeholderStyle: TextStyle( + color: isDark ? Colors.grey[500] : Colors.grey, + fontSize: 16, + ), + style: TextStyle( + color: isDark ? Colors.white : Colors.black, + fontSize: 16, + ), + prefix: Padding( + padding: const EdgeInsets.only(left: 8), + child: Icon( + CupertinoIcons.search, + size: 18, + color: isDark ? Colors.grey[400] : Colors.grey, + ), + ), + suffix: _searchQuery.isNotEmpty + ? GestureDetector( + onTap: () { + _searchController.clear(); + setState(() => _searchQuery = ''); + }, + child: Padding( + padding: const EdgeInsets.only(right: 8), + child: Icon( + CupertinoIcons.clear_circled_solid, + size: 18, + color: isDark ? Colors.grey[400] : Colors.grey, + ), + ), + ) + : null, + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 10, + ), + decoration: const BoxDecoration(), + onChanged: (value) => setState(() => _searchQuery = value), + ), + ), + ), + Expanded( + child: _filteredSettings.isEmpty + ? Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + CupertinoIcons.search, + size: 48, + color: isDark ? Colors.grey[600] : Colors.grey[400], + ), + const SizedBox(height: 12), + Text( + '未找到"$_searchQuery"相关设置', + style: TextStyle( + fontSize: 16, + color: isDark + ? Colors.grey[400] + : Colors.grey[600], + ), + ), + ], + ), + ) + : ListView.separated( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: _filteredSettings.length, + separatorBuilder: (_, __) => Divider( + height: 0.5, + indent: 56, + color: isDark + ? Colors.grey[800] + : const Color(0xFFE5E5EA), + ), + itemBuilder: (context, index) { + final item = _filteredSettings[index]; + return _buildSearchResultItem(item, isDark, themeColor); + }, + ), + ), + ], ), ); }); } + + Widget _buildSearchResultItem( + Map item, + bool isDark, + Color themeColor, + ) { + return ListTile( + leading: Container( + width: 32, + height: 32, + decoration: BoxDecoration( + color: themeColor.withAlpha(20), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(item['icon'] as IconData, color: themeColor, size: 18), + ), + title: Text( + item['title'] as String, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white : Colors.black, + ), + ), + subtitle: Text( + item['subtitle'] as String, + style: TextStyle( + fontSize: 12, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + ), + trailing: Icon( + CupertinoIcons.chevron_forward, + size: 16, + color: isDark ? Colors.grey[600] : Colors.grey[400], + ), + onTap: () { + Get.to(() => item['page'] as Widget); + }, + ); + } } diff --git a/lib/services/get/favorites_controller.dart b/lib/services/get/favorites_controller.dart index 4f98dc5..98dd8c1 100644 --- a/lib/services/get/favorites_controller.dart +++ b/lib/services/get/favorites_controller.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../../constants/app_constants.dart'; import 'theme_controller.dart'; class FavoritesController extends GetxController { @@ -61,79 +60,99 @@ class FavoritesController extends GetxController { } void showFilterOptions(BuildContext context) { - // 先获取当前值,避免在弹窗中使用 Obx - final currentSortByTime = sortByTime.value; - final currentLikesFirst = likesFirst.value; + final themeController = Get.find(); + final isDark = themeController.isDarkMode; + final themeColor = themeController.currentThemeColor; showModalBottomSheet( context: context, + backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), builder: (BuildContext context) => Container( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ - const Text( + Container( + width: 40, + height: 4, + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: isDark ? Colors.grey[600] : Colors.grey[300], + borderRadius: BorderRadius.circular(2), + ), + ), + Text( '排序选项', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), ), const SizedBox(height: 16), - ListTile( - leading: const Icon(Icons.date_range), - title: const Text('按时间排序'), + Obx(() => ListTile( + leading: Icon(Icons.date_range, color: themeColor), + title: Text( + '按时间排序', + style: TextStyle(color: isDark ? Colors.white : Colors.black87), + ), trailing: Icon( - currentSortByTime + sortByTime.value ? Icons.radio_button_checked : Icons.radio_button_unchecked, - color: AppConstants.primaryColor, + color: themeColor, ), onTap: () { Navigator.pop(context); sortByTime.value = true; - // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar Future.delayed(const Duration(milliseconds: 100), () { - final tc = Get.find(); - Get.snackbar('提示', '已按时间排序', colorText: tc.currentThemeColor); + Get.snackbar('提示', '已按时间排序', colorText: themeColor); }); }, - ), - ListTile( - leading: const Icon(Icons.title), - title: const Text('按分类排序'), + )), + Obx(() => ListTile( + leading: Icon(Icons.title, color: themeColor), + title: Text( + '按分类排序', + style: TextStyle(color: isDark ? Colors.white : Colors.black87), + ), trailing: Icon( - !currentSortByTime + !sortByTime.value ? Icons.radio_button_checked : Icons.radio_button_unchecked, - color: AppConstants.primaryColor, + color: themeColor, ), onTap: () { Navigator.pop(context); sortByTime.value = false; - // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar Future.delayed(const Duration(milliseconds: 100), () { - final tc = Get.find(); - Get.snackbar('提示', '已按分类排序', colorText: tc.currentThemeColor); + Get.snackbar('提示', '已按分类排序', colorText: themeColor); }); }, - ), - const Divider(), - ListTile( - leading: const Icon(Icons.swap_vert), - title: Text(currentLikesFirst ? '点赞在前' : '笔记在前'), - trailing: Icon(Icons.swap_vert, color: AppConstants.primaryColor), + )), + const Divider(color: Colors.grey), + Obx(() => ListTile( + leading: Icon(Icons.swap_vert, color: themeColor), + title: Text( + likesFirst.value ? '点赞在前' : '笔记在前', + style: TextStyle(color: isDark ? Colors.white : Colors.black87), + ), + trailing: Icon(Icons.swap_vert, color: themeColor), onTap: () { Navigator.pop(context); likesFirst.value = !likesFirst.value; - // 使用 Future.delayed 确保弹窗完全关闭后再显示 snackbar Future.delayed(const Duration(milliseconds: 100), () { - final tc = Get.find(); Get.snackbar( '提示', likesFirst.value ? '点赞在前' : '笔记在前', - colorText: tc.currentThemeColor, + colorText: themeColor, ); }); }, - ), + )), ], ), ), diff --git a/lib/services/get/home_controller.dart b/lib/services/get/home_controller.dart index fe4f440..b2b5270 100644 --- a/lib/services/get/home_controller.dart +++ b/lib/services/get/home_controller.dart @@ -279,35 +279,36 @@ class HomeController extends GetxController with NetworkListenerMixin { try { final response = await PoetryApi.toggleLike(poetryData.value!.id); - // 根据API响应消息直接判断状态 isLiked.value = response.message.contains('点赞成功'); - // 更新诗词数据 - if (response.data != null) { - poetryData.value = PoetryData( - id: poetryData.value!.id, - name: poetryData.value!.name, - alias: poetryData.value!.alias, - keywords: poetryData.value!.keywords, - introduce: poetryData.value!.introduce, - drtime: poetryData.value!.drtime, - like: response.data!.like, - url: poetryData.value!.url, - tui: poetryData.value!.tui, - star: poetryData.value!.star, - hitsTotal: poetryData.value!.hitsTotal, - hitsMonth: poetryData.value!.hitsMonth, - hitsDay: poetryData.value!.hitsDay, - date: poetryData.value!.date, - datem: poetryData.value!.datem, - time: poetryData.value!.time, - createTime: poetryData.value!.createTime, - updateTime: poetryData.value!.updateTime, - ); - update(); // 通知UI更新 - } + final newLikeCount = response.data != null + ? response.data!.like + : (isLiked.value + ? poetryData.value!.like + 1 + : (poetryData.value!.like > 0 + ? poetryData.value!.like - 1 + : 0)); - // 通知UI更新点赞状态 + poetryData.value = PoetryData( + id: poetryData.value!.id, + name: poetryData.value!.name, + alias: poetryData.value!.alias, + keywords: poetryData.value!.keywords, + introduce: poetryData.value!.introduce, + drtime: poetryData.value!.drtime, + like: newLikeCount, + url: poetryData.value!.url, + tui: poetryData.value!.tui, + star: poetryData.value!.star, + hitsTotal: poetryData.value!.hitsTotal, + hitsMonth: poetryData.value!.hitsMonth, + hitsDay: poetryData.value!.hitsDay, + date: poetryData.value!.date, + datem: poetryData.value!.datem, + time: poetryData.value!.time, + createTime: poetryData.value!.createTime, + updateTime: poetryData.value!.updateTime, + ); update(); // 管理点赞存储 @@ -396,8 +397,16 @@ class HomeController extends GetxController with NetworkListenerMixin { } Future checkIfLiked() async { - // 这里可以实现检查收藏状态的逻辑 - // 暂时使用简单的模拟逻辑 + if (poetryData.value == null) return; + try { + final likedList = await HistoryController.getLikedHistory(); + final isAlreadyLiked = likedList.any( + (item) => item['id'].toString() == poetryData.value!.id.toString(), + ); + isLiked.value = isAlreadyLiked; + } catch (e) { + isLiked.value = false; + } } Future loadNextPoetry() async { diff --git a/lib/services/get/theme_controller.dart b/lib/services/get/theme_controller.dart index 0ea223d..301c8fc 100644 --- a/lib/services/get/theme_controller.dart +++ b/lib/services/get/theme_controller.dart @@ -1,8 +1,10 @@ // 时间: 2026-04-02 // 功能: 主题控制器 - 管理深色模式和主题设置 // 介绍: 使用 GetX 管理主题状态,支持状态持久化到 SharedPreferences +// 上次更新: 2026-04-18 新增跟随系统深色模式开关,监听系统亮度变化 import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../models/colors/theme_colors.dart'; @@ -10,7 +12,7 @@ import '../../models/night-mode/theme_model.dart'; /// 主题控制器 /// 管理应用的主题模式、深色模式状态,并持久化到 SharedPreferences -class ThemeController extends GetxController { +class ThemeController extends GetxController with WidgetsBindingObserver { // SharedPreferences 实例 SharedPreferences? _prefs; @@ -22,6 +24,7 @@ class ThemeController extends GetxController { static const String _fontSizeIndexKey = 'fontSizeIndex'; static const String _enableAnimationKey = 'enableAnimation'; static const String _enableBlurEffectKey = 'enableBlurEffect'; + static const String _followSystemKey = 'followSystem'; // 可观察状态 final _isDarkMode = false.obs; @@ -31,6 +34,7 @@ class ThemeController extends GetxController { final _fontSizeIndex = 1.obs; final _enableAnimation = true.obs; final _enableBlurEffect = true.obs; + final _followSystem = true.obs; // Getters bool get isDarkMode => _isDarkMode.value; @@ -40,6 +44,7 @@ class ThemeController extends GetxController { int get fontSizeIndex => _fontSizeIndex.value; bool get enableAnimation => _enableAnimation.value; bool get enableBlurEffect => _enableBlurEffect.value; + bool get followSystem => _followSystem.value; // 获取当前主题颜色 Color get currentThemeColor => @@ -51,10 +56,13 @@ class ThemeController extends GetxController { /// 获取当前 Flutter ThemeMode ThemeMode get currentThemeMode { + if (_followSystem.value) { + return ThemeMode.system; + } if (_isDarkMode.value) { return ThemeMode.dark; } - return _themeMode.value.themeMode; + return ThemeMode.light; } /// 获取 Rx 状态(供 Obx 使用) @@ -65,13 +73,34 @@ class ThemeController extends GetxController { RxInt get fontSizeIndexRx => _fontSizeIndex; RxBool get enableAnimationRx => _enableAnimation; RxBool get enableBlurEffectRx => _enableBlurEffect; + RxBool get followSystemRx => _followSystem; @override void onInit() { super.onInit(); + WidgetsBinding.instance.addObserver(this); _loadThemeSettings(); } + @override + void onClose() { + WidgetsBinding.instance.removeObserver(this); + super.onClose(); + } + + /// 系统亮度变化回调 + @override + void didChangePlatformBrightness() { + super.didChangePlatformBrightness(); + if (_followSystem.value) { + final isSystemDark = + SchedulerBinding.instance.platformDispatcher.platformBrightness == + Brightness.dark; + _isDarkMode.value = isSystemDark; + _applyThemeMode(); + } + } + /// SharedPreferences 实例(公开访问,供其他组件使用) SharedPreferences? get prefs => _prefs; @@ -90,6 +119,15 @@ class ThemeController extends GetxController { _fontSizeIndex.value = _prefs?.getInt(_fontSizeIndexKey) ?? 1; _enableAnimation.value = _prefs?.getBool(_enableAnimationKey) ?? true; _enableBlurEffect.value = _prefs?.getBool(_enableBlurEffectKey) ?? true; + _followSystem.value = _prefs?.getBool(_followSystemKey) ?? true; + + // 跟随系统时,同步系统亮度到 _isDarkMode + if (_followSystem.value) { + final isSystemDark = + SchedulerBinding.instance.platformDispatcher.platformBrightness == + Brightness.dark; + _isDarkMode.value = isSystemDark; + } // 应用主题模式 _applyThemeMode(); @@ -106,6 +144,7 @@ class ThemeController extends GetxController { await _prefs?.setInt(_fontSizeIndexKey, _fontSizeIndex.value); await _prefs?.setBool(_enableAnimationKey, _enableAnimation.value); await _prefs?.setBool(_enableBlurEffectKey, _enableBlurEffect.value); + await _prefs?.setBool(_followSystemKey, _followSystem.value); } /// 应用主题模式到 GetX @@ -142,6 +181,34 @@ class ThemeController extends GetxController { ); } + /// 切换跟随系统深色模式 + /// [enabled] true 跟随系统, false 手动控制 + Future toggleFollowSystem(bool enabled) async { + if (_followSystem.value == enabled) return; + + _followSystem.value = enabled; + + if (enabled) { + final isSystemDark = + SchedulerBinding.instance.platformDispatcher.platformBrightness == + Brightness.dark; + _isDarkMode.value = isSystemDark; + } + + await _saveThemeSettings(); + _applyThemeMode(); + + Get.snackbar( + '主题切换', + enabled ? '已开启跟随系统 🔄' : '已切换为手动控制 ✋', + snackPosition: SnackPosition.BOTTOM, + duration: const Duration(seconds: 2), + margin: const EdgeInsets.all(16), + borderRadius: 12, + colorText: currentThemeColor, + ); + } + /// 设置主题模式 Future setThemeMode(AppThemeMode mode) async { if (_themeMode.value == mode) return; @@ -257,6 +324,7 @@ class ThemeController extends GetxController { _fontSizeIndex.value = 1; _enableAnimation.value = true; _enableBlurEffect.value = true; + _followSystem.value = true; await _saveThemeSettings(); _applyThemeMode(); @@ -274,11 +342,11 @@ class ThemeController extends GetxController { /// 判断当前是否为深色模式(考虑系统设置) bool isDarkModeEffective(BuildContext context) { - if (_isDarkMode.value) return true; - if (_themeMode.value == AppThemeMode.dark) return true; - if (_themeMode.value == AppThemeMode.system) { + if (_followSystem.value) { return MediaQuery.platformBrightnessOf(context) == Brightness.dark; } + if (_isDarkMode.value) return true; + if (_themeMode.value == AppThemeMode.dark) return true; return false; } } diff --git a/lib/views/active/category_page.dart b/lib/views/active/category_page.dart index 3ea561e..936d60c 100644 --- a/lib/views/active/category_page.dart +++ b/lib/views/active/category_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../services/get/category_controller.dart'; import '../../services/get/theme_controller.dart'; diff --git a/lib/views/active/popular_page.dart b/lib/views/active/popular_page.dart index 7f294ca..bcc3746 100644 --- a/lib/views/active/popular_page.dart +++ b/lib/views/active/popular_page.dart @@ -1,6 +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'; import '../../models/poetry_model.dart'; diff --git a/lib/views/active/search/search_history_manager.dart b/lib/views/active/search/search_history_manager.dart index df8ef6e..62aaa33 100644 --- a/lib/views/active/search/search_history_manager.dart +++ b/lib/views/active/search/search_history_manager.dart @@ -1,7 +1,9 @@ -/// 时间: 2026-04-09 -/// 功能: 搜索历史管理器 -/// 介绍: 管理用户的搜索历史记录,支持添加、删除、清空等功能 -/// 最新变化: 新建搜索历史管理器 +// 时间: 2026-04-09 +// 功能: 搜索历史管理器 +// 介绍: 管理用户的搜索历史记录,支持添加、删除、清空等功能 +// 最新变化: 新建搜索历史管理器 + +import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -52,7 +54,7 @@ class SearchHistoryManager { .map((item) { try { return SearchHistoryItem.fromJson( - Map.from(_decodeJson(item)), + Map.from(json.decode(item) as Map), ); } catch (e) { return null; @@ -68,24 +70,6 @@ class SearchHistoryManager { } } - Map _decodeJson(String jsonString) { - final result = {}; - final parts = jsonString.substring(1, jsonString.length - 1).split(','); - for (final part in parts) { - final keyValue = part.split(':'); - if (keyValue.length >= 2) { - final key = keyValue[0].trim().replaceAll('"', ''); - final value = keyValue.sublist(1).join(':').trim().replaceAll('"', ''); - if (key == 'query') { - result[key] = value; - } else if (key == 'timestamp') { - result[key] = value; - } - } - } - return result; - } - Future addSearch(String query) async { final trimmedQuery = query.trim(); if (trimmedQuery.isEmpty) return; @@ -121,7 +105,7 @@ class SearchHistoryManager { try { final prefs = await SharedPreferences.getInstance(); final historyList = _history.map((item) { - return '{"query":"${item.query}","timestamp":"${item.timestamp.toIso8601String()}"}'; + return json.encode(item.toJson()); }).toList(); await prefs.setStringList(_searchHistoryKey, historyList); } catch (e) { diff --git a/lib/views/active/search/search_history_page.dart b/lib/views/active/search/search_history_page.dart index dd39736..bc13535 100644 --- a/lib/views/active/search/search_history_page.dart +++ b/lib/views/active/search/search_history_page.dart @@ -6,7 +6,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../../constants/app_constants.dart'; import '../../../../config/app_config.dart'; import '../../../../services/get/theme_controller.dart'; import 'search_history_manager.dart'; diff --git a/lib/views/active/tags/corr_page.dart b/lib/views/active/tags/corr_page.dart index cf08443..f21f62d 100644 --- a/lib/views/active/tags/corr_page.dart +++ b/lib/views/active/tags/corr_page.dart @@ -1,14 +1,14 @@ /// 时间: 2026-04-01 /// 功能: 标签/朝代诗词列表页面 /// 介绍: 展示指定标签或朝代相关的诗词列表,支持搜索和浏览 -/// 最新变化: 2026-04-02 支持深色模式 +/// 上次更新: 2026-04-18 修复点赞后数据不更新 library; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; import '../../../utils/http/http_client.dart'; +import '../../../utils/http/poetry_api.dart'; import '../../../controllers/history_controller.dart'; import '../../../services/network_listener_service.dart'; import '../../../services/get/theme_controller.dart'; @@ -185,24 +185,47 @@ class _CorrPageState extends State final poetryId = poetry['id'].toString(); final isLiked = await HistoryController.isInLiked(poetryId); - if (isLiked) { - await HistoryController.removeLikedPoetry(poetryId); + try { + final int id = int.tryParse(poetryId) ?? 0; + if (id > 0) { + await PoetryApi.toggleLike(id); + } + + if (isLiked) { + await HistoryController.removeLikedPoetry(poetryId); + final currentLike = (poetry['like'] as int?) ?? 0; + poetry['like'] = currentLike > 0 ? currentLike - 1 : 0; + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('已取消点赞'), + duration: Duration(seconds: 1), + ), + ); + } + } else { + await HistoryController.addToLiked(poetry); + poetry['like'] = ((poetry['like'] as int?) ?? 0) + 1; + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('已点赞'), + duration: Duration(seconds: 1), + ), + ); + } + } + } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('已取消点赞'), - duration: Duration(seconds: 1), + SnackBar( + content: Text('操作失败: $e'), + duration: const Duration(seconds: 1), ), ); } - } else { - await HistoryController.addToLiked(poetry); - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('已点赞'), duration: Duration(seconds: 1)), - ); - } } + if (mounted) { setState(() {}); } diff --git a/lib/views/discover_page.dart b/lib/views/discover_page.dart index 3b9f480..ee55f2f 100644 --- a/lib/views/discover_page.dart +++ b/lib/views/discover_page.dart @@ -453,7 +453,7 @@ class _DiscoverPageState extends State ), const SizedBox(height: 8), Text( - '统计开源:来自本软件各个平台的数据,安卓 鸿蒙 web 小程序等平台。', + '统计来源:来自本软件各个平台的数据,安卓 鸿蒙 web 小程序等平台。', style: TextStyle( fontSize: 12, color: isDark ? Colors.grey[400] : Colors.grey[600], diff --git a/lib/views/favorites_page.dart b/lib/views/favorites_page.dart index b17b483..f2798fa 100644 --- a/lib/views/favorites_page.dart +++ b/lib/views/favorites_page.dart @@ -14,7 +14,7 @@ import '../services/get/theme_controller.dart'; /// 时间: 2026-03-22 /// 功能: 收藏页面 /// 介绍: 展示用户收藏的内容,支持分类管理和搜索 -/// 最新变化: 笔记列表组件独立到 local_jilu.dart +/// 上次更新: 2026-04-18 修复搜索栏深色模式文字不可见,布局切换按钮响应 class FavoritesPage extends StatefulWidget { const FavoritesPage({super.key}); @@ -103,24 +103,24 @@ class _FavoritesPageState extends State 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, - color: isDark ? Colors.white70 : null, + Obx( + () => IconButton( + icon: Icon( + controller.isGridView.value ? Icons.view_list : Icons.grid_view, + color: isDark ? Colors.white70 : null, + ), + onPressed: controller.toggleViewMode, ), - onPressed: controller.toggleViewMode, ), IconButton( icon: Icon(Icons.filter_list, color: isDark ? Colors.white70 : null), onPressed: () { - // 使用 Get.context 而不是传递的 context if (Get.context != null) { controller.showFilterOptions(Get.context!); } @@ -145,6 +145,7 @@ class _FavoritesPageState extends State ), child: TextField( readOnly: true, + style: TextStyle(color: isDark ? Colors.white : Colors.black87), onTap: () { Get.to( ActiveSearchPage( diff --git a/lib/views/footprint/all_list.dart b/lib/views/footprint/all_list.dart index 96d19e6..425a410 100644 --- a/lib/views/footprint/all_list.dart +++ b/lib/views/footprint/all_list.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; import '../../controllers/history_controller.dart'; import '../../services/network_listener_service.dart'; @@ -178,7 +177,7 @@ class AllListPageState extends State { @override Widget build(BuildContext context) { final favoritesController = Get.find(); - + return Obx(() { final isDark = _themeController.isDarkMode; final themeColor = _themeController.currentThemeColor; @@ -198,7 +197,9 @@ class AllListPageState extends State { return RefreshIndicator( onRefresh: _loadAllData, - child: isGridView ? _buildGridView(isDark, themeColor) : _buildListView(isDark, themeColor), + child: isGridView + ? _buildGridView(isDark, themeColor) + : _buildListView(isDark, themeColor), ); }); } @@ -364,7 +365,6 @@ class AllListPageState extends State { Widget _buildGridNoteCard(Map note, bool isDark) { final title = note['title'] as String? ?? ''; final content = note['content'] as String? ?? ''; - final category = note['category'] as String? ?? ''; final isPinned = note['isPinned'] == true; final isLocked = note['isLocked'] == true; @@ -421,14 +421,18 @@ class AllListPageState extends State { Icon( Icons.note_outlined, size: 10, - color: isDark ? Colors.orange[300] : Colors.orange[700], + color: isDark + ? Colors.orange[300] + : Colors.orange[700], ), const SizedBox(width: 2), Text( '笔记', style: TextStyle( fontSize: 9, - color: isDark ? Colors.orange[300] : Colors.orange[700], + color: isDark + ? Colors.orange[300] + : Colors.orange[700], fontWeight: FontWeight.w500, ), ), @@ -440,13 +444,17 @@ class AllListPageState extends State { Icon( Icons.push_pin, size: 12, - color: isDark ? Colors.orange[300] : Colors.orange[700], + color: isDark + ? Colors.orange[300] + : Colors.orange[700], ), if (isLocked) Icon( Icons.lock, size: 12, - color: isDark ? Colors.orange[300] : Colors.orange[700], + color: isDark + ? Colors.orange[300] + : Colors.orange[700], ), ], ), @@ -471,9 +479,7 @@ class AllListPageState extends State { '${note['charCount'] ?? displayText.length} 字', style: TextStyle( fontSize: 10, - color: isDark - ? Colors.grey[400] - : Colors.grey[500], + color: isDark ? Colors.grey[400] : Colors.grey[500], ), ), ], @@ -489,9 +495,8 @@ class AllListPageState extends State { child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: Container( - color: (isDark ? Colors.black : Colors.white).withValues( - alpha: 0.4, - ), + color: (isDark ? Colors.black : Colors.white) + .withValues(alpha: 0.4), child: Center( child: Icon( Icons.lock, diff --git a/lib/views/footprint/collect_notes.dart b/lib/views/footprint/collect_notes.dart index 49f06ca..d1512ff 100644 --- a/lib/views/footprint/collect_notes.dart +++ b/lib/views/footprint/collect_notes.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../controllers/history_controller.dart'; import '../../services/network_listener_service.dart'; import '../../services/get/theme_controller.dart'; diff --git a/lib/views/footprint/liked_poetry_manager.dart b/lib/views/footprint/liked_poetry_manager.dart index 6cd5569..6ef8605 100644 --- a/lib/views/footprint/liked_poetry_manager.dart +++ b/lib/views/footprint/liked_poetry_manager.dart @@ -1,7 +1,7 @@ /// 时间: 2025-03-22 /// 功能: 点赞诗词管理器 /// 介绍: 管理点赞诗词的加载、显示、删除等操作 -/// 最新变化: 从FavoritesPage分离出来的点赞管理逻辑,添加底部内边距适配液态玻璃导航栏 +/// 上次更新: 2026-04-18 修复详情刷新按钮显示开发中、支持深色模式 library liked_poetry_manager; @@ -32,12 +32,11 @@ class LikedPoetryManager extends StatefulWidget { PoetryData poetry, ) async { try { - debugPrint( - 'DEBUG: LikedPoetryManager - 点击查看详情 - Poetry ID: ${poetry.id}', - ); + final themeController = Get.find(); + final isDark = themeController.isDarkMode; + final themeColor = themeController.currentThemeColor; final likedList = await HistoryController.getLikedHistory(); - debugPrint('DEBUG: LikedPoetryManager - 获取到 ${likedList.length} 条点赞记录'); Map poetryData; try { @@ -45,177 +44,216 @@ class LikedPoetryManager extends StatefulWidget { (item) => item['id'].toString() == poetry.id.toString(), orElse: () => poetry.toJson(), ); - debugPrint('DEBUG: LikedPoetryManager - 找到匹配的诗词数据'); } catch (e) { - debugPrint('DEBUG: LikedPoetryManager - 未找到匹配数据,使用当前poetry数据'); poetryData = poetry.toJson(); } - debugPrint( - 'DEBUG: LikedPoetryManager - 诗词数据字段: ${poetryData.keys.toList()}', - ); - if (context.mounted) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, - builder: (context) => Container( - height: MediaQuery.of(context).size.height * 0.8, - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), - ), - ), - child: Column( - children: [ - Container( - margin: const EdgeInsets.only(top: 8), - width: 40, - height: 4, + builder: (context) { + return StatefulBuilder( + builder: (context, setSheetState) { + return Container( + height: MediaQuery.of(context).size.height * 0.8, decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(2), + color: isDark ? const Color(0xFF1E1E1E) : Colors.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), ), - ), - Padding( - padding: const EdgeInsets.all(16), - child: Row( + child: Column( children: [ - Icon( - Icons.article, - color: AppConstants.primaryColor, - size: 24, - ), - const SizedBox(width: 8), - const Text( - '诗词详情', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, + Container( + margin: const EdgeInsets.only(top: 8), + width: 40, + height: 4, + decoration: BoxDecoration( + color: isDark ? Colors.grey[600] : Colors.grey[300], + borderRadius: BorderRadius.circular(2), ), ), - const Spacer(), - GestureDetector( - onTap: () { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('开发中'), - duration: Duration(seconds: 1), + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Icon(Icons.article, color: themeColor, size: 24), + const SizedBox(width: 8), + Text( + '诗词详情', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black87, + ), ), - ); - }, - child: Container( - padding: const EdgeInsets.all(8), - child: Icon( - Icons.refresh, - color: Colors.grey[600], - size: 20, + const Spacer(), + GestureDetector( + onTap: () async { + setSheetState(() {}); + try { + final freshList = + await HistoryController.getLikedHistory(); + final freshData = freshList.firstWhere( + (item) => + item['id'].toString() == + poetry.id.toString(), + orElse: () => poetryData, + ); + setSheetState(() { + poetryData = freshData; + }); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('已刷新'), + duration: const Duration(seconds: 1), + backgroundColor: themeColor, + ), + ); + } + } catch (e) { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('刷新失败: $e'), + duration: const Duration(seconds: 1), + backgroundColor: Colors.red, + ), + ); + } + } + }, + child: Container( + padding: const EdgeInsets.all(8), + child: Icon( + Icons.refresh, + color: isDark + ? Colors.grey[400] + : Colors.grey[600], + size: 20, + ), + ), + ), + const SizedBox(width: 8), + IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon(Icons.close), + color: isDark + ? Colors.grey[400] + : Colors.grey[600], + ), + ], + ), + ), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildDetailCard( + '精选诗句', + poetryData['name'] ?? poetry.name, + Icons.format_quote, + themeColor, + isDark, + ), + Row( + children: [ + if (poetryData['liked_time'] != null) ...[ + Expanded( + child: _buildDetailCard( + '点赞时间', + '${poetryData['liked_date'] ?? ''} ${poetryData['liked_time'] ?? ''}', + Icons.favorite, + Colors.orange, + isDark, + ), + ), + ], + if (poetryData['keywords'] != null && + poetryData['keywords'] + .toString() + .isNotEmpty) ...[ + const SizedBox(width: 8), + Expanded( + child: _buildDetailCard( + '标签', + poetryData['keywords'], + Icons.local_offer, + Colors.green, + isDark, + ), + ), + ], + ], + ), + Row( + children: [ + if (poetryData['alias'] != null && + poetryData['alias'] + .toString() + .isNotEmpty) ...[ + Expanded( + child: _buildDetailCard( + '出处', + poetryData['url'], + Icons.link, + Colors.teal, + isDark, + ), + ), + ], + if (poetryData['url'] != null && + poetryData['url'] + .toString() + .isNotEmpty) ...[ + const SizedBox(width: 8), + Expanded( + child: _buildDetailCard( + '朝代', + poetryData['alias'], + Icons.history, + Colors.blue, + isDark, + ), + ), + ], + ], + ), + if (poetryData['introduce'] != null && + poetryData['introduce'].toString().isNotEmpty) + _buildDetailCard( + '译文/介绍', + poetryData['introduce'], + Icons.translate, + themeColor, + isDark, + ), + if (poetryData['drtime'] != null && + poetryData['drtime'].toString().isNotEmpty) + _buildDetailCard( + '原文or赏析', + poetryData['drtime'], + Icons.menu_book, + Colors.purple, + isDark, + ), + const SizedBox(height: 20), + ], ), ), ), - const SizedBox(width: 8), - IconButton( - onPressed: () => Navigator.of(context).pop(), - icon: const Icon(Icons.close), - color: Colors.grey[600], - ), ], ), - ), - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildDetailCard( - '精选诗句', - poetryData['name'] ?? poetry.name, - Icons.format_quote, - AppConstants.primaryColor, - ), - Row( - children: [ - if (poetryData['liked_time'] != null) ...[ - Expanded( - child: _buildDetailCard( - '点赞时间', - '${poetryData['liked_date'] ?? ''} ${poetryData['liked_time'] ?? ''}', - Icons.favorite, - Colors.orange, - ), - ), - ], - if (poetryData['keywords'] != null && - poetryData['keywords'] - .toString() - .isNotEmpty) ...[ - const SizedBox(width: 8), - Expanded( - child: _buildDetailCard( - '标签', - poetryData['keywords'], - Icons.local_offer, - Colors.green, - ), - ), - ], - ], - ), - Row( - children: [ - if (poetryData['alias'] != null && - poetryData['alias'].toString().isNotEmpty) ...[ - Expanded( - child: _buildDetailCard( - '出处', - poetryData['url'], - Icons.link, - Colors.teal, - ), - ), - ], - if (poetryData['url'] != null && - poetryData['url'].toString().isNotEmpty) ...[ - const SizedBox(width: 8), - Expanded( - child: _buildDetailCard( - '朝代', - poetryData['alias'], - Icons.history, - Colors.blue, - ), - ), - ], - ], - ), - if (poetryData['introduce'] != null && - poetryData['introduce'].toString().isNotEmpty) - _buildDetailCard( - '译文/介绍', - poetryData['introduce'], - Icons.translate, - AppConstants.primaryColor, - ), - if (poetryData['drtime'] != null && - poetryData['drtime'].toString().isNotEmpty) - _buildDetailCard( - '原文or赏析', - poetryData['drtime'], - Icons.menu_book, - Colors.purple, - ), - const SizedBox(height: 20), - ], - ), - ), - ), - ], - ), - ), + ); + }, + ); + }, ); } } catch (e) { @@ -238,12 +276,15 @@ class LikedPoetryManager extends StatefulWidget { String content, IconData icon, Color accentColor, + bool isDark, ) { return Container( width: double.infinity, margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( - color: accentColor.withValues(alpha: 0.05), + color: isDark + ? accentColor.withValues(alpha: 0.12) + : accentColor.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(12), border: Border.all(color: accentColor.withValues(alpha: 0.2), width: 1), ), @@ -253,7 +294,9 @@ class LikedPoetryManager extends StatefulWidget { Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: accentColor.withValues(alpha: 0.1), + color: isDark + ? accentColor.withValues(alpha: 0.18) + : accentColor.withValues(alpha: 0.1), borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), @@ -278,9 +321,9 @@ class LikedPoetryManager extends StatefulWidget { padding: const EdgeInsets.all(12), child: Text( content, - style: const TextStyle( + style: TextStyle( fontSize: 15, - color: Colors.black87, + color: isDark ? Colors.white70 : Colors.black87, height: 1.5, ), ), diff --git a/lib/views/footprint/load/notice-page.dart b/lib/views/footprint/load/notice-page.dart index 2638978..e0da870 100644 --- a/lib/views/footprint/load/notice-page.dart +++ b/lib/views/footprint/load/notice-page.dart @@ -3,8 +3,6 @@ /// 介绍: 显示系统公告列表,支持下拉刷新 /// 最新变化: 添加底部"到底了"提示,防止被底部 tabs 遮住 -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; diff --git a/lib/views/footprint/local_jilu.dart b/lib/views/footprint/local_jilu.dart index c1581ca..8173a5c 100644 --- a/lib/views/footprint/local_jilu.dart +++ b/lib/views/footprint/local_jilu.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; import 'collect_notes.dart'; import '../../controllers/history_controller.dart'; @@ -157,7 +156,6 @@ class _LocalNotesListState extends State { final title = note['title'] as String? ?? ''; final content = note['content'] as String? ?? ''; final timeStr = note['time'] as String? ?? ''; - final createTimeStr = note['createTime'] as String? ?? ''; final category = note['category'] as String? ?? ''; final isPinned = note['isPinned'] == true; final isLocked = note['isLocked'] == true; diff --git a/lib/views/home/care/care-page.dart b/lib/views/home/care/care-page.dart index dca170d..b8963ee 100644 --- a/lib/views/home/care/care-page.dart +++ b/lib/views/home/care/care-page.dart @@ -17,7 +17,6 @@ class CarePage extends StatefulWidget { class _CarePageState extends State { final CareController _careController = Get.find(); - bool _readAloudEnabled = false; final List _options = ['诗词', '出处', '译文', '更多', '原文', '问候语']; @override diff --git a/lib/views/home/care/care_poetry_page.dart b/lib/views/home/care/care_poetry_page.dart index 58abba6..3b92d47 100644 --- a/lib/views/home/care/care_poetry_page.dart +++ b/lib/views/home/care/care_poetry_page.dart @@ -8,8 +8,6 @@ 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 '../components/skeleton_widgets.dart'; import 'care_widgets.dart'; import 'pinyin_helper.dart'; @@ -334,7 +332,6 @@ class _CarePoetryPageState extends State : 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), @@ -615,7 +612,6 @@ class _CarePoetryPageState extends State 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), diff --git a/lib/views/home/home_page.dart b/lib/views/home/home_page.dart index 49350e2..d98cd98 100644 --- a/lib/views/home/home_page.dart +++ b/lib/views/home/home_page.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; import '../../../services/get/home_controller.dart'; import '../../../services/get/theme_controller.dart'; diff --git a/lib/views/home/home_part.dart b/lib/views/home/home_part.dart index a83fd32..6a76cba 100644 --- a/lib/views/home/home_part.dart +++ b/lib/views/home/home_part.dart @@ -6,7 +6,6 @@ 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'; @@ -490,6 +489,13 @@ class _PoetryCardState extends State { '关键词', isDark: isDark, ), + onTap: () => Get.toNamed( + '/corrPage', + arguments: { + 'label': keyword, + 'searchType': 'keywords', + }, + ), child: Container( padding: const EdgeInsets.symmetric( horizontal: 8, @@ -523,6 +529,13 @@ class _PoetryCardState extends State { '朝代', isDark: isDark, ), + onTap: () => Get.toNamed( + '/corrPage', + arguments: { + 'label': widget.poetryData.alias, + 'searchType': 'alias', + }, + ), child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, diff --git a/lib/views/home/set/home-load.dart b/lib/views/home/set/home-load.dart index a93ba29..e530f22 100644 --- a/lib/views/home/set/home-load.dart +++ b/lib/views/home/set/home-load.dart @@ -4,13 +4,10 @@ /// 最新变化: 新建文件 import 'dart:async'; -import 'dart:ui' as ui; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../../utils/http/poetry_api.dart'; -import '../../../../constants/app_constants.dart'; class SecondaryButtonsManager { static const String _hideSecondaryButtonsKey = 'hide_secondary_buttons'; diff --git a/lib/views/profile/app-info.dart b/lib/views/profile/app-info.dart index 4ea09f9..26510b5 100644 --- a/lib/views/profile/app-info.dart +++ b/lib/views/profile/app-info.dart @@ -6,8 +6,6 @@ import 'package:get/get.dart'; 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 '../../../controllers/settings/is_platform.dart'; import '../../../services/get/theme_controller.dart'; @@ -780,6 +778,15 @@ class _AppInfoPageState extends State { ) ?? 'Unknown'; + String renderEngine = 'Skia'; + try { + renderEngine = const bool.fromEnvironment('FLUTTER_IMPELLER') + ? 'Impeller' + : 'Skia'; + } catch (_) { + renderEngine = 'Skia'; + } + return Container( decoration: BoxDecoration( color: isDark ? const Color(0xFF2A2A2A) : Colors.white, @@ -869,6 +876,13 @@ class _AppInfoPageState extends State { isDark, primaryColor, ), + _buildGridInfoItem( + '渲染引擎', + renderEngine, + Icons.precision_manufacturing, + isDark, + primaryColor, + ), _buildGridCopyableItem( context, 'Flutter UUID', @@ -992,14 +1006,14 @@ class _AppInfoPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildUpdateItem('版本 1.4.9', '2026-04-10', [ - '新增布局切换、答题骨架屏、搜索历史、个性化等功能', - '优化消息提示、公告页面、平台适配与多项修复', + _buildUpdateItem('版本 1.6.0', '2026-04-18', [ + '代码质量优化与清理', + '新增项目分析与标签跳转功能', ], isDark), const SizedBox(height: 16), - _buildUpdateItem('版本 1.4.3', '2026-04-04', [ - '新增平台判断工具类、动态版本号、Web图标替换', - '修复部分接口失效等问题', + _buildUpdateItem('版本 1.5.8', '2026-04-12', [ + '跟随系统深色模式', + '布局切换与搜索历史等体验优化', ], isDark), ], ), @@ -1084,67 +1098,6 @@ class _AppInfoPageState extends State { ); } - Widget _buildDesignStyleCard(bool isDark) { - final platform = Platform.instance; - final String designStyle = - platform.when( - material: () => 'Material Design', - cupertino: () => 'Cupertino Design', - orElse: () => null, - ) ?? - 'Unknown'; - - return Container( - decoration: BoxDecoration( - color: isDark ? const Color(0xFF2A2A2A) : Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: isDark - ? Colors.black.withValues(alpha: 0.3) - : Colors.black.withValues(alpha: 0.05), - blurRadius: 10, - offset: const Offset(0, 2), - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.pink.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - ), - child: Icon(Icons.palette, color: Colors.pink[700], size: 20), - ), - const SizedBox(width: 12), - Text( - '设计风格', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black, - ), - ), - ], - ), - ), - Divider(height: 1, color: isDark ? Colors.grey[800] : null), - _buildInfoItem('当前风格', designStyle, Icons.style, isDark), - _buildInfoItem('设计语言', 'Flutter', Icons.design_services, isDark), - _buildInfoItem('交互模式', '触摸优先', Icons.touch_app, isDark), - ], - ), - ); - } - - // 2x2 网格技术栈项 Widget _buildTechStackItem( String title, String value, diff --git a/lib/views/profile/components/entire_page.dart b/lib/views/profile/components/entire_page.dart index e7e8824..7610f54 100644 --- a/lib/views/profile/components/entire_page.dart +++ b/lib/views/profile/components/entire_page.dart @@ -26,6 +26,7 @@ class _EntirePageState extends State final ThemeController _themeController = Get.find(); Map? _statsData; String? _errorMessage; + bool _isLoading = false; late AnimationController _animationController; late Animation _fadeAnimation; @@ -50,12 +51,14 @@ class _EntirePageState extends State } Future _loadStatsData() async { - if (!mounted) return; + if (!mounted || _isLoading) return; setState(() { _errorMessage = null; + _isLoading = true; }); + _animationController.reset(); startNetworkLoading('stats'); try { @@ -67,6 +70,7 @@ class _EntirePageState extends State setState(() { _statsData = response.jsonData['data'] as Map; }); + _animationController.forward(); sendRefreshEvent(); } else { setState(() { @@ -80,6 +84,11 @@ class _EntirePageState extends State _errorMessage = '网络错误:$e'; }); } finally { + if (mounted) { + setState(() { + _isLoading = false; + }); + } endNetworkLoading('stats'); } } @@ -492,11 +501,24 @@ class _EntirePageState extends State ), ), const Spacer(), - IconButton( - icon: const Icon(Icons.refresh, color: Colors.white, size: 22), - onPressed: _loadStatsData, - tooltip: '刷新数据', - ), + _isLoading + ? const SizedBox( + width: 22, + height: 22, + child: CircularProgressIndicator( + color: Colors.white, + strokeWidth: 2, + ), + ) + : IconButton( + icon: const Icon( + Icons.refresh, + color: Colors.white, + size: 22, + ), + onPressed: _loadStatsData, + tooltip: '刷新数据', + ), ], ), const SizedBox(height: 12), diff --git a/lib/views/profile/components/jinrishici_sdk_page.dart b/lib/views/profile/components/jinrishici_sdk_page.dart index 8bd03dc..eca4f69 100644 --- a/lib/views/profile/components/jinrishici_sdk_page.dart +++ b/lib/views/profile/components/jinrishici_sdk_page.dart @@ -10,7 +10,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../../../models/scenario/jinrishici_sdk_config.dart'; -import '../../../models/colors/app_colors.dart'; import '../../../services/get/theme_controller.dart'; import '../../../services/jinrishici_service.dart'; diff --git a/lib/views/profile/components/login_register_dialog.dart b/lib/views/profile/components/login_register_dialog.dart index c7aa648..32ad7c3 100644 --- a/lib/views/profile/components/login_register_dialog.dart +++ b/lib/views/profile/components/login_register_dialog.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.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 { @@ -19,7 +18,6 @@ class LoginRegisterDialog extends StatefulWidget { } class _LoginRegisterDialogState extends State { - final ThemeController _themeController = Get.find(); final _formKey = GlobalKey(); final _usernameController = TextEditingController(); bool _isLoading = false; @@ -112,7 +110,6 @@ class _LoginRegisterDialogState extends State { @override Widget build(BuildContext context) { return Obx(() { - final isDark = _themeController.isDarkMode; return Dialog( backgroundColor: AppColors.surface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), @@ -140,10 +137,7 @@ class _LoginRegisterDialogState extends State { ), Text( '微信号或手机号或邮箱作为投票凭证,\n任何人都可以填写,限时开放投票,\n投票凭证仅用于投票,不会泄露隐私.\n结束后删除会所有凭证,仅保留投票结果', - style: TextStyle( - fontSize: 14, - color: AppColors.secondaryText, - ), + style: TextStyle(fontSize: 14, color: AppColors.secondaryText), textAlign: TextAlign.center, ), const SizedBox(height: 2), @@ -168,7 +162,10 @@ class _LoginRegisterDialogState extends State { focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: AppColors.primary), ), - prefixIcon: Icon(Icons.person, color: AppColors.primary), + prefixIcon: Icon( + Icons.person, + color: AppColors.primary, + ), ), validator: _validateUsername, ), diff --git a/lib/views/profile/components/pop-menu.dart b/lib/views/profile/components/pop-menu.dart index 33a7ef6..95343e0 100644 --- a/lib/views/profile/components/pop-menu.dart +++ b/lib/views/profile/components/pop-menu.dart @@ -7,7 +7,6 @@ import '../../../services/isweb/wakelock_service.dart'; import '../../../services/get/theme_controller.dart'; import '../../../controllers/settings/is_platform.dart'; import '../guide/beginner_page.dart'; -import 'jinrishici_sdk_page.dart'; import '../../home/care/care-page.dart'; class PopMenu extends StatelessWidget { @@ -31,16 +30,7 @@ class PopMenu extends StatelessWidget { static Future shareApp(BuildContext context) async { try { const String shareText = '情景诗词App - 一款优雅的诗词学习应用,包含丰富的诗词内容和答题功能'; - - final result = await Share.shareWithResult(shareText, subject: '情景诗词App'); - - if (result.status == ShareResultStatus.success) { - if (context.mounted) { - ScaffoldMessenger.of( - context, - ).showSnackBar(const SnackBar(content: Text('分享成功!'))); - } - } + await Share.share(shareText, subject: '情景诗词App'); } catch (e) { if (context.mounted) { ScaffoldMessenger.of( diff --git a/lib/views/profile/components/server_info_dialog.dart b/lib/views/profile/components/server_info_dialog.dart index fe48d5f..52ecb53 100644 --- a/lib/views/profile/components/server_info_dialog.dart +++ b/lib/views/profile/components/server_info_dialog.dart @@ -3,7 +3,6 @@ library; import 'package:flutter/material.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}) { @@ -15,13 +14,10 @@ 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 Obx(() { - final isDark = themeController.isDarkMode; return Dialog( backgroundColor: AppColors.surface, shape: RoundedRectangleBorder( @@ -191,10 +187,12 @@ class ServerInfoDialog { ), decoration: BoxDecoration( color: isOnline - ? AppColors.iosGreen - .withValues(alpha: 0.1) - : AppColors.iosRed - .withValues(alpha: 0.1), + ? AppColors.iosGreen.withValues( + alpha: 0.1, + ) + : AppColors.iosRed.withValues( + alpha: 0.1, + ), borderRadius: BorderRadius.circular( 8, ), @@ -284,10 +282,7 @@ class ServerInfoDialog { children: [ Text( title, - style: TextStyle( - fontSize: 12, - color: AppColors.tertiaryText, - ), + style: TextStyle(fontSize: 12, color: AppColors.tertiaryText), ), const SizedBox(height: 2), Text( diff --git a/lib/views/profile/expand/manu-script.dart b/lib/views/profile/expand/manu-script.dart index aa8b60f..b5119cd 100644 --- a/lib/views/profile/expand/manu-script.dart +++ b/lib/views/profile/expand/manu-script.dart @@ -30,7 +30,6 @@ class _ManuscriptPageState extends State { List> _categories = []; String? _selectedCategory; - bool _isLoadingCategories = true; bool _isCheckingName = false; bool _isSubmitting = false; @@ -70,18 +69,14 @@ class _ManuscriptPageState extends State { if (data['ok'] == true && data['categories'] != null) { setState(() { _categories = List>.from(data['categories']); - _isLoadingCategories = false; }); } else { - setState(() => _isLoadingCategories = false); _showSnackBar('加载分类失败', isError: true); } } else { - setState(() => _isLoadingCategories = false); _showSnackBar('加载分类失败', isError: true); } } catch (e) { - setState(() => _isLoadingCategories = false); _showSnackBar('网络请求失败: $e', isError: true); } } diff --git a/lib/views/profile/guide/app-data.dart b/lib/views/profile/guide/app-data.dart index f0d3423..65af473 100644 --- a/lib/views/profile/guide/app-data.dart +++ b/lib/views/profile/guide/app-data.dart @@ -1,10 +1,13 @@ +import 'dart:convert'; import 'dart:io'; +import 'package:file_picker_ohos/file_picker_ohos.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:path_provider/path_provider.dart'; -import '../../../constants/app_constants.dart'; +import 'package:share_plus/share_plus.dart'; +import '../../../config/app_config.dart'; import '../../../services/get/theme_controller.dart'; import '../../../controllers/settings/is_platform.dart'; @@ -89,8 +92,8 @@ class _AppDataPageState extends State { try { int totalSize = 0; final tempDir = await getTemporaryDirectory(); - final appDocDir = await getApplicationDocumentsDirectory(); - final supportDir = await getApplicationSupportDirectory(); + await getApplicationDocumentsDirectory(); + await getApplicationSupportDirectory(); final parentDir = tempDir.parent; if (await parentDir.exists()) { @@ -383,25 +386,334 @@ class _AppDataPageState extends State { } } - Future _exportData() async { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: const Text('数据导出功能开发中...'), - backgroundColor: Colors.grey[600], - ), + Future _showConfigDetails() async { + try { + final prefs = await SharedPreferences.getInstance(); + final keys = prefs.getKeys().toList()..sort(); + + if (keys.isEmpty) { + if (mounted) { + ScaffoldMessenger.of( + context, + ).showSnackBar(const SnackBar(content: Text('暂无配置数据'))); + } + return; + } + + if (!mounted) return; + + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) { + final isDark = _themeController.isDarkMode; + final primaryColor = _themeController.currentThemeColor; + + return Container( + height: MediaQuery.of(context).size.height * 0.75, + decoration: BoxDecoration( + color: isDark ? const Color(0xFF2A2A2A) : Colors.white, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + child: Column( + children: [ + Container( + width: 40, + height: 4, + margin: const EdgeInsets.only(top: 12, bottom: 8), + decoration: BoxDecoration( + color: isDark ? Colors.grey[600] : Colors.grey[300], + borderRadius: BorderRadius.circular(2), + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + child: Row( + children: [ + Icon(Icons.list_alt, color: primaryColor), + const SizedBox(width: 8), + Text( + '配置详情 (${keys.length}项)', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: isDark ? Colors.white : Colors.black, + ), + ), + const Spacer(), + IconButton( + icon: Icon(Icons.copy, color: primaryColor, size: 20), + onPressed: () async { + final buffer = StringBuffer(); + for (final key in keys) { + buffer.writeln('$key = ${prefs.get(key)}'); + } + await Clipboard.setData( + ClipboardData(text: buffer.toString()), + ); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('已复制到剪贴板')), + ); + } + }, + ), + ], + ), + ), + const Divider(height: 1), + Expanded( + child: ListView.separated( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: keys.length, + separatorBuilder: (_, __) => Divider( + height: 1, + indent: 16, + color: isDark ? Colors.grey[700] : Colors.grey[200], + ), + itemBuilder: (context, index) { + final key = keys[index]; + final value = prefs.get(key); + final typeLabel = value is bool + ? 'bool' + : value is int + ? 'int' + : value is double + ? 'double' + : value is String + ? 'String' + : value is List + ? 'List' + : 'unknown'; + + return ListTile( + dense: true, + title: Text( + key, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: isDark ? Colors.white70 : Colors.black87, + ), + ), + subtitle: Text( + '$value', + style: TextStyle( + fontSize: 12, + color: isDark ? Colors.grey[400] : Colors.grey[600], + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + trailing: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 2, + ), + decoration: BoxDecoration( + color: primaryColor.withAlpha(20), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + typeLabel, + style: TextStyle(fontSize: 10, color: primaryColor), + ), + ), + ); + }, + ), + ), + ], + ), + ); + }, ); + } catch (e) { + debugPrint('查看配置详情失败: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('加载失败: $e'), backgroundColor: Colors.red), + ); + } + } + } + + Future _exportData() async { + try { + final prefs = await SharedPreferences.getInstance(); + final keys = prefs.getKeys().toList(); + + final Map exportData = { + 'app': '情景诗词', + 'version': AppConfig.appVersion, + 'exportTime': DateTime.now().toIso8601String(), + 'preferences': {}, + }; + + for (final key in keys) { + final value = prefs.get(key); + exportData['preferences'][key] = value; + } + + final jsonString = const JsonEncoder.withIndent(' ').convert(exportData); + final timestamp = DateTime.now().millisecondsSinceEpoch; + final fileName = 'poetry_backup_$timestamp.json'; + + final dir = await getApplicationDocumentsDirectory(); + final file = File('${dir.path}/$fileName'); + await file.writeAsString(jsonString); + + if (mounted) { + final result = await Share.shareXFiles( + [XFile(file.path)], + subject: '情景诗词数据备份', + text: '情景诗词数据备份 - ${DateTime.now().toString().substring(0, 19)}', + ); + + if (result.status == ShareResultStatus.success && mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('数据已导出,共 ${keys.length} 项配置'), + backgroundColor: _themeController.currentThemeColor, + ), + ); + } + } + } catch (e) { + debugPrint('导出数据失败: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('导出失败: $e'), backgroundColor: Colors.red), + ); + } } } Future _importData() async { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: const Text('数据导入功能开发中...'), - backgroundColor: Colors.grey[600], - ), + try { + final result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['json'], + dialogTitle: '选择情景诗词备份文件', ); + + if (result == null || result.files.isEmpty) return; + + final filePath = result.files.single.path; + if (filePath == null) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('无法获取文件路径'), + backgroundColor: Colors.red, + ), + ); + } + return; + } + + final file = File(filePath); + final jsonString = await file.readAsString(); + + final Map importData; + try { + importData = jsonDecode(jsonString) as Map; + } catch (_) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('文件格式错误,请选择有效的备份文件'), + backgroundColor: Colors.red, + ), + ); + } + return; + } + + if (importData['app'] != '情景诗词') { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('不是情景诗词的备份文件'), + backgroundColor: Colors.red, + ), + ); + } + return; + } + + final preferences = importData['preferences'] as Map?; + if (preferences == null || preferences.isEmpty) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('备份文件中没有数据'), + backgroundColor: Colors.orange, + ), + ); + } + return; + } + + final confirmed = await _showConfirmDialog( + '导入数据', + '即将导入 ${preferences.length} 项配置数据\n\n' + '备份版本: ${importData['version'] ?? '未知'}\n' + '备份时间: ${importData['exportTime'] ?? '未知'}\n\n' + '导入将覆盖现有同名配置项,是否继续?', + ); + + if (confirmed != true) return; + + final prefs = await SharedPreferences.getInstance(); + int importedCount = 0; + + for (final entry in preferences.entries) { + final key = entry.key; + final value = entry.value; + + if (value is bool) { + await prefs.setBool(key, value); + importedCount++; + } else if (value is int) { + await prefs.setInt(key, value); + importedCount++; + } else if (value is double) { + await prefs.setDouble(key, value); + importedCount++; + } else if (value is String) { + await prefs.setString(key, value); + importedCount++; + } else if (value is List) { + await prefs.setStringList(key, value.cast()); + importedCount++; + } + } + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('成功导入 $importedCount 项配置数据'), + backgroundColor: _themeController.currentThemeColor, + duration: const Duration(seconds: 3), + ), + ); + + await _loadDataInfo(); + } + } catch (e) { + debugPrint('导入数据失败: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('导入失败: $e'), backgroundColor: Colors.red), + ); + } } } @@ -678,7 +990,7 @@ class _AppDataPageState extends State { '查看所有存储的配置项', Icons.list_alt, Colors.green, - () => _showSnackBar('功能开发中...'), + _showConfigDetails, ), ], ), diff --git a/lib/views/profile/guide/beginner_page.dart b/lib/views/profile/guide/beginner_page.dart index a0802ca..c69eb26 100644 --- a/lib/views/profile/guide/beginner_page.dart +++ b/lib/views/profile/guide/beginner_page.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; import '../../../services/get/theme_controller.dart'; import 'sp-guide.dart'; diff --git a/lib/views/profile/guide/permission.dart b/lib/views/profile/guide/permission.dart index 052a16a..6ca32f0 100644 --- a/lib/views/profile/guide/permission.dart +++ b/lib/views/profile/guide/permission.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../../../constants/app_constants.dart'; import '../../../controllers/settings/is_platform.dart'; import '../../../services/get/theme_controller.dart'; import '../../../controllers/settings/suggestions.dart'; diff --git a/lib/views/profile/guide/sp-guide.dart b/lib/views/profile/guide/sp-guide.dart index e12ea22..73fb4b1 100644 --- a/lib/views/profile/guide/sp-guide.dart +++ b/lib/views/profile/guide/sp-guide.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../../../constants/app_constants.dart'; import '../../../config/app_config.dart'; import '../../../services/get/theme_controller.dart'; import '../settings/privacy.dart'; @@ -29,8 +28,6 @@ class _SpGuidePageState extends State final ThemeController _themeController = Get.find(); TabController? _tabController; int _currentPage = 0; - bool _firstLaunch = true; - bool _showGuideOnStartup = false; bool _agreementAccepted = false; bool _userPlanJoined = false; @@ -62,23 +59,12 @@ class _SpGuidePageState extends State Future _loadSettings() async { final prefs = await SharedPreferences.getInstance(); setState(() { - _firstLaunch = prefs.getBool(AppConfig.keyFirstLaunch) ?? true; - _showGuideOnStartup = - prefs.getBool(AppConfig.keyShowGuideOnStartup) ?? false; _agreementAccepted = prefs.getBool(AppConfig.keyAgreementAccepted) ?? false; _userPlanJoined = prefs.getBool(AppConfig.keyUserPlanJoined) ?? false; }); } - Future _toggleShowGuide(bool value) async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setBool(AppConfig.keyShowGuideOnStartup, value); - setState(() { - _showGuideOnStartup = value; - }); - } - Future _toggleUserPlan(bool value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(AppConfig.keyUserPlanJoined, value); @@ -93,7 +79,6 @@ class _SpGuidePageState extends State await prefs.setBool(AppConfig.keyFirstLaunch, false); setState(() { _agreementAccepted = true; - _firstLaunch = false; }); } @@ -490,117 +475,6 @@ class _SpGuidePageState extends State ); } - void _showGuideStatusPopup(bool isDark) { - showDialog( - context: context, - builder: (context) => Dialog( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - child: Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: isDark ? const Color(0xFF1A1A1A) : Colors.white, - borderRadius: BorderRadius.circular(16), - boxShadow: [ - BoxShadow( - color: isDark - ? Colors.black.withValues(alpha: 0.3) - : Colors.black.withValues(alpha: 0.15), - blurRadius: 20, - offset: const Offset(0, 4), - ), - ], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - Icon( - _showGuideOnStartup - ? Icons.check_circle - : Icons.info_outline, - color: _showGuideOnStartup - ? _themeController.currentThemeColor - : (isDark ? Colors.grey[400] : Colors.grey[600]), - size: 24, - ), - const SizedBox(width: 8), - Text( - '通知设置', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: isDark ? Colors.white : Colors.black87, - ), - ), - ], - ), - const SizedBox(height: 16), - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: _showGuideOnStartup - ? _themeController.currentThemeColor.withAlpha(10) - : (isDark ? const Color(0xFF2A2A2A) : Colors.grey[50]), - borderRadius: BorderRadius.circular(12), - ), - child: Column( - children: [ - Icon( - _showGuideOnStartup - ? Icons.notifications_active - : Icons.notifications_off, - color: _showGuideOnStartup - ? _themeController.currentThemeColor - : (isDark ? Colors.grey[400] : Colors.grey[500]), - size: 40, - ), - const SizedBox(height: 12), - Text( - _showGuideOnStartup ? '已开启' : '已关闭', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: _showGuideOnStartup - ? _themeController.currentThemeColor - : (isDark ? Colors.white : Colors.grey[700]), - ), - ), - const SizedBox(height: 8), - Text( - _showGuideOnStartup ? '下次启动时将显示欢迎页' : '下次启动时将不显示欢迎页', - style: TextStyle( - fontSize: 14, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), - textAlign: TextAlign.center, - ), - ], - ), - ), - const SizedBox(height: 16), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () => Navigator.pop(context), - style: ElevatedButton.styleFrom( - backgroundColor: _themeController.currentThemeColor, - foregroundColor: Colors.white, - padding: const EdgeInsets.symmetric(vertical: 12), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - child: const Text('知道了'), - ), - ), - ], - ), - ), - ), - ); - } - Widget _buildPrivacyPage(bool isDark, Color primaryColor) { _initTabController(); return Stack( diff --git a/lib/views/profile/history_page.dart b/lib/views/profile/history_page.dart index 372004c..ebc58bc 100644 --- a/lib/views/profile/history_page.dart +++ b/lib/views/profile/history_page.dart @@ -2,8 +2,6 @@ import 'package:flutter/cupertino.dart'; 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'; diff --git a/lib/views/profile/level/distinguish.dart b/lib/views/profile/level/distinguish.dart index 8edabb4..c7f8613 100644 --- a/lib/views/profile/level/distinguish.dart +++ b/lib/views/profile/level/distinguish.dart @@ -153,7 +153,6 @@ class _DistinguishPageState extends State { Widget _buildStatisticsSheet() { return Obx(() { - final isDark = _themeController.isDarkMode; return Container( decoration: BoxDecoration( color: AppColors.surface, @@ -541,7 +540,6 @@ $_poetryLevel Widget _buildEmptyView() { return Obx(() { - final isDark = _themeController.isDarkMode; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/views/profile/level/poetry.dart b/lib/views/profile/level/poetry.dart index a623863..7a8510c 100644 --- a/lib/views/profile/level/poetry.dart +++ b/lib/views/profile/level/poetry.dart @@ -18,7 +18,7 @@ import '../settings/offline-data.dart'; /// 时间: 2026-03-28 /// 功能: 诗词答题页面 /// 介绍: 基于 API 接口实现的诗词答题系统,支持获取题目、提交答案、获取提示 -/// 最新变化: 添加自动加载下一题开关,隐藏提示标签,使用独立逻辑管理器 +/// 上次更新: 2026-04-18 修复答题重复记录问题 class PoetryLevelPage extends StatefulWidget { final bool showBackButton; @@ -330,11 +330,6 @@ class _PoetryLevelPageState extends State /// 下一题 void _nextQuestion() { - // 增加跳过次数 - _skipCount++; - // 保存答题记录 - _saveAnswerRecord(); - _manager.nextQuestion(); _loadQuestion(); } @@ -348,7 +343,6 @@ class _PoetryLevelPageState extends State /// 保存答题记录到本地存储 Future _saveAnswerRecord({bool isCorrect = false}) async { try { - // 保存统计数据 await SharedPreferencesStorageController.setInt( 'totalQuestions', _totalQuestions, @@ -365,9 +359,7 @@ class _PoetryLevelPageState extends State await SharedPreferencesStorageController.setInt('hintCount', _hintCount); await SharedPreferencesStorageController.setInt('skipCount', _skipCount); - // 保存当前题目的详细记录 if (_currentQuestion != null) { - // 构建标签列表 List tags = []; if (_currentQuestion!['type'] != null) { tags.add(_currentQuestion!['type'].toString()); @@ -388,21 +380,29 @@ class _PoetryLevelPageState extends State 'answerTime': DateTime.now().toIso8601String(), }; - // 获取已有的记录列表 List records = await SharedPreferencesStorageController.getStringList( 'poetryAnswerRecords', defaultValue: [], ); - // 添加新记录(JSON格式) - records.add(jsonEncode(record)); + bool alreadyExists = records.any((r) { + try { + final existing = jsonDecode(r) as Map; + return existing['questionId'] == record['questionId'] && + existing['isCorrect'] == record['isCorrect']; + } catch (_) { + return false; + } + }); - // 保存更新后的列表 - await SharedPreferencesStorageController.setStringList( - 'poetryAnswerRecords', - records, - ); + if (!alreadyExists) { + records.add(jsonEncode(record)); + await SharedPreferencesStorageController.setStringList( + 'poetryAnswerRecords', + records, + ); + } } } catch (e) { // 保存失败 diff --git a/lib/views/profile/per_card.dart b/lib/views/profile/per_card.dart index 93f5a06..61ec6ff 100644 --- a/lib/views/profile/per_card.dart +++ b/lib/views/profile/per_card.dart @@ -5,7 +5,6 @@ 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'; diff --git a/lib/views/profile/profile_page.dart b/lib/views/profile/profile_page.dart index c16c58a..62bd587 100644 --- a/lib/views/profile/profile_page.dart +++ b/lib/views/profile/profile_page.dart @@ -3,15 +3,11 @@ /// 介绍: 展示用户头像、个性签名、昵称、统计信息和设置列表,支持左右滑动切换页面 /// 最新变化: 重新设计布局,实现朋友圈风格的个人页面,添加底部内边距适配液态玻璃导航栏 -import 'dart:io' as io; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import '../../constants/app_constants.dart'; import '../../config/app_config.dart'; -import '../../models/colors/theme_colors.dart'; import '../../controllers/settings/is_platform.dart'; import 'history_page.dart'; import 'per_card.dart'; @@ -38,7 +34,7 @@ class ProfilePage extends StatelessWidget { @override Widget build(BuildContext context) { - final controller = Get.put(ProfileController()); + Get.put(ProfileController()); final pageController = PageController(initialPage: 1); final themeController = Get.find(); @@ -567,7 +563,7 @@ class ProfilePage extends StatelessWidget { ), const SizedBox(height: 16), Text( - AppConstants.appName, + AppConfig.appName, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, diff --git a/lib/views/profile/settings/app_fun.dart b/lib/views/profile/settings/app_fun.dart index 1c34b85..29405b5 100644 --- a/lib/views/profile/settings/app_fun.dart +++ b/lib/views/profile/settings/app_fun.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.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 '../../../services/get/tap_liquid_glass_controller.dart'; import '../../../utils/audio_manager.dart'; @@ -650,52 +649,6 @@ class _AppFunSettingsPageState extends State { return const SuggestionsCard(); } - 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: 12, - fontWeight: FontWeight.w500, - color: isDark ? Colors.white : Colors.black87, - ), - ), - const SizedBox(height: 2), - Text( - subtitle, - style: TextStyle( - fontSize: 10, - color: isDark ? Colors.grey[400] : Colors.grey[600], - ), - textAlign: TextAlign.center, - ), - ], - ), - ), - ); - } - void _showSnackBar(String message) { Get.snackbar( '提示', diff --git a/lib/views/profile/settings/learn-us.dart b/lib/views/profile/settings/learn-us.dart index fd2f50a..800d795 100644 --- a/lib/views/profile/settings/learn-us.dart +++ b/lib/views/profile/settings/learn-us.dart @@ -3,7 +3,6 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../../config/app_config.dart'; -import '../../../constants/app_constants.dart'; import '../../../services/get/theme_controller.dart'; /// 时间: 2026-03-26 @@ -581,23 +580,6 @@ class LearnUsPage extends StatelessWidget { ); } - void _copyQQGroupNumber(BuildContext context) { - final themeController = Get.find(); - final primaryColor = themeController.currentThemeColor; - Clipboard.setData(const ClipboardData(text: '271129018')); - - Get.snackbar( - '复制成功', - 'QQ群号已复制到剪贴板', - duration: const Duration(seconds: 2), - colorText: primaryColor, - snackPosition: SnackPosition.BOTTOM, - borderRadius: 8, - margin: const EdgeInsets.all(16), - icon: Icon(Icons.check_circle, color: primaryColor, size: 20), - ); - } - void _showQQGroupDialog(bool isDark, Color primaryColor) { const groupUrl = 'http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=7NoZCGz7tud_DZKYY5AaTzj1TCQngb69&authKey=QRzusXi6sISV76R%2Bk8kfqFzYnbnKo9wBxUXhZyp4e9ra0Joae37oBsO6m2dH23MS&noverify=0&group_code=271129018'; diff --git a/lib/views/profile/settings/offline-data.dart b/lib/views/profile/settings/offline-data.dart index 55ea4e5..b9ce0e9 100644 --- a/lib/views/profile/settings/offline-data.dart +++ b/lib/views/profile/settings/offline-data.dart @@ -3,7 +3,6 @@ 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 '../../../services/get/theme_controller.dart'; import '../../../utils/http/http_client.dart'; import 'user-plan.dart'; @@ -256,11 +255,10 @@ class _OfflineDataPageState extends State { }); final themeController = Get.find(); - final themeController2 = Get.find(); Get.snackbar( '成功', '成功缓存 ${_selectedType == DownloadType.poetry ? '诗词' : '答题'} $_cachedCount 条数据', - colorText: themeController2.currentThemeColor, + colorText: themeController.currentThemeColor, ); } } catch (e) { diff --git a/lib/views/profile/settings/privacy.dart b/lib/views/profile/settings/privacy.dart index cfd9688..3c6c247 100644 --- a/lib/views/profile/settings/privacy.dart +++ b/lib/views/profile/settings/privacy.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; import '../../../services/get/theme_controller.dart'; /// 时间: 2026-03-26 diff --git a/lib/views/profile/settings/user-plan.dart b/lib/views/profile/settings/user-plan.dart index 2656b7e..04020a9 100644 --- a/lib/views/profile/settings/user-plan.dart +++ b/lib/views/profile/settings/user-plan.dart @@ -1,7 +1,6 @@ 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'; /// 时间: 2026-03-26 diff --git a/lib/views/profile/settings/widgets.dart b/lib/views/profile/settings/widgets.dart index 94f06d6..8937e91 100644 --- a/lib/views/profile/settings/widgets.dart +++ b/lib/views/profile/settings/widgets.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../../constants/app_constants.dart'; import '../../../services/get/theme_controller.dart'; /// 时间: 2026-03-27 diff --git a/lib/views/profile/theme/app-diy.dart b/lib/views/profile/theme/app-diy.dart index dabc858..ae98b7b 100644 --- a/lib/views/profile/theme/app-diy.dart +++ b/lib/views/profile/theme/app-diy.dart @@ -8,6 +8,7 @@ import '../../../services/get/theme_controller.dart'; /// 时间: 2026-03-27 /// 功能: 主题个性化设置页面 /// 介绍: 允许用户自定义应用主题、颜色、字体大小等 +/// 上次更新: 2026-04-18 新增跟随系统深色模式开关 class AppDiyPage extends StatefulWidget { const AppDiyPage({super.key}); @@ -280,13 +281,22 @@ class _AppDiyPageState extends State { // 主题模式 _buildSection('显示设置', isDark), _buildSwitchItem( - '深色模式', - _themeController.isDarkModeRx.value, - (value) => _themeController.toggleDarkMode(value), - icon: Icons.dark_mode, + '跟随系统', + _themeController.followSystemRx.value, + (value) => _themeController.toggleFollowSystem(value), + icon: Icons.brightness_auto, isDark: isDark, themeColorIdx: themeColorIdx, ), + if (!_themeController.followSystemRx.value) + _buildSwitchItem( + '深色模式', + _themeController.isDarkModeRx.value, + (value) => _themeController.toggleDarkMode(value), + icon: Icons.dark_mode, + isDark: isDark, + themeColorIdx: themeColorIdx, + ), // 主题颜色 _buildSection('主题颜色', isDark), diff --git a/lib/widgets/tabbed_nav_app_bar.dart b/lib/widgets/tabbed_nav_app_bar.dart index 5edcb85..ad4fb62 100644 --- a/lib/widgets/tabbed_nav_app_bar.dart +++ b/lib/widgets/tabbed_nav_app_bar.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../constants/app_constants.dart'; import '../services/get/theme_controller.dart'; /// 时间: 2026-03-22 diff --git a/lib/widgets/tap-liquid-glass.dart b/lib/widgets/tap-liquid-glass.dart index 6ae3cb0..380c868 100644 --- a/lib/widgets/tap-liquid-glass.dart +++ b/lib/widgets/tap-liquid-glass.dart @@ -1,7 +1,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../constants/app_constants.dart'; import '../config/app_config.dart'; import '../services/get/theme_controller.dart'; import '../services/get/tap_liquid_glass_controller.dart'; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index cc10c4d..d8a4062 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,12 +7,16 @@ #include "generated_plugin_registrant.h" #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 8e2a190..04f81f4 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_linux + file_selector_linux url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index e139e19..b8c00b5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,6 +7,8 @@ import Foundation import audioplayers_darwin import device_info_plus +import file_picker_ohos +import file_selector_macos import flutter_udid import package_info_plus import path_provider_foundation @@ -18,6 +20,8 @@ import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/ohos/build-profile.json5 b/ohos/build-profile.json5 index d51d848..f7ee1a1 100644 --- a/ohos/build-profile.json5 +++ b/ohos/build-profile.json5 @@ -5,13 +5,13 @@ "name": "default", "type": "HarmonyOS", "material": { - "certpath": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.cer", + "certpath": "C:/Users/无书/.ohos/config/default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.cer", "keyAlias": "debugKey", - "keyPassword": "0000001BDCE59CF329035B600E433CAB700C4AE16559081238E790CDFE37F7AB73BDBB71CD0F079BD5702B", - "profile": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p7b", + "keyPassword": "0000001B48EBC2D945ABE7D6F3BB718C43469FA59B7639FF7F8457288FBE77D0014C9A68BE986AE71A017D", + "profile": "C:/Users/无书/.ohos/config/default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p7b", "signAlg": "SHA256withECDSA", - "storeFile": "C:\\Users\\无书\\.ohos\\config\\default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p12", - "storePassword": "0000001BC77AD39EA9D28DC278EFD43AFA07D2E069731C1FDF82558FE0608857D134EF1BB89BC4674B6F57" + "storeFile": "C:/Users/无书/.ohos/config/default_ohos_hWyPJmkoRvc13RxcUC3NSaiad5bS6MHBrY9nkKd-288=.p12", + "storePassword": "0000001B536349C216E71C824846D712C6EC1732383090A4067D9E3971DDB496C75A876F491C94114BD6AB" } }, { @@ -20,11 +20,11 @@ "material": { "certpath": "D:/zhshu/520kiss123Release .cer", "keyAlias": "520kiss123", - "keyPassword": "0000001AAF334677E7522B45BC3CAA1BE491DBBE5B832B990DADB9162D2E52F03259D18F4885EA34CE65", + "keyPassword": "0000001A898E369024A788AA7DD3BD58B65B023D01DC48938BCCA8528A68B8BCE07DB3FBF9FCBF5FEE27", "profile": "D:/zhshu/520kiss123Release .p7b", "signAlg": "SHA256withECDSA", "storeFile": "D:/zhshu/520kiss123.p12", - "storePassword": "0000001A78654F120BD94B943B8BDE312943D887BCBF078C19FA10BEF86062CF1D4B348F26B61DC489C1" + "storePassword": "0000001AFD1940FE217965559F008F2D132590EDB4175196F5B83B2CB1AF54843910D42C9793EBE7B3BF" } } ], diff --git a/packages/file_picker b/packages/file_picker new file mode 160000 index 0000000..433c8f6 --- /dev/null +++ b/packages/file_picker @@ -0,0 +1 @@ +Subproject commit 433c8f6567ae6224e1446d001045499014a24461 diff --git a/pubspec.lock b/pubspec.lock index 0f8aa46..2e58ce9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -215,6 +215,45 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" + file_picker_ohos: + dependency: "direct main" + description: + path: "packages/file_picker" + relative: true + source: path + version: "10.3.8" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.4" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.5" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.7.0" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.3+5" fixnum: dependency: transitive description: @@ -236,6 +275,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.34" flutter_test: dependency: "direct dev" description: flutter @@ -278,6 +325,70 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.1.2" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.1" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "66810af8e99b2657ee98e5c6f02064f69bb63f7a70e343937f70946c5f8c6622" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.8.13+16" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.1" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "956c16a42c0c708f914021666ffcd8265dde36e673c9fa68c81f7d085d9774ad" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.8.13+3" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.2+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.11.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.2" intl: dependency: "direct main" description: @@ -375,7 +486,7 @@ packages: source: hosted version: "1.9.1" path_provider: - dependency: transitive + dependency: "direct main" description: path: "packages/path_provider/path_provider" ref: HEAD diff --git a/pubspec.yaml b/pubspec.yaml index ed4ff03..c8f4c27 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: poes description: "腹有诗书气自华" publish_to: 'none' -version: 1.5.0+26041002 +version: 1.6.0+26041801 environment: sdk: ^3.9.2 @@ -47,6 +47,12 @@ dependencies: pinyin: ^3.3.0 package_info_plus: ^9.0.1 + file_picker_ohos: + path: packages/file_picker + path_provider: + git: + url: https://gitcode.com/openharmony-sig/flutter_packages.git + path: packages/path_provider/path_provider dev_dependencies: flutter_test: diff --git a/web/index.html b/web/index.html index cd43676..1f0643a 100644 --- a/web/index.html +++ b/web/index.html @@ -18,12 +18,12 @@ - + - + diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index ae488a2..17b2834 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,12 +7,15 @@ #include "generated_plugin_registrant.h" #include +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { AudioplayersWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); SharePlusWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ed0a61c..d76c82a 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_windows + file_selector_windows share_plus url_launcher_windows )