Skip to content

[Bug] 共享账本 Editor 的标签选择器「最近使用」与「全部标签」内容相同 #443

Description

@TNT-Likely

问题描述

共享账本 Editor 打开记账页的标签选择器时,「最近使用」区块和「全部标签」区块内容完全一致,「最近使用」失去意义。

个人账本 / Owner 视角正常。

根因

lib/utils/shared_ledger_picker_filter.dart::filterTagsForLedger 在 Editor 分支里无视传入的列表,直接返回该账本的全量 mirror 标签:

Future<List<Tag>> filterTagsForLedger(List<Tag> all, LedgerPickerContext? ctx) async {
  if (ctx == null || !ctx.isEditorInShared || ctx.ledgerSyncId == null) {
    return all;
  }
  final shared = await (select(sharedLedgerTags)
        ..where((t) => t.ledgerSyncId.equals(ctx.ledgerSyncId!))).get();
  return shared.map(_sharedTagAsMain).toList();   // ← 入参 all 被整个丢掉
}

lib/providers/tag_providers.dartrecentTagsForCurrentLedgerProvider 先查出真正的最近 10 条、再交给它过滤:

final recent = await repo.getRecentlyUsedTags(limit: 10);
if (repo is! LocalRepository) return recent;
final ledgerId = ref.watch(currentLedgerIdProvider);
final ctx = await repo.db.loadLedgerPickerContext(ledgerId);
return repo.db.filterTagsForLedger(recent, ctx);   // Editor 下被整体替换成全量

于是 Editor 下「最近使用」= 全部 mirror 标签。

影响范围很小

只有这一处调用方传的是子集。其余调用方传的都是全量列表,此时「丢弃入参、返回 mirror 集合」正是预期语义,不受影响:

调用点 传入 是否受影响
tag_providers.dart:48(全部标签) 全量
tag_providers.dart:104(最近使用) 子集 recent
account_selector.dart:90 全量
transfer_form.dart:328 全量
category_selector.dart:104 / category_selector_dialog.dart:147 全量

所以 filterAccountsForLedger / filterCategoriesForLedger 虽然是同款写法,但没有子集调用方,暂时没有等价问题。

还有两个相邻问题,建议一并评估

1. Editor 的「最近使用」本质上取不到数据

getRecentlyUsedTagslib/data/repositories/local/local_tag_repository.dart:723)查的是主表关联:

FROM tags t
INNER JOIN transaction_tags tt ON t.id = tt.tag_id
INNER JOIN transactions tx ON tt.transaction_id = tx.id

但共享账本 Editor 的标签关联存在 transaction_tag_overrides(按 tag_sync_id),不在 transaction_tags。所以即使修掉上面那个替换问题,Editor 的 recent 也会是空的 —— 真正的最近使用需要从 transaction_tag_overrides join transactions,再经 shared_ledger_tags 映射成 synthetic ID。

2. getRecentlyUsedTags 没有账本维度

上面那段 SQL 没有 ledger_id 过滤,是跨全部账本的全局「最近使用」。多账本用户在 A 账本记账时,「最近使用」里会混进 B 账本用过的标签。这个可能是有意的(标签本身是 user-scoped),但跟「按当前账本过滤」的 provider 命名有出入,值得确认是否符合预期。

建议修法

recentTagsForCurrentLedgerProvider 在 Editor 分支下不要复用 filterTagsForLedger,改为:

  1. transaction_tag_overrides join 当前账本的 transactions,按 MAX(happened_at) 取最近 N 个 tag_sync_id
  2. shared_ledger_tags 把这些 syncId 映射成 synthetic Tag(与 filterTagsForLedger 用同一个 _sharedTagAsMain / syntheticIdForSyncId 口径,保证 ID 与「全部标签」区块一致,否则选中态会错位)
  3. 拿不到(mirror 未到齐等)就返回空列表,让「最近使用」区块自然隐藏 —— 现有代码已经有 recentTags.isEmpty → SizedBox.shrink() 的分支

个人账本 / Owner 分支保持现状不动。

备注

发现于 #436 的真机验证过程。该 PR 未改动 shared_ledger_picker_filter.dartrecentTagsForCurrentLedgerProvider 也原封未动,因此不是 #436 引入的,按最小改动原则单独跟进。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions