本次更新包含多项功能优化与兼容性修复: 1. iOS/鸿蒙端添加加密出口合规配置,跳过App Store审核问卷 2. 新增学习计划设置页路由与国际化支持 3. 修复鸿蒙端剪贴板粘贴不工作问题,安装标准剪贴板拦截器 4. 优化收藏功能:兼容复合ID、添加状态同步与触觉反馈 5. 修复鸿蒙端相册保存兼容性,统一使用系统分享降级方案 6. 优化搜索快捷方式跳转逻辑,避免白屏问题 7. 更新本地化资源,新增闲情逸致、学习计划等模块翻译 8. 修复节气日期表排序与跨年边界问题 9. 优化设备信息页面显示,新增系统版本号展示 10. 重构文件传输二维码逻辑,使用纯URL提升兼容性 11. 优化设置项布局,避免文本溢出问题 12. 修复登录页记住账户功能,新增隐私协议守卫 13. 更新macOS依赖库,替换flutter_secure_storage为darwin版本
159 lines
4.3 KiB
Dart
159 lines
4.3 KiB
Dart
/// ============================================================
|
||
/// 闲言APP — 学习计划数据模型
|
||
/// 创建时间: 2026-05-02
|
||
/// 更新时间: 2026-06-17
|
||
/// 作用: 学习计划 + 记录 + 模板 — 支持进度追踪
|
||
/// 上次更新: emoji替换为CupertinoIcons,label改为多语言键
|
||
/// ============================================================
|
||
|
||
import 'package:flutter/cupertino.dart';
|
||
|
||
enum PlanCategory {
|
||
poetry('catPoetry', 0xFF4A90D9),
|
||
chengyu('catChengyu', 0xFFEF5350),
|
||
classic('catClassic', 0xFF5C6BC0),
|
||
wisdom('catWisdom', 0xFFD4A843),
|
||
custom('catCustom', 0xFF26A69A);
|
||
|
||
const PlanCategory(this.labelKey, this.colorValue);
|
||
|
||
/// 多语言翻译键,如 'catPoetry' → t.studyPlan.catPoetry
|
||
final String labelKey;
|
||
|
||
/// 分类颜色值
|
||
final int colorValue;
|
||
|
||
/// 分类图标(非常量,通过 getter 返回)
|
||
IconData get iconData => switch (this) {
|
||
poetry => CupertinoIcons.doc_text,
|
||
chengyu => CupertinoIcons.textformat_abc,
|
||
classic => CupertinoIcons.book,
|
||
wisdom => CupertinoIcons.lightbulb,
|
||
custom => CupertinoIcons.star,
|
||
};
|
||
}
|
||
|
||
class PlanTemplate {
|
||
const PlanTemplate({
|
||
required this.id,
|
||
required this.titleKey,
|
||
required this.descriptionKey,
|
||
required this.category,
|
||
required this.dailyGoal,
|
||
required this.iconDataKey,
|
||
});
|
||
|
||
final String id;
|
||
|
||
/// 多语言翻译键,如 'dailyPoetry5Title' → t.studyPlan.dailyPoetry5Title
|
||
final String titleKey;
|
||
|
||
/// 多语言翻译键,如 'dailyPoetry5Desc' → t.studyPlan.dailyPoetry5Desc
|
||
final String descriptionKey;
|
||
|
||
final PlanCategory category;
|
||
final int dailyGoal;
|
||
|
||
/// 图标键名,用于获取对应的CupertinoIcons
|
||
final String iconDataKey;
|
||
|
||
/// 获取模板图标
|
||
IconData get iconData => switch (iconDataKey) {
|
||
'doc_text' => CupertinoIcons.doc_text,
|
||
'flower' => CupertinoIcons.leaf_arrow_circlepath,
|
||
'textformat_abc' => CupertinoIcons.textformat_abc,
|
||
'lightbulb' => CupertinoIcons.lightbulb,
|
||
'book' => CupertinoIcons.book,
|
||
'star' => CupertinoIcons.star,
|
||
_ => CupertinoIcons.doc_text,
|
||
};
|
||
}
|
||
|
||
class PlanTemplates {
|
||
PlanTemplates._();
|
||
|
||
static const List<PlanTemplate> all = [
|
||
PlanTemplate(
|
||
id: 'daily_poetry_5',
|
||
titleKey: 'dailyPoetry5Title',
|
||
descriptionKey: 'dailyPoetry5Desc',
|
||
category: PlanCategory.poetry,
|
||
dailyGoal: 5,
|
||
iconDataKey: 'doc_text',
|
||
),
|
||
PlanTemplate(
|
||
id: 'daily_poetry_3',
|
||
titleKey: 'dailyPoetry3Title',
|
||
descriptionKey: 'dailyPoetry3Desc',
|
||
category: PlanCategory.poetry,
|
||
dailyGoal: 3,
|
||
iconDataKey: 'flower',
|
||
),
|
||
PlanTemplate(
|
||
id: 'daily_chengyu_5',
|
||
titleKey: 'dailyChengyu5Title',
|
||
descriptionKey: 'dailyChengyu5Desc',
|
||
category: PlanCategory.chengyu,
|
||
dailyGoal: 5,
|
||
iconDataKey: 'textformat_abc',
|
||
),
|
||
PlanTemplate(
|
||
id: 'daily_wisdom_3',
|
||
titleKey: 'dailyWisdom3Title',
|
||
descriptionKey: 'dailyWisdom3Desc',
|
||
category: PlanCategory.wisdom,
|
||
dailyGoal: 3,
|
||
iconDataKey: 'lightbulb',
|
||
),
|
||
PlanTemplate(
|
||
id: 'weekly_classic',
|
||
titleKey: 'weeklyClassicTitle',
|
||
descriptionKey: 'weeklyClassicDesc',
|
||
category: PlanCategory.classic,
|
||
dailyGoal: 1,
|
||
iconDataKey: 'book',
|
||
),
|
||
PlanTemplate(
|
||
id: 'daily_mix_5',
|
||
titleKey: 'dailyMix5Title',
|
||
descriptionKey: 'dailyMix5Desc',
|
||
category: PlanCategory.custom,
|
||
dailyGoal: 5,
|
||
iconDataKey: 'star',
|
||
),
|
||
];
|
||
}
|
||
|
||
class StudyPlanState {
|
||
const StudyPlanState({
|
||
this.plans = const [],
|
||
this.todayRecords = const [],
|
||
this.selectedPlanId,
|
||
this.isLoading = false,
|
||
this.showCreateSheet = false,
|
||
});
|
||
|
||
final List<dynamic> plans;
|
||
final List<dynamic> todayRecords;
|
||
final int? selectedPlanId;
|
||
final bool isLoading;
|
||
final bool showCreateSheet;
|
||
|
||
StudyPlanState copyWith({
|
||
List<dynamic>? plans,
|
||
List<dynamic>? todayRecords,
|
||
int? selectedPlanId,
|
||
bool? isLoading,
|
||
bool? showCreateSheet,
|
||
bool clearSelectedPlanId = false,
|
||
}) {
|
||
return StudyPlanState(
|
||
plans: plans ?? this.plans,
|
||
todayRecords: todayRecords ?? this.todayRecords,
|
||
selectedPlanId: clearSelectedPlanId ? null : (selectedPlanId ?? this.selectedPlanId),
|
||
isLoading: isLoading ?? this.isLoading,
|
||
showCreateSheet: showCreateSheet ?? this.showCreateSheet,
|
||
);
|
||
}
|
||
}
|