fix(app): 日记可见性修复 — 私密日记仅本地 + Web 端 ID 修复 + 分享按钮
问题修复: 1. Web端保存的日记看不到:createJournal 返回值未捕获,server ID 丢失导致 后续元素保存用错 ID。现在使用 saved.id 贯穿全部操作。 2. 管理端看不到新建日记:后端 list_journals 添加 is_private 过滤,admin/teacher 查看他人日记时排除私密日记。 3. RemoteJournalRepository 添加 onJournalChanged 变更通知流,HomeBloc 可自动刷新。 4. SyncEngine(native + web)enqueue 添加 is_private 防御性检查,私密日记不入队。 5. 编辑器 _persistState 条件入队:仅非私密日记同步到后端。 6. 分享流程改造:首次从私密变为公开时入队 create 操作上传。 7. 日记卡片添加可见性标签(仅自己可见/班级可见/公开),私密日记可点击分享。 8. 首页 _sharePrivateJournal 弹出 ShareBottomSheet 主动分享。
This commit is contained in:
@@ -121,28 +121,35 @@ class _EditorPageState extends State<EditorPage> {
|
||||
title: '${now.month}月${now.day}日的日记',
|
||||
date: now,
|
||||
);
|
||||
await repo.createJournal(entry);
|
||||
setId(entry.id);
|
||||
|
||||
// 保存笔画
|
||||
// 保存到仓库(Web=远程API,原生=Isar本地)
|
||||
// 远程仓库返回服务端生成的 ID,必须使用返回值
|
||||
final saved = await repo.createJournal(entry);
|
||||
final journalId = saved.id;
|
||||
setId(journalId);
|
||||
|
||||
// 保存笔画 — 使用 saved.id(与仓库一致)
|
||||
if (state.strokes.isNotEmpty) {
|
||||
await _saveStrokesAsElement(repo, entry.id, state.strokes);
|
||||
await _saveStrokesAsElement(repo, journalId, state.strokes);
|
||||
}
|
||||
|
||||
// 保存其他元素
|
||||
for (final element in state.elements) {
|
||||
await repo.addElement(element.copyWith(journalId: entry.id));
|
||||
await repo.addElement(element.copyWith(journalId: journalId));
|
||||
}
|
||||
|
||||
// 入队 SyncEngine 等待同步到后端
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: entry.id,
|
||||
type: SyncOperationType.create,
|
||||
endpoint: '/diary/journals',
|
||||
data: entry.toJson(),
|
||||
version: entry.version,
|
||||
createdAt: now,
|
||||
));
|
||||
// 仅非私密日记入队 SyncEngine 等待同步到后端
|
||||
// 私密日记(is_private=true)仅保存在本地,不上传
|
||||
if (!saved.isPrivate) {
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: journalId,
|
||||
type: SyncOperationType.create,
|
||||
endpoint: '/diary/journals',
|
||||
data: saved.toJson(),
|
||||
version: saved.version,
|
||||
createdAt: now,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// --- 更新已有日记 ---
|
||||
final existing = await repo.getJournal(savedJournalId);
|
||||
@@ -156,15 +163,17 @@ class _EditorPageState extends State<EditorPage> {
|
||||
);
|
||||
await repo.updateJournal(updated);
|
||||
|
||||
// 入队 SyncEngine 等待同步到后端
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: existing.id,
|
||||
type: SyncOperationType.update,
|
||||
endpoint: '/diary/journals/${existing.id}',
|
||||
data: existing.toJson(),
|
||||
version: existing.version,
|
||||
createdAt: now,
|
||||
));
|
||||
// 仅非私密日记入队 SyncEngine
|
||||
if (!updated.isPrivate) {
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: updated.id,
|
||||
type: SyncOperationType.update,
|
||||
endpoint: '/diary/journals/${updated.id}',
|
||||
data: updated.toJson(),
|
||||
version: updated.version,
|
||||
createdAt: now,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 更新笔画
|
||||
@@ -215,6 +224,11 @@ class _EditorPageState extends State<EditorPage> {
|
||||
}
|
||||
|
||||
/// 显示分享面板并在用户选择后导航
|
||||
///
|
||||
/// 分享行为:
|
||||
/// - 分享到班级/所有人 → is_private=false + shared_to_class=对应值
|
||||
/// - 仅自己可见 → is_private=true,不上传到后端
|
||||
/// - 首次将私密日记变为公开时,入队 SyncEngine create 操作上传
|
||||
static Future<void> _showShareSheetAndNavigate(
|
||||
BuildContext context,
|
||||
JournalRepository repo,
|
||||
@@ -246,14 +260,41 @@ class _EditorPageState extends State<EditorPage> {
|
||||
classId: userClassId,
|
||||
className: userClassName,
|
||||
onDecision: (shareToClass) async {
|
||||
// 更新日记的 sharedToClass 状态
|
||||
if (savedJournalId != null) {
|
||||
try {
|
||||
final entry = await repo.getJournal(savedJournalId);
|
||||
if (entry != null) {
|
||||
await repo.updateJournal(
|
||||
entry.copyWith(sharedToClass: shareToClass),
|
||||
final wasPrivate = entry.isPrivate;
|
||||
// 分享到班级/所有人 → 取消私密标记
|
||||
final updated = entry.copyWith(
|
||||
isPrivate: false,
|
||||
sharedToClass: shareToClass,
|
||||
);
|
||||
await repo.updateJournal(updated);
|
||||
|
||||
// 首次从私密变为公开 → 入队 SyncEngine 上传到后端
|
||||
if (wasPrivate && !updated.isPrivate) {
|
||||
final syncEngine = context.read<SyncEngine>();
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: updated.id,
|
||||
type: SyncOperationType.create,
|
||||
endpoint: '/diary/journals',
|
||||
data: updated.toJson(),
|
||||
version: updated.version,
|
||||
createdAt: DateTime.now(),
|
||||
));
|
||||
} else if (!updated.isPrivate) {
|
||||
// 已公开日记的分享状态更新
|
||||
final syncEngine = context.read<SyncEngine>();
|
||||
syncEngine.enqueue(PendingOperation(
|
||||
id: updated.id,
|
||||
type: SyncOperationType.update,
|
||||
endpoint: '/diary/journals/${updated.id}',
|
||||
data: updated.toJson(),
|
||||
version: updated.version,
|
||||
createdAt: DateTime.now(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('更新分享状态失败: $e');
|
||||
|
||||
Reference in New Issue
Block a user