feat: 添加起卦教程首次访问追踪和Agent时间上下文

- 后端 ProfileSettingsV1 添加 DivinationTutorialSettings 字段
- 前端三个起卦页面添加首次访问检测,自动弹出教程
- 教程展示后更新 settings 标记,避免重复弹出
- 使用本地状态管理避免并发更新覆盖问题
- Agent 系统提示添加时间上下文信息
This commit is contained in:
qzl
2026-04-15 18:56:41 +08:00
parent 55eeab43df
commit 69b34bd723
13 changed files with 624 additions and 0 deletions
@@ -51,6 +51,14 @@ class ProfileApi {
'allow_notifications': settings.notification.allowNotifications,
'allow_vibration': settings.notification.allowVibration,
},
'divination_tutorial': {
'divination_entry_shown':
settings.divinationTutorial.divinationEntryShown,
'auto_divination_shown':
settings.divinationTutorial.autoDivinationShown,
'manual_divination_shown':
settings.divinationTutorial.manualDivinationShown,
},
},
};
final json = await _apiClient.rawDio.patch<Map<String, dynamic>>(
@@ -119,6 +127,23 @@ class ProfileApi {
)
: const NotificationSettings();
final divinationTutorialRaw = settingsRaw is Map<String, dynamic>
? settingsRaw['divination_tutorial']
: null;
final divinationTutorial = divinationTutorialRaw is Map<String, dynamic>
? DivinationTutorialSettings(
divinationEntryShown:
(divinationTutorialRaw['divination_entry_shown'] as bool?) ??
true,
autoDivinationShown:
(divinationTutorialRaw['auto_divination_shown'] as bool?) ??
true,
manualDivinationShown:
(divinationTutorialRaw['manual_divination_shown'] as bool?) ??
true,
)
: const DivinationTutorialSettings();
return ProfileSettingsV1(
displayName: (json['display_name'] as String?) ?? '',
bio: (json['bio'] as String?) ?? '',
@@ -130,6 +155,7 @@ class ProfileApi {
const <String, dynamic>{})
: const <String, dynamic>{},
notification: notification,
divinationTutorial: divinationTutorial,
);
}
}
@@ -59,6 +59,31 @@ class NotificationSettings {
}
}
class DivinationTutorialSettings {
const DivinationTutorialSettings({
this.divinationEntryShown = true,
this.autoDivinationShown = true,
this.manualDivinationShown = true,
});
final bool divinationEntryShown;
final bool autoDivinationShown;
final bool manualDivinationShown;
DivinationTutorialSettings copyWith({
bool? divinationEntryShown,
bool? autoDivinationShown,
bool? manualDivinationShown,
}) {
return DivinationTutorialSettings(
divinationEntryShown: divinationEntryShown ?? this.divinationEntryShown,
autoDivinationShown: autoDivinationShown ?? this.autoDivinationShown,
manualDivinationShown:
manualDivinationShown ?? this.manualDivinationShown,
);
}
}
class ProfileSettingsV1 {
const ProfileSettingsV1({
this.version = 1,
@@ -69,6 +94,7 @@ class ProfileSettingsV1 {
this.preferences = const PreferenceSettings(),
this.privacy = const <String, Object?>{},
this.notification = const NotificationSettings(),
this.divinationTutorial = const DivinationTutorialSettings(),
});
final int version;
@@ -79,6 +105,7 @@ class ProfileSettingsV1 {
final PreferenceSettings preferences;
final Map<String, Object?> privacy;
final NotificationSettings notification;
final DivinationTutorialSettings divinationTutorial;
ProfileSettingsV1 copyWith({
int? version,
@@ -89,6 +116,7 @@ class ProfileSettingsV1 {
PreferenceSettings? preferences,
Map<String, Object?>? privacy,
NotificationSettings? notification,
DivinationTutorialSettings? divinationTutorial,
}) {
return ProfileSettingsV1(
version: version ?? this.version,
@@ -99,6 +127,7 @@ class ProfileSettingsV1 {
preferences: preferences ?? this.preferences,
privacy: privacy ?? this.privacy,
notification: notification ?? this.notification,
divinationTutorial: divinationTutorial ?? this.divinationTutorial,
);
}