chore: 批量完成2026-05-24版本迭代更新

本次提交涵盖多项功能优化与重构:
1. 重构pro_image_editor依赖为官方托管版本,移除本地包引用
2. 拆分角色表情枚举至独立文件,优化代码复用性
3. 新增壁纸收藏、预加载、健康检测服务与本地存储支持
4. 完善API响应类型安全检查与排行榜服务能力
5. 新增应用锁设置路由与页面支持
6. 优化路由跳转使用常量路径替代硬编码字符串
7. 新增阅读报告分享功能与设置变更日志服务
8. 修复多处类型转换与空指针风险问题
9. 调整API超时时间优化网络请求表现
10. 统一文件头格式与部分UI组件样式
This commit is contained in:
Developer
2026-05-24 04:00:49 +08:00
parent f5a75cb6d3
commit df1f127a12
84 changed files with 11368 additions and 2176 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
# 架构重构与功能增强 实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 修复9项架构不足动态圆角生效、角色精灵主题化、枚举位置迁移、引导页解耦、设置Provider简化、互斥锁超时、渐变背景优化、个性化页增强、协议页增强
**Architecture:** 逐项独立修改,每项完成后验证编译通过。动态圆角采用"先写测试→再批量替换"策略确保安全。
**Tech Stack:** Flutter/Dart, Riverpod, CustomPainter, ThemeExtension
---
## Task 1: CharacterExpression 枚举迁移(独立,无依赖)
**Files:**
- Create: `lib/core/constants/character_expression.dart`
- Modify: `lib/shared/widgets/animation/appbar_character_sprite.dart`
- Modify: `lib/features/onboarding/presentation/onboarding_page.dart`
- Modify: `lib/features/home/presentation/home_page.dart`
- Modify: `lib/features/home/presentation/home_refresh_indicator.dart`
- Modify: `lib/shared/widgets/animation/sprite_loading_indicator.dart`
- [ ] **Step 1:** 创建 `lib/core/constants/character_expression.dart`,将枚举从 `appbar_character_sprite.dart` 提取出来
- [ ] **Step 2:** 修改 `appbar_character_sprite.dart`,删除枚举定义,改为 `import`
- [ ] **Step 3:** 修改其他4个引用文件将 import 路径从 `appbar_character_sprite.dart` 改为 `character_expression.dart`
- [ ] **Step 4:** 运行 `flutter analyze` 验证
---
## Task 2: EffectMutex 超时机制(独立)
**Files:**
- Modify: `lib/core/services/performance/effect_mutex.dart`
- [ ] **Step 1:**`acquire()` 添加 `Duration? timeout` 参数
- [ ] **Step 2:** 当 timeout 不为 null 时,用 `Future.any` + `Future.delayed` 实现超时取消
- [ ] **Step 3:** 超时后从 `_pending` 列表移除complete 一个异常或 null token
- [ ] **Step 4:** 运行 `flutter analyze` 验证
---
## Task 3: Onboarding 完成回调解耦(独立)
**Files:**
- Modify: `lib/features/onboarding/providers/onboarding_provider.dart`
- [ ] **Step 1:**`completeOnboarding()` 中,将直接调用 `generalSettingsProvider.notifier` 的3行替换为直接写 KV 存储(与 generalSettingsProvider 使用相同的 key让 generalSettingsProvider 在下次 build 时自动从 KV 读取
- [ ] **Step 2:** 确认 KV key 一致性(`general_shake_to_switch` / `sfx_enabled` / `general_shader_background`
- [ ] **Step 3:** 运行 `flutter analyze` 验证
---
## Task 4: 角色精灵硬编码颜色主题化(独立,大改动)
**Files:**
- Modify: `lib/shared/widgets/animation/appbar_character_sprite.dart`
- Modify: `lib/core/theme/app_theme.dart`(新增角色配色令牌)
- [ ] **Step 1:**`AppThemeExtension` 中新增角色配色字段:`characterSkinLight`/`characterSkinMid`/`characterSkinDark`/`characterEarInner`/`characterNose`/`characterHair`/`characterOutline`
- [ ] **Step 2:**`_lightExtension`/`_darkExtension`/`_amoledExtension` 中定义浅色/深色/AMOLED三套角色配色
- [ ] **Step 3:** 修改 `_AppBarCharacterPainter`,将所有硬编码颜色替换为主题令牌参数
- [ ] **Step 4:** 修改 `AppBarCharacterSprite.build()` 传递主题颜色到 Painter
- [ ] **Step 5:** 运行 `flutter analyze` 验证
---
## Task 5: 动态圆角批量替换(高风险,需测试先行)
**Files:**
- Modify: 100+ 文件602处 `AppRadius.xxxBorder``AppRadius.of(context).xxxBorder`
- Create: `test/core/theme/app_radius_test.dart`
- [ ] **Step 1:** 编写测试文件 `app_radius_test.dart`,验证 `AppRadiusData._fromId` 的4种风格返回正确值
- [ ] **Step 2:** 运行测试确认通过
- [ ] **Step 3:** 用脚本批量替换:`AppRadius.xsBorder``AppRadius.of(context).xsBorder` 等6种模式
- [ ] **Step 4:** 手动检查替换结果,修复无 context 的场景(如 Provider/常量定义处)
- [ ] **Step 5:** 运行 `flutter analyze` 验证全项目无错误
- [ ] **Step 6:** 运行测试确认通过
---
## Task 6: general_settings_provider.dart 简化(独立)
**Files:**
- Modify: `lib/features/mine/settings/providers/general_settings_provider.dart`
- [ ] **Step 1:** 提取通用 `_setField<T>` 方法,封装"更新state + 写KV"模式
- [ ] **Step 2:** 将所有 setter 方法改为调用 `_setField`
- [ ] **Step 3:** 运行 `flutter analyze` 验证
---
## Task 7: Mesh渐变背景优化独立
**Files:**
- Modify: `lib/features/onboarding/presentation/widgets/mesh_gradient_background.dart`
- [ ] **Step 1:** 预计算色块路径:在 `_initBlobs` 中生成 `List<Offset>` 路径点,动画时只做插值
- [ ] **Step 2:** 扩展 `_isLowEnd` 判断iOS 检测 `Platform.isIOS` + 低内存设备列表Android 检测 `DeviceInfoPlugin` 低 RAM
- [ ] **Step 3:** 运行 `flutter analyze` 验证
---
## Task 8: 个性化页增强(依赖 Task 4 角色主题化)
**Files:**
- Modify: `lib/features/onboarding/presentation/pages/personalization_page.dart`
- [ ] **Step 1:** 预览卡片增强:实时反映主题模式(浅/深色切换时卡片背景变化)和强调色变化
- [ ] **Step 2:** 增加圆角风格选择3个选项紧凑/标准/圆润),使用 CupertinoIcons
- [ ] **Step 3:** 运行 `flutter analyze` 验证
---
## Task 9: 协议页章节导航 + 权限分组(独立)
**Files:**
- Modify: `lib/features/onboarding/presentation/pages/agreement_page.dart`
- Modify: `lib/core/services/auth/permission_service.dart`(添加分组字段)
- [ ] **Step 1:**`AppPermission` 枚举添加 `group` 字段(必要权限/可选权限/系统权限)
- [ ] **Step 2:** 修改权限列表展示,按分组显示,每组有标题
- [ ] **Step 3:** 协议内容添加章节锚点导航(顶部章节标签)
- [ ] **Step 4:** 运行 `flutter analyze` 验证
---
## 执行顺序
```
Task 1 (枚举迁移) ─── 独立,可先执行
Task 2 (互斥锁超时) ── 独立,可先执行
Task 3 (引导页解耦) ── 独立,可先执行
Task 4 (角色主题化) ── 独立,但 Task 8 依赖它
Task 5 (动态圆角) ──── 高风险,需测试先行
Task 6 (设置简化) ──── 独立
Task 7 (渐变优化) ──── 独立
Task 8 (个性化增强) ── 依赖 Task 4
Task 9 (协议页增强) ── 独立
```
可并行Task 1/2/3/6/7/9 可同时执行
串行Task 4 → Task 8Task 5 需单独执行(影响面太大)

View File

@@ -4,7 +4,7 @@
* @author AI Coder
* @date 2026-05-14
* @desc 赛季排行榜: 赛季列表/排行榜/我的排名/领取奖励
* @update v14.103.0 新增_ensureActiveSeason自动创建周赛季,leaderboard和myRank无活跃赛季时自动创建
* @update v14.104.0 新增install方法自动建表;install加入noNeedLogin
*/
namespace app\api\controller;
@@ -14,7 +14,7 @@ use think\Db;
class Rank extends Api
{
protected $noNeedLogin = ['seasons', 'leaderboard'];
protected $noNeedLogin = ['seasons', 'leaderboard', 'install'];
protected $noNeedRight = ['*'];
protected $rateLimit = [
@@ -219,6 +219,54 @@ class Rank extends Api
]);
}
/**
* @name 安装排行榜表
* @desc 自动创建rank_season和rank_record表并激活当前赛季
*/
public function install()
{
$sql1 = "CREATE TABLE IF NOT EXISTS `tool_rank_season` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL DEFAULT '',
`type` enum('weekly','monthly') NOT NULL DEFAULT 'weekly',
`start_time` int(11) unsigned NOT NULL DEFAULT 0,
`end_time` int(11) unsigned NOT NULL DEFAULT 0,
`status` enum('active','settled','cancelled') NOT NULL DEFAULT 'active',
`rewards` text DEFAULT NULL,
`createtime` int(11) unsigned NOT NULL DEFAULT 0,
`updatetime` int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
$sql2 = "CREATE TABLE IF NOT EXISTS `tool_rank_record` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`season_id` int(11) unsigned NOT NULL DEFAULT 0,
`rank_type` enum('exp','signin','badge','score') NOT NULL DEFAULT 'exp',
`user_id` int(11) unsigned NOT NULL DEFAULT 0,
`rank` int(11) unsigned NOT NULL DEFAULT 0,
`value` int(11) NOT NULL DEFAULT 0,
`reward_claimed` tinyint(1) NOT NULL DEFAULT 0,
`createtime` int(11) unsigned NOT NULL DEFAULT 0,
`updatetime` int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_season_type` (`season_id`, `rank_type`),
KEY `idx_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
try {
Db::execute($sql1);
Db::execute($sql2);
} catch (\Exception $e) {
$this->error('建表失败: ' . $e->getMessage());
}
$currentSeason = $this->_ensureActiveSeason();
$this->success('安装成功', [
'tables' => ['tool_rank_season', 'tool_rank_record'],
'active_season' => $currentSeason,
]);
}
/**
* @name 实时计算排行(前N名)
*/

File diff suppressed because it is too large Load Diff